談一談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 轉載請保留本行資訊*************************