天天看點

VB.NET中圖像處理的一些技巧以及其和C#圖像處理的差距。

談一談VB.NET中圖像處理的快速實作,以及其和C#的速度差距分析。

  早期的時候我使用的開發工具是VB6,VB6做圖像處理的速度在我的軟體Imageshop中有所展現,還是算可以的。目前,我已經改用C#來研究圖像算法,C#中有指針,做圖像處理起來效率确實要高不少。VB.NET當初也用過不到半年的時間,在http://blog.csdn.net/laviewpbt/article/details/752003一文中我曾經對VB.NET圖像處理做了簡單的總結。今天就我掌握的情況,在對VB.NET的圖像處理做一個簡單的描述。

      首先,還是談談圖像像素時資料擷取方面吧,.net中的圖像相關類基本上都是基于GDI+的,是以,圖像資料的擷取其實也是調用GDI+的一些函數。這個函數就是LockBits,在vb.net中彩色圖像資料的快速擷取 一文中,我們是調用了Marshal.Copy把LockBits鎖定的記憶體資料拷貝到資料中,然後對數組中的值進行處理。這樣做主要的原因是VB.NET不好直接通路記憶體(Marshal.ReadByte之類的函數不适合用于大型的循環中)。那麼,這就造成了2個不好的事情,第一:在同一時間需要2倍于圖像資料量的記憶體,第二:記憶體資料拷貝到資料,以及處理後再把數組的資料拷貝會記憶體中都是會減低速度的。作為一種改進,我們應該充分利用LockBits的功能。LockBits中的LockMode中有一種模式為ImageLockMode.UserInputBuffer,該模式下需要使用者先申請記憶體,然後在把圖像資料按照相關格式填充如這個記憶體中。這樣,就可以先定義個數組,然後把圖像資料填充到這個數組中,就避免了來回拷貝的耗時了,簡單示例代碼如下:

Dim BmpData As New BitmapData
  Stride = ((Bmp.Width * 3 + 3) And &HFFFFFFFC)
  Dim PixleValue(Stride * Bmp.Height) As Byte
  Dim Hanlde As GCHandle = GCHandle.Alloc(PixleValue, GCHandleType.Pinned)
  BmpData.Scan0 = Hanlde.AddrOfPinnedObject()                                 '取得位元組數組的的第一個元素在記憶體中的位址,VB.NET沒有了VB6.0的VarPtr函數了
  BmpData.Stride = Stride                                                     'Stide這一個字段也必須實作填充,這個需要按照像素格式來計算大小,必須為4的倍數
  Bmp.LockBits(New Rectangle(0, 0, Bmp.Width, Bmp.Height), ImageLockMode.ReadWrite Or ImageLockMode.UserInputBuffer, PixelFormat.Format24bppRgb, BmpData)
  Hanlde.Free()          

  這種調用模式下,BitmapData對象的Scan0和Stride必須由使用者自行計算,其中Scan0為儲存解碼後的資料記憶體的位址。在VB.NET中擷取數組記憶體位址的代碼似乎比VB6複雜一些,這一點我也不是特别在行。

      調用上述代碼後,PixleValue就已經儲存了圖像的資料了。

      之後就是對圖像資料進行各種各樣的處理了。比如我們那前一段日子共享的色調均化的代碼為例:

For Y = 0 To Height - 1
            Speed = Y * Stride                          ' 定位到每個掃描行的第一個像素,以避免溶于資料的影響
            For X = 0 To Width - 1
                HistGram(PixleValue(Speed)) += 1        ' Blue
                HistGram(PixleValue(Speed + 1)) += 1    ' Green
                HistGram(PixleValue(Speed + 2)) += 1    ' Red     
                Speed += 3                              ' 移向下一個像素
            Next
        Next

        Num = 0
        For Y = 0 To 255
            Num = Num + HistGram(Y)         ' 計算映射表
            Lut(Y) = CByte(Math.Truncate(CSng(Num) / (Width * Height * 3) * 255))
        Next
        For Y = 0 To Height - 1
            Speed = Y * Stride
            For X = 0 To Width - 1
                PixleValue(Speed) = Lut(PixleValue(Speed))
                PixleValue(Speed + 1) = Lut(PixleValue(Speed + 1))
                PixleValue(Speed + 2) = Lut(PixleValue(Speed + 2))
                Speed += 3
            Next
        Next      

  執行速度比較:針對上述算法,我們隻比較算法的執行部分的耗時。

      測試語言            測試圖像(512*384)耗時      測試圖像(1024*768)耗時    測試圖像(4000*3000)耗時  

       VB.NET                7ms              25ms              178ms

        c# 指針        4ms                                  16ms              100ms

        c# 數組                     5ms                                  24ms              139ms

     上表中可以明顯看出指針在速度上還是有明顯的優勢的,唯一值得注意的是,VB.NET的數組版要比C#的數組版的速度要慢,由于VB.NET中我不知道怎麼樣檢視其對應的反彙編碼,是以我還不清楚這是為什麼。 

     上述三種方案的代碼下載下傳:https://files.cnblogs.com/Imageshop/HistgramEqualize%28VB.NETandCsharp%29.rar

     看來VB.NET确實不是圖像處理方案的首選工具啊。

 ***************************作者: laviewpbt   時間: 2013.4.07    聯系QQ:  33184777  轉載請保留本行資訊*************************

繼續閱讀