狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

在WPF中使用WriteableBitmap對接工業相機及常用操作

freeflydom
2024年9月7日 10:44 本文熱度 983

寫作背景

寫這篇文章主要是因為工業相機(海康、大恒等)提供的.NET開發文檔和示例程序都是用WinForm項目來說明的,而在WPF項目中對圖像的使用和處理與在WinForm項目中有很大不同。在WinForm中用System.Drawing.Bitmap來處理圖像,而在WPF中是用System.Windows.Media.Imaging.WriteableBitmap來處理圖像的。

本文的主要內容也是對WriteableBitmap類使用的介紹以及與使用Drawing.Bitmap的比較。

從相機中接收圖像

首先當然要創建一個WriteableBitmap,這里以PixelFormats.Bgr24像素格式舉例說明

PropertyInfo dpiXProperty = typeof(SystemParameters).GetProperty("DpiX", BindingFlags.NonPublic | BindingFlags.Static);

PropertyInfo dpiYProperty = typeof(SystemParameters).GetProperty("Dpi", BindingFlags.NonPublic | BindingFlags.Static);

int dpiX = (int)dpiXProperty.GetValue(null);

int dpiY = (int)dpiYProperty.GetValue(null);

WriteableBitmap WBitmap = new WriteableBitmap(PhotoWidth, PhotoHeight, dpiX, dpiY, PixelFormats.Bgr24, null);

雖然工業相機有多個品牌,但是獲取位圖像素數據的方式基本有兩種:

1、代表位圖像素地址的IntPtr作為相機SDK方法的參數,由SDK方法向該地址寫入像素數據。

2、相機SDK方法返回代表位圖像素地址的IntPtr。

針對第一種,將WBitmap.BackBuffer傳給SDK方法,BackBuffer代表的就是WriteableBitmap對象像素數據的地址。

針對第二種,使用

Int32Rect rect = new Int32Rect(0, 0, wbBitmap.PixelWidth, wbBitmap.PixelHeight);

wbBitmap.WritePixels(rect, ppixel, wbBitmap.PixelWidth * wbBitmap.PixelHeight * 3, wbBitmap.PixelWidth * 3);

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屬性即可。

WBitmap.Lock();

WBitmap.AddDirtyRect(new Int32Rect(0, 0, PhotoWidth, PhotoHeight));

WBitmap.Unlock();

MyImage.Source = WBitmap;

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)處的地址 ,所以完整的讀取像素值的代碼如下:

int offset = WBitmap.BackBufferStride * 200 + PixelFormats.Bgr24.BitsPerPixel / 8 * 100;

unsafe {

    byte* pb = (byte*)WBitmap.BackBuffer.ToPointer();

    byte cB = pb[offset];

    byte cG = pb[offset + 1];

    byte cR = pb[offset + 2];

}

或者使用System.Runtime.InteropServices.Marshal.ReadByte,不需要unsafe模式

byte cB = Marshal.ReadByte(WBitmap.BackBuffer, offset);

byte cG = Marshal.ReadByte(WBitmap.BackBuffer, offset+1);

byte cR = Marshal.ReadByte(WBitmap.BackBuffer, offset+2);

像素修改也是同樣的方法,把讀取變成賦值即可,或者用Marshal.WriteByte寫值。

2、使用WritePixels

WritePixels方法適合修改一個特定矩形內的像素。源像素數據通常來自另一個已生成的圖像的數據。WritePixels方法接受IntPtr類型(數據地址)或byte[]類型(數據內容)的值。可參考前面【從相機中接收圖像】的例子。

與Bitmap比較

使用Bitmap也有兩種方式操作像素。1:Bitmap提供GetPixel和SetPixel方法操作單個像素。2:調用LockBits方法獲得BitmapData對象,BitmapData對象的Scan0即像素數據地址。

圖像的保存

與Bitmap使用Save不同,WriteableBitmap需要使用Encoder編碼后才能保存成文件。

using(FileStream stream = new FileStream(@"C:\newu8.bmp", FileMode.Create)) {

    BmpBitmapEncoder encoder = new BmpBitmapEncoder();

    encoder.Frames.Add(BitmapFrame.Create(WBitmap));

    encoder.Save(stream);

}

這里使用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 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved