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

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

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

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

寫作背景

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

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

從相機中接收圖像

首先當(dāng)然要創(chuàng)建一個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);

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

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

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

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

針對第二種,使用

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

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

WritePixels方法是專門用來修改一個矩形區(qū)域中像素數(shù)據(jù)的方法,其中參數(shù)rect代表修改的區(qū)域,ppixel代表相機SDK方法返回的代表像素數(shù)據(jù)的地址。

與Bitmap比較

在WinForm中使用Bitmap則有兩種方式接收圖像。

針對第一種,使用Bitmap(int width, int height, PixelFormat format)創(chuàng)建Bitmap,然后調(diào)用LockBits方法獲得BitmapData對象,BitmapData的scan0屬性表示圖像像素數(shù)據(jù)地址。

針對第二種,在創(chuàng)建Bitmap時使用Bitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0)構(gòu)造函數(shù),將ppixel作為scan0的值傳入。

圖像的顯示

WriteableBitmap使用兩個緩沖區(qū),一個后端緩沖區(qū)和一個前端緩沖區(qū)(后端緩沖區(qū)用來處理圖像像素數(shù)據(jù),前端緩沖區(qū)用來顯示圖像),所以一個WriteableBitmap對象存著圖像的兩份數(shù)據(jù)。

如果在【從相機中接收圖像】中使用第一種方式創(chuàng)建WriteableBitmap,那么圖像數(shù)據(jù)存在后端緩沖區(qū)中(BackBuffer),而界面上Image控件顯示圖像用的是前端緩沖區(qū)中的圖像。

所以現(xiàn)在我們需要把后端緩沖區(qū)中的數(shù)據(jù)更新到前端緩沖區(qū)中去,然后傳給Image的Source屬性即可。

WBitmap.Lock();

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

WBitmap.Unlock();

MyImage.Source = WBitmap;

Lock鎖定后端緩沖區(qū),AddDirtyRect將后端緩沖區(qū)數(shù)據(jù)更新到前端緩沖區(qū),Unlock解鎖后端緩沖區(qū)。AddDirtyRect的使用模式是固定的,都是先Lock然后Unlock。

如果在前面【從相機中接收圖像】使用的是方式二WritePixels方法,則在圖像顯示時只需要MyImage.Source = WBitmap即可,因為WritePixels的內(nèi)部已經(jīng)調(diào)用了AddDirtyRect方法。

與Bitmap比較

WinForm中使用PictureBox控件顯示圖像。使用方法是:

Image showImage= Image.FromHbitmap(bitmap.GetHbitmap());

MyPictureBox.Image = showImage;

像素操作

WriteableBitmap中的像素操作有兩種方式

1、使用像素地址

該方式涉及到代表像素地址的指針。在前面【從相機中接收圖像】中方式一提到用一個指針地址去接受圖像,

所以圖像的所有像素數(shù)據(jù)都保存在這個起始地址的內(nèi)存中,也就是后端緩沖區(qū)中。WBitmap.BackBuffer指向的就是坐標(biāo)(0,0)點的像素數(shù)據(jù)。

下面以讀取(100,200)坐標(biāo)點的像素數(shù)據(jù)舉例說明,先介紹要用到的兩個屬性:WBitmap.BackBufferStride表示一行圖像數(shù)據(jù)的字節(jié)數(shù),WBitmap.Format.BitsPerPixel表示一個像素的位數(shù)。

首先計算(100,200)處的偏移量應(yīng)該是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方法適合修改一個特定矩形內(nèi)的像素。源像素數(shù)據(jù)通常來自另一個已生成的圖像的數(shù)據(jù)。WritePixels方法接受IntPtr類型(數(shù)據(jù)地址)或byte[]類型(數(shù)據(jù)內(nèi)容)的值。可參考前面【從相機中接收圖像】的例子。

與Bitmap比較

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

圖像的保存

與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圖像,要保存成其他格式則使用對應(yīng)的編碼器即可,如JpegBitmapEncoder等。

與Bitmap比較

調(diào)用Save方法即可。

注意事項

1:工業(yè)相機的開發(fā)也可以查看C/C++版本的開發(fā)文檔,C#可以使用DllImport調(diào)用C/C++版SDK中的函數(shù)。

2:使用工業(yè)相機采圖一般都是使用回調(diào)函數(shù)的形式,所以在回調(diào)函數(shù)的多線程環(huán)境中要注意跨線程訪問資源的問題。

3:圖像保存用的是后端緩沖區(qū)中的數(shù)據(jù)(再次證明前端緩沖區(qū)只是用來在界面上展示的)。

作者:左眼水星

轉(zhuǎn)載請注明原文鏈接:https://www.cnblogs.com/yxllxy/p/18269391



該文章在 2024/9/7 10:45:58 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved