在WPF中使用WriteableBitmap對接工業相機及常用操作
當前位置:點晴教程→知識管理交流
→『 技術文檔交流 』
寫作背景寫這篇文章主要是因為工業相機(海康、大恒等)提供的.NET開發文檔和示例程序都是用WinForm項目來說明的,而在WPF項目中對圖像的使用和處理與在WinForm項目中有很大不同。在WinForm中用System.Drawing.Bitmap來處理圖像,而在WPF中是用System.Windows.Media.Imaging.WriteableBitmap來處理圖像的。 本文的主要內容也是對WriteableBitmap類使用的介紹以及與使用Drawing.Bitmap的比較。 從相機中接收圖像首先當然要創建一個WriteableBitmap,這里以PixelFormats.Bgr24像素格式舉例說明
雖然工業相機有多個品牌,但是獲取位圖像素數據的方式基本有兩種: 1、代表位圖像素地址的IntPtr作為相機SDK方法的參數,由SDK方法向該地址寫入像素數據。 2、相機SDK方法返回代表位圖像素地址的IntPtr。 針對第一種,將WBitmap.BackBuffer傳給SDK方法,BackBuffer代表的就是WriteableBitmap對象像素數據的地址。 針對第二種,使用
WritePixels方法是專門用來修改一個矩形區域中像素數據的方法,其中參數rect代表修改的區域,ppixel代表相機SDK方法返回的代表像素數據的地址。 與Bitmap比較 在WinForm中使用Bitmap則有兩種方式接收圖像。 針對第一種,使用Bitmap(int width, int height, PixelFormat format)創建Bitmap,然后調用LockBits方法獲得BitmapData對象,BitmapData的scan0屬性表示圖像像素數據地址。 針對第二種,在創建Bitmap時使用Bitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0)構造函數,將ppixel作為scan0的值傳入。 圖像的顯示WriteableBitmap使用兩個緩沖區,一個后端緩沖區和一個前端緩沖區(后端緩沖區用來處理圖像像素數據,前端緩沖區用來顯示圖像),所以一個WriteableBitmap對象存著圖像的兩份數據。 如果在【從相機中接收圖像】中使用第一種方式創建WriteableBitmap,那么圖像數據存在后端緩沖區中(BackBuffer),而界面上Image控件顯示圖像用的是前端緩沖區中的圖像。 所以現在我們需要把后端緩沖區中的數據更新到前端緩沖區中去,然后傳給Image的Source屬性即可。
Lock鎖定后端緩沖區,AddDirtyRect將后端緩沖區數據更新到前端緩沖區,Unlock解鎖后端緩沖區。AddDirtyRect的使用模式是固定的,都是先Lock然后Unlock。 如果在前面【從相機中接收圖像】使用的是方式二WritePixels方法,則在圖像顯示時只需要MyImage.Source = WBitmap即可,因為WritePixels的內部已經調用了AddDirtyRect方法。 與Bitmap比較 WinForm中使用PictureBox控件顯示圖像。使用方法是: Image showImage= Image.FromHbitmap(bitmap.GetHbitmap()); MyPictureBox.Image = showImage; 像素操作WriteableBitmap中的像素操作有兩種方式 1、使用像素地址 該方式涉及到代表像素地址的指針。在前面【從相機中接收圖像】中方式一提到用一個指針地址去接受圖像, 所以圖像的所有像素數據都保存在這個起始地址的內存中,也就是后端緩沖區中。WBitmap.BackBuffer指向的就是坐標(0,0)點的像素數據。 下面以讀取(100,200)坐標點的像素數據舉例說明,先介紹要用到的兩個屬性:WBitmap.BackBufferStride表示一行圖像數據的字節數,WBitmap.Format.BitsPerPixel表示一個像素的位數。 首先計算(100,200)處的偏移量應該是WBitmap.BackBufferStride*200 + WBitmap.Format.BitsPerPixel / 8*100,那么BackBuffer加上偏移量就是(100,200)處的地址 ,所以完整的讀取像素值的代碼如下:
或者使用System.Runtime.InteropServices.Marshal.ReadByte,不需要unsafe模式
像素修改也是同樣的方法,把讀取變成賦值即可,或者用Marshal.WriteByte寫值。 2、使用WritePixels WritePixels方法適合修改一個特定矩形內的像素。源像素數據通常來自另一個已生成的圖像的數據。WritePixels方法接受IntPtr類型(數據地址)或byte[]類型(數據內容)的值。可參考前面【從相機中接收圖像】的例子。 與Bitmap比較 使用Bitmap也有兩種方式操作像素。1:Bitmap提供GetPixel和SetPixel方法操作單個像素。2:調用LockBits方法獲得BitmapData對象,BitmapData對象的Scan0即像素數據地址。 圖像的保存與Bitmap使用Save不同,WriteableBitmap需要使用Encoder編碼后才能保存成文件。
這里使用BmpBitmapEncoder編碼器來保存bmp圖像,要保存成其他格式則使用對應的編碼器即可,如JpegBitmapEncoder等。 與Bitmap比較 調用Save方法即可。 注意事項1:工業相機的開發也可以查看C/C++版本的開發文檔,C#可以使用DllImport調用C/C++版SDK中的函數。 2:使用工業相機采圖一般都是使用回調函數的形式,所以在回調函數的多線程環境中要注意跨線程訪問資源的問題。 3:圖像保存用的是后端緩沖區中的數據(再次證明前端緩沖區只是用來在界面上展示的)。 作者:左眼水星 轉載請注明原文鏈接:https://www.cnblogs.com/yxllxy/p/18269391 該文章在 2024/9/7 10:45:58 編輯過 |
關鍵字查詢
相關文章
正在查詢... |