在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 编辑过 |
关键字查询
相关文章
正在查询... |