Baumer工业相机堡盟工业相机如何通过BGAPI SDK直接实现Mono16位深度的图像保存(C#)

news/2024/4/25 23:38:35/文章来源:https://blog.csdn.net/xianzuzhicai/article/details/130354760

Baumer工业相机堡盟工业相机如何通过BGAPI SDK直接实现Mono16位深度的图像保存(C#)

  • Baumer工业相机
  • Baumer工业相机保存位深度12/16位图像的技术背景
  • 代码案例分享
    • 1:引用合适的类文件
    • 2:通过BGAPI SDK直接保存Mono12/16图像
    • 3:使用BGAPI SDK的图像直接转换Mono12/16图像并保存的功能
  • 工业相机使用位深度12/16位图像的优点
  • 工业相机使用位深度12/16位图像的行业应用

Baumer工业相机

Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。

Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度可扩展性等特点。

Baumer工业相机通过使用BGAPI SDK进行开发时,在C++环境可以直接实现位深度为16的图像保存。

Baumer工业相机保存位深度12/16位图像的技术背景

工业相机通常用于需要高质量图像的分析和检查的专业环境中。这些相机被设计用来捕捉16比特的高比特深度的图像,与低比特深度的图像相比,可以捕捉到更大范围的色彩和细节。

保存位深16位图像的工业相机的技术背景涉及几个关键部分。首先,相机的图像传感器必须能够捕捉到高比特深度的图像。这是通过使用高质量的图像传感器来实现的,该传感器能够以每像素16比特的分辨率捕获数据。

其次,相机的电子设备必须能够处理和存储高比特深度的图像数据。这意味着相机需要有一个高速处理器和足够的内存来处理所产生的大量图像数据。

第三,相机的软件必须能够支持16位图像的保存。这意味着相机的固件和软件接口必须被设计成能够处理16位图像所产生的更大的文件尺寸,并且还能与工业标准文件格式如TIFF和RAW兼容。

总的来说,保存16位深度图像的工业相机的技术背景涉及高质量的图像传感器、强大的电子器件和专门的软件的组合,这些都是为了处理捕捉和存储高位深度图像的独特需求。

这里主要描述如何在C#的平台下通过BGAPI SDK直接实现Mono16图像格式的保存功能的核心代码

代码案例分享

本文介绍使用BGAPI SDK对Baumer的工业相机进行开发时,直接实现Mono12或者Mono16图像格式的保存功能

如下为核心代码实现步骤:

1:引用合适的类文件

C#环境下核心代码如下所示:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
using CSCameraDemo.Properties;
using System.Globalization;
using WindowsFormsApplication1;
using System.Threading.Tasks;
using System.Threading;
using System.Drawing.Imaging;using BGAPI2;

2:通过BGAPI SDK直接保存Mono12/16图像

下面为在在C#环境开启相机连接相机后通过转换图像格式实现Mono12或者Mono16图像格式保存的核心代码。

如下所示:

SystemList 
Open a System 
Get the InterfaceList and fill it Open an Interface 
Get the DeviceList and fill it 
Open a Devicevoid mDataStream_NewBufferEvent(object sender, BGAPI2.Events.NewBufferEventArgs mDSEvent)
{try{BGAPI2.Buffer mBufferFilled = null;              mBufferFilled = mDSEvent.BufferObj;if (mBufferFilled == null){MessageBox.Show("Error: Buffer Timeout after 1000 ms!");}else if (mBufferFilled.IsIncomplete == true){//MessageBox.Show("Error: Image is incomplete!");//queue buffer againmBufferFilled.QueueBuffer();}else{#region//获取当前FrameIDFrameIDInt = (int)mBufferFilled.FrameID;OnNotifySetFrameID(FrameIDInt.ToString());#endregion//将相机内部图像内存数据转为bitmap数据System.Drawing.Bitmap bitmap  = new System.Drawing.Bitmap((int)mBufferFilled.Width, (int)mBufferFilled.Height, (int)mBufferFilled.Width,System.Drawing.Imaging.PixelFormat.Format8bppIndexed, (IntPtr)((ulong)mBufferFilled.MemPtr + mBufferFilled.ImageOffset));#region//Mono图像数据转换。彩色图像数据转换于此不同System.Drawing.Imaging.ColorPalette palette = bitmap.Palette;int nColors = 256;for (int ix = 0; ix < nColors; ix++){uint Alpha = 0xFF;uint Intensity = (uint)(ix * 0xFF / (nColors - 1));palette.Entries[ix] = System.Drawing.Color.FromArgb((int)Alpha, (int)Intensity, (int)Intensity, (int)Intensity);}bitmap.Palette = palette;#endregionlong currenttime = (long)mBufferFilled.Timestamp;                   DateTime sdasd = GetTime(currenttime, true);#region//回调函数保存图像功能if (bSaveImg){//使用bitmap自带函数保存string strtime = DateTime.Now.ToString("yyyyMMddhhmmssfff");string saveimagepath = pImgFileDir  +"\\"+ strtime + ".jpg";// bitmap.Save(saveimagepath, System.Drawing.Imaging.ImageFormat.Bmp);//使用opencv进行保存图像if (mBufferFilled.PixelFormat == "Mono8"){OpenCvSharp.Mat matgray = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);//用bitmap转换为mat                           matgray.SaveImage("opencv_image.png");Cv2.ImWrite("opencvcv_image_Clone.png", matgray);Cv2.ImWrite(saveimagepath, matgray);}                      //将相机中原始图像数据通过BGAPI SDK直接保存为16位深度的图像if (mBufferFilled.PixelFormat.Contains("Mono12")){short[] mImageBuffer16Copy = new short[(uint)((uint)mBufferFilled.Width * (uint)mBufferFilled.Height * 1)];Marshal.Copy((IntPtr)mBufferFilled.MemPtr, mImageBuffer16Copy, 0, (int)((int)mBufferFilled.Width * (int)mBufferFilled.Height * 1));//convert Mono12 to Mono16uint length = (uint)((uint)mBufferFilled.Width * (uint)mBufferFilled.Height) * 1;for (uint l = 0; l < length; l++){mImageBuffer16Copy[l] = (short)(mImageBuffer16Copy[l] << 4);}saveimagepath = pImgFileDir + "\\" + strtime + "-Mono16.png";saveMono16Tiff(saveimagepath , mImageBuffer16Copy, (int)mBufferFilled.Width, (int)mBufferFilled.Height * 1);}bSaveImg = false;//变量控制单次保存图像}#endregion#region//bitmap的图像数据复制pBitmapBitmap clonebitmap = (Bitmap)bitmap.Clone();BitmapData data = clonebitmap.LockBits(new Rectangle(0, 0, clonebitmap.Width, clonebitmap.Height), ImageLockMode.ReadOnly, clonebitmap.PixelFormat);clonebitmap.UnlockBits(data);pBitmap = clonebitmap;#endregion#region//将pBitmap图像数据显示在UI界面PictureBox控件上prcSource.X = 0;prcSource.Y = 0;prcSource.Width = (int)mBufferFilled.Width;prcSource.Height = (int)mBufferFilled.Height;System.Drawing.Graphics graph = System.Drawing.Graphics.FromHwnd(pictureBoxA.Handle);graph.DrawImage(pBitmap, prcPBox, prcSource, GraphicsUnit.Pixel);#endregionclonebitmap.Dispose(); //清除临时变量clonebitmap所占内存空间mBufferFilled.QueueBuffer();}}catch (BGAPI2.Exceptions.IException ex){{string str2;str2 = string.Format("ExceptionType:{0}! ErrorDescription:{1} in function:{2}", ex.GetType(), ex.GetErrorDescription(), ex.GetFunctionName());MessageBox.Show(str2);}}return;
}

3:使用BGAPI SDK的图像直接转换Mono12/16图像并保存的功能

下面为在在C#环境开启相机连接相机后通过BGAPI SDK直接实现Mono12或者Mono16图像格式保存的核心代码。

如下所示:

public static void saveMono16Tiff(string fileName, short[] shortarray, int imagewidth, int imageheight)
{FileStream FileST = new FileStream(fileName, FileMode.Create);// Create the writer for data.BinaryWriter binWriter = new BinaryWriter(FileST);// Write data to Test.data.ushort data16 = 0;uint data32 = 0;uint sizeX = (uint)imagewidth;uint sizeY = (uint)imageheight;int imagelength2 = imagewidth * imageheight;// TIFF identifier and count of directory entries//================================================data16 = 0x4949;	// identifier "II" for little-endian byte orderbinWriter.Write(data16);data16 = 42;		// tiff identifier 42binWriter.Write(data16);data32 = 8;			// offset for the first IFDbinWriter.Write(data32);data16 = 12;		// number of directory entriesbinWriter.Write(data16);// 1. entry: ImageWidth (number of columns)//==========================================data16 = 0x100;		// tag:   100.HbinWriter.Write(data16);data16 = 4;			// type:  LONGbinWriter.Write(data16);data32 = 1;			// count: 1binWriter.Write(data32);data32 = sizeX;		// value: horizontal image sizebinWriter.Write(data32);// 2. entry: ImageLength (number of rows)//=======================================data16 = 0x101;		// tag:   101.H binWriter.Write(data16);data16 = 4;			// type:  LONGbinWriter.Write(data16);data32 = 1;			// count: 1binWriter.Write(data32);data32 = sizeY;		// value: horizontal image sizebinWriter.Write(data32);// 3. entry: BitsPerSample//=========================data16 = 0x102;		// tag:   102.H binWriter.Write(data16);data16 = 3;			// type:  SHORTbinWriter.Write(data16);data32 = 1;			// count: 1 == SamplesPerPixel Mono16binWriter.Write(data32);data32 = 16;		 // SamplesPerPixel == 1 => value: 16    (16 bps => NOT BASELINE!)binWriter.Write(data32);// 4. entry: Compression//=======================data16 = 0x103;		// tag:   103.H binWriter.Write(data16);data16 = 3;			// type:  SHORTbinWriter.Write(data16);data32 = 1;			// count: 1 binWriter.Write(data32);data32 = 1;			// value: 1 (no compression)binWriter.Write(data32);// 5. entry: PhotometricInterpretation//======================================data16 = 0x106;		// tag:   106.H binWriter.Write(data16);data16 = 3;			// type:  SHORTbinWriter.Write(data16);data32 = 1;			// count: 1 binWriter.Write(data32);data32 = 1;			// SamplesPerPixel == 1 => value: 1 (BlackIsZero)binWriter.Write(data32);// 6. entry: StripOffsets//========================data16 = 0x111;		// tag:   111.H binWriter.Write(data16);data16 = 4;			// type:  LONGbinWriter.Write(data16);data32 = 1;			// count: 1 == StripsPerImagebinWriter.Write(data32);data32 = 174;		// value = 8 + 2 + 12*12 + 4 + 8 + 8 = 174binWriter.Write(data32);// 7. entry: SamplesPerPixel//===========================data16 = 0x115;		// tag:   115.H binWriter.Write(data16);data16 = 3;			// type:  SHORTbinWriter.Write(data16);data32 = 1;			// count: 1 binWriter.Write(data32); ;data32 = 1;			// SamplesPerPixel == 1 Mono16binWriter.Write(data32);// 8. entry: RowsPerStrip//========================data16 = 0x116;		// tag:   116.H binWriter.Write(data16);data16 = 4;			// type:  LONGbinWriter.Write(data16);data32 = 1;			// count: 1binWriter.Write(data32);data32 = sizeY;		// value: vertical image size (one strip only)binWriter.Write(data32);// 9. entry: StripByteCounts (For each strip, the number of bytes in the strip after compression.)//================================================================================================data16 = 0x117;		// tag:   117.H binWriter.Write(data16);data16 = 4;			// type:  LONGbinWriter.Write(data16);data32 = 1;			// count: 1 == StripsPerImagebinWriter.Write(data32);data32 = 2 * 1 * sizeX * sizeY;		// value = 2* 1 * SizeX * SizeYbinWriter.Write(data32);// 10. entry: XResolution (The number of pixels per ResolutionUnit in the ImageWidth direction.)//================================================================================================data16 = 0x11A;		// tag:   11A.H binWriter.Write(data16);data16 = 5;			// type:  RATIONALbinWriter.Write(data16);data32 = 1;			// count: 1 binWriter.Write(data32);data32 = 158;		// offset to value = 8 + (2 + 12*12 + 4) = 158binWriter.Write(data32);// 11. entry: YResolution (The number of pixels per ResolutionUnit in the ImageLength direction.)//================================================================================================data16 = 0x11B;		// tag:   11B.H binWriter.Write(data16);data16 = 5;			// type:  RATIONALbinWriter.Write(data16);data32 = 1;			// count: 1 binWriter.Write(data32);data32 = 166;		// offset to value = 8 + (2 + 12*12 + 4) + 8 = 166binWriter.Write(data32);// 12. entry: ResolutionUnit (The unit of measurement for XResolution and YResolution.)//=====================================================================================data16 = 0x128;		// tag:   128.H binWriter.Write(data16);data16 = 3;			// type:  SHORTbinWriter.Write(data16);data32 = 1;			// count: 1 binWriter.Write(data32);data32 = 2;			// value: 2 (Inch) => dpibinWriter.Write(data32);data32 = 0;			// offset of next IFD: nonebinWriter.Write(data32);//  write IFD values longer than 4 byte//======================================data32 = 72;		// XResolution numerator: 72 => 72 dpi (a common value..)binWriter.Write(data32);data32 = 1;			// XResolution denominator: 1binWriter.Write(data32);data32 = 72;		// YResolution numerator: 72 => 72 dpi (a common value..)binWriter.Write(data32);data32 = 1;			// YResolution denominator: 1binWriter.Write(data32);// end of header save to file// save image data (converted from Mono12 to Mono16) to filefor (int i = 0; i < imagelength2; i++){data16 = (ushort)shortarray[i];binWriter.Write(data16);}// close filebinWriter.Close();FileST.Close();return;}   // end of saveMono16Tiff()

工业相机使用位深度12/16位图像的优点

更好的图像细节:12/16位图像可以捕捉到更多的细节和颜色深度,提供更高的图像质量。

更广泛的动态范围:12/16位图像允许在明暗变化很大的场景中捕捉到更多的细节和颜色,以及更好的光线控制。

更低的噪声:采用12/16位图像可以减少噪声,使得图像更加清晰。

更好的后期处理:12/16位图像可以在后期处理中更灵活地进行平滑、增加对比度和其他调整。

因此,工业相机使用12/16位图像可以提供更高质量的图像,更好的细节和颜色控制,并为后期处理提供更多的灵活性。

工业相机使用位深度12/16位图像的行业应用

  1. 医疗成像:工业相机可用于各种医疗成像应用,例如X射线成像,MRI和CT扫描。这些应用需要16位图像位深度来提供高质量的成像结果。

  2. 汽车制造:工业相机可以用于汽车制造中的各种应用,例如质量控制和检查。这些应用需要高分辨率和16位图像位深度,以检测并处理微小的缺陷或问题。

  3. 机器人视觉:工业相机的高速度和高精度对于机器人视觉应用非常重要。机器人需要能够识别和定位目标,同时能够处理16位图像位深度的高质量图像。

  4. 智能交通系统:工业相机也可以用于智能交通系统中。例如,交通监控摄像机需要高质量的图像以便能够识别和跟踪车辆,行人和其他交通标志。

总之,工业相机使用16位图像位深度的行业应用范围非常广泛,它们可以用于各种不同的应用,以提供高质量的成像结果和精确的图像处理功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_103641.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv5网络模型的结构原理讲解(全)

目录 前言1. 基本概念2. 输入端2.1 Mosaic 图像增强2.2 自适应锚框计算2.3 自适应图片缩放 3. Backbone层3.1 Focus结构3.2 CSP结构 3. Neck网络3.1 SPP结构3.2 PAN结构 4. 输出端4.1 Bounding box损失函数4.2 NMS非极大值抑制 前言 YOLOv5有几种不同的架构&#xff0c;各网络…

Qt信号槽原理

Qt之信号槽原理 一.概述 所谓信号槽&#xff0c;实际就是观察者模式。当某个事件发生之后&#xff0c;比如&#xff0c;按钮检测到自己被点击了一下&#xff0c;它就会发出一个信号&#xff08;signal&#xff09;。这种发出是没有目的的&#xff0c;类似广播。如果有对象对这…

Openswan安装和简单配置

Openswan安装和简单配置 安装环境&#xff1a; 操作系统&#xff1a;Ubuntu20.0.4TLS 用户权限&#xff1a;root下载Openswan: wget https://github.com/xelerance/Openswan/archive/refs/tags/v3.0.0.zip安装Openswan: 解压Openswan&#xff1a;&#xff08;PS&#xff1a…

银行数字化转型导师坚鹏:商业银行数字化风控(2天)

商业银行数字化风控 课程背景&#xff1a; 数字化背景下&#xff0c;很多银行存在以下问题&#xff1a; 不清楚商业银行数字化风控发展现状&#xff1f; 不清楚对公业务数字化风控工作如何开展&#xff1f; 不知道零售业务数字化风控工作如何开展&#xff1f; 课程特色…

海光信息业绩高歌猛进,但其作为国产CPU龙头的“地基”并不牢固

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 在“芯片寒冬”的大背景下&#xff0c;2022年全球头部芯片半导体公司纷纷下调业绩预期&#xff0c;英特尔、英伟达、美光等无一幸免。但是随着AIGC异军突起&#xff0c;仿佛寒冬中的一股暖流&#xff0c;催生着半导体市场行…

C. Trailing Loves (or L‘oeufs?)(求某个质因子在n的阶乘中的个数 + 思维)

Problem - C - Codeforces Aki喜欢数字&#xff0c;尤其是那些带有尾随零的数字。例如&#xff0c;数字9200有两个尾随零。Aki认为数字拥有的尾随零越多&#xff0c;它就越漂亮。 然而&#xff0c;Aki认为&#xff0c;一个数字拥有的尾随零的数量并不是固定的&#xff0c;而是…

idea中导入spring源码;在spring源码中添加注释

标题&#xff1a;idea中导入spring源码;在spring源码中添加注释 我是跟着他操作的&#xff0c;下文是一些补充说明&#xff1a; 这个也可以借鉴 gradle下载链接【使用网盘下载】,不过有的没有&#xff0c; gradel下载链接&#xff1a;这个比较全 1.Spring源码编译环境 spr…

Karl Guttag:现有Micro LED/LCoS+光波导AR眼镜对比解析

轻量化是未来AR眼镜的发展趋势&#xff0c;为了缩减尺寸&#xff0c;AR眼镜厂商尝试了多种方案&#xff0c;长期来看Micro LED光机在小型化上更有优势&#xff0c;但现阶段LCoS光机的图像表现更好。在CES 2023期间&#xff0c;DigiLens、Lumus、Vuzix、OPPO、Avegant也展出了不…

linux编译安装python的全过程,pip python不与linux系统环境混乱

因为使用要求&#xff0c;使得我需要在linux环境下安装一个独立的python环境&#xff0c;不干扰其他环境。 预安装 在安装python之前&#xff0c;请在linux系统下安装下面这些包&#xff1a; sudo apt-get install namelibssl-dev libcurl4 libcurl4-openssl-dev zlib-devel…

27-Servlet执行原理

目录 1.Tomcat详解 ①接收请求&#xff1a; ②根据请求计算响应&#xff1a; ③返回响应&#xff1a; 2.Tomcat执行流程 2.1.Tomcat 初始化流程 2.2.Tomcat 处理请求流程 2.3.Servlet 的 service 方法的实现 在 Servlet 的代码中并没有写 main ⽅法&#xff0c;那么对应…

【C++关联容器】map的成员函数

目录 map 1. 构造、析构和赋值运算符重载 1.1 构造函数 1.2 析构函数 1.3 赋值运算符重载 2. 迭代器 3. 容量 4. 元素访问 5. 修改器 6. 观察者 7. 操作 8. 分配器 map map是关联容器&#xff0c;它按照特定的顺序存储由关键字值和映射值的组合形成的元素。 在一…

【Springboot系列】项目启动时怎么给mongo表加自动过期索引

1、前言 在之前操作mongo的过程中&#xff0c;都是自动创建&#xff0c;几乎没有手动创建过表。 这次开发中有张表数据量大&#xff0c;并且不是特别重要&#xff0c;数据表维护一个常见的问题是过期数据没有被及时清理&#xff0c;导致数据量过大&#xff0c;查询变得缓慢。…

LeetCode-242. 有效的字母异位词

题目链接 LeetCode-242. 有效的字母异位词 题目描述 题解 题解一&#xff08;Java&#xff09; 作者&#xff1a;仲景 首先&#xff0c;满足条件的情况下&#xff0c;两个字符串的长度一定是相等的&#xff0c;不相等一定不满足条件 使用Hash表来存储字符串s中各个字符出现的…

Spring Security实战(九)—— 使用Spring Security OAuth实现OAuth对接

一、OAuth2.0介绍 OAuth2.0是一种授权协议&#xff0c;允许用户授权第三方应用程序代表他们获取受保护的资源&#xff0c;如个人信息或照片等。它允许用户授权访问他们存储在另一个服务提供商上的资源&#xff0c;而无需将其凭据共享给第三方应用程序。OAuth2.0协议建立在OAuth…

【具体到每一步】从0制作一个uniapp的新闻类页面(界面篇)

目录 项目初始化 / 基础配置 项目创建 配置路由/页面/tabbar pages.json配置tabbar 配置图标/静态资源 导航栏和字体颜色 scroll-view实现横向滚动条样式 公共模块定义components组件 新建组件 使用组件 组件里的结构 布局个人中心页面 组件差异化处理 数据传递 导航…

DevExpress:报表在winform窗体上显示(使用documentViewer控件)

一&#xff1a;控件认识 documentViewer&#xff08;版本DX22.2&#xff09;,老版本中的可能是printControl&#xff08;工具箱面板中可能找不到&#xff09;&#xff0c;通过官网搜索发现&#xff0c;这个控件现在继承于documentViewer这个控件。因此&#xff0c;使用documen…

Unity入门(一)

Unity Unity是一套完善体系与编辑器的跨平台游戏开发工具&#xff0c;也可以称之为游戏引擎。游戏引擎是指一些编写好的可以重复利用的代码与开发游戏所用的各功能编辑器。 基于C#编程&#xff0c;易上手&#xff0c;高安全性独特的面向组件游戏开发思想让游戏开发更加简单易…

【神经网络】tensorflow实验7--回归问题

1. 实验目的 ①掌握一元线性回归模型的实现方法 ②掌握多元线性回归模型的实现方法 ③掌握三维数据可视化方法 2. 实验内容 ①使用TensorFlow建立一元线性回归模型&#xff0c;使用商品房销售数据训练模型&#xff0c;并使用训练好的模型预测房价 ②使用TensorFlow建立多元线…

十、ElasticSearch 实战 - 源码运行

一、概述 想深入理解 Elasticsearch&#xff0c;了解其报错机制&#xff0c;并有针对性的调整参数&#xff0c;阅读其源码是很有必要的。此外&#xff0c;了解优秀开源项目的代码架构&#xff0c;能够提高个人的代码架构能力 阅读 Elasticsearch 源码的第一步是搭建调试环境&…

思维导图从入门到大神

思维导图怎么做&#xff1f;思维导图是一种发散性思维的图。在我们生活的方方面面都有运用。无论是工作、学习、还是生活&#xff0c;我们都可以用到它。那思维导图是怎么绘制的呢&#xff1f;其实非常简单&#xff0c;只要这简单的几步 1、首先在绘制思维导图前&#xff0c;我…