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中我不知道怎么樣查看其對應的反匯編碼,所以我還不清楚這是為什么。 

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

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

 

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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM