Baumer工业相机堡盟工业相机如何联合BGAPI SDK和OpenCVSharp合并偏振相机4个角度的图像并显示(C#)
- Baumer工业相机
- Baumer工业相机偏振相机的技术背景
- 代码案例分享
- 1:引用合适的类文件
- 2:回调函数里联合BGAPI SDK和OpenCVSharp合并偏振相机4个角度的图像
- 3:OpenCVSharp合并偏振相机4个角度的图像的功能
- Baumer工业偏振相机获取多角度偏振图像的优点
- Baumer工业偏振相机获取多角度偏振图像的行业应用
Baumer工业相机
Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。
Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度可扩展性等特点。
Baumer工业相机的BGAPI SDK给新型偏振相机提供了测量所获图像的强度和偏振的能力。因此,它能够在应用程序中利用偏振信息。本应用说明描述了如何同时获得偏振相机4个角度图像数据并进行转换和显示的功能。
Baumer工业相机的偏振功能的详细介绍应用可以参考下面的技术博客,本文介绍如何同时获取4个角度偏振数据的功能:
Baumer工业相机堡盟相机如何使用偏振功能(偏振相机优点和行业应用)(C++)
如何使用ADOLP的偏振图像数据进行显示的技术博客:
Baumer工业相机堡盟工业相机如何通过BGAPISDK转换和显示偏振相机的图像(C#)
如何使用BGAPISDK同时获取四个角度图像的技术博客:
Baumer工业相机堡盟工业相机如何通过BGAPI SDK获取偏振相机4个角度的图像转换和显示(C#)
Baumer工业相机偏振相机的技术背景
工业相机中的偏振相机是基于偏振光原理实现的。偏振光是指在光的传播过程中,光的振动方向只在一个特定平面内振荡的光,与之相对的光称为自然光。偏振相机通过使用偏振片或偏振镜来控制光线的振动方向,使得只有具有特定偏振方向的光线经过相机镜头,从而达到特定的筛选或测量功能。
偏振相机在工业品质检测、医学诊断、材料分析等领域有着广泛的应用。例如,在工业品质检测中,偏振相机可以检测材料的应力分布、表面缺陷等信息,从而确定产品的质量;在医学诊断中,偏振相机可以用于检测组织和染色质等生物样本的材料学特征;在材料分析中,偏振相机可以用于检测材料中的畸变和裂缝等缺陷。
总的来说,偏振相机在工业自动化和科学研究等领域中具有重要的应用价值,可以实现快速、准确、高效的检测和分析。
Baumer工业相机中的偏振相机是基于索尼IMC250MZR传感器的。该传感器涂有一层金属网,可以过滤4个相邻像素的偏振信息。偏振角度被过滤以0°、45°、90°、135°的方式排列。
这里主要描述如何在C#的平台下联合BGAPI SDK和OpenCVSharp合并偏振相机4个角度的图像并显示的核心代码
代码案例分享
本文介绍使用BGAPI SDK对Baumer的工业相机进行开发时,合并偏振相机4个角度的图像并显示的功能
如下为核心代码实现步骤:
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;
using OpenCvSharp;
using OpenCvSharp.Dnn;
2:回调函数里联合BGAPI SDK和OpenCVSharp合并偏振相机4个角度的图像
下面为在在C#环境开启相机连接相机后联合BGAPI SDK和OpenCVSharp合并偏振相机4个角度的图像的核心代码。
如下所示:
SystemList
Open a System
Get the InterfaceList and fill it Open an Interface
Get the DeviceList and fill it
Open a Device
void mDataStream_NewBufferEvent(object sender, BGAPI2.Events.NewBufferEventArgs mDSEvent)
{
try
{
BGAPI2.Image imagePolarized = null;
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 again
mBufferFilled.QueueBuffer();
}
else
{
#region//获取当前FrameID
FrameIDInt = (int)mBufferFilled.FrameID;
OnNotifySetFrameID(FrameIDInt.ToString());
#endregion
uint width = (uint)(mBufferFilled.Width);
uint height = (uint)(mBufferFilled.Height);
IntPtr pBufferData = mBufferFilled.MemPtr;
ulong bufferDataSize = mBufferFilled.MemSize;
ulong imageOffset = mBufferFilled.ImageOffset;
ulong imageDataSize = (bufferDataSize > imageOffset) ? (bufferDataSize - imageOffset) : 0;
IntPtr pImageData = (IntPtr)((ulong)(pBufferData) + imageOffset);
string sComponent = "POL90";
string sPixelFormatRaw = "BaumerPolarized8";
SortedSet<string> sComponents = new SortedSet<string> { "POL0", "POL45", "POL90", "POL135" };
if (imagePolarized == null)
{
imagePolarized = pImgProcessor.CreateImage(width, height, sPixelFormatRaw, pImageData, imageDataSize);
SortedSet<string> sEnableComponents = new SortedSet<string>(sComponents);
EnableComponents(imagePolarized, sEnableComponents);
}
else
{
imagePolarized.Init(width, height, sPixelFormatRaw, pImageData, imageDataSize);
}
BGAPI2.Image multiPartImage = pImgProcessor.CreateTransformedImage(imagePolarized, "Mono8");
BGAPI2.Node componentSelector = multiPartImage.NodeList["ComponentSelector"];
BGAPI2.Node componentEnable = multiPartImage.NodeList["ComponentEnable"];
BGAPI2.Node componentOffset = multiPartImage.NodeList["ComponentOffset"];
BGAPI2.Node componentLength = multiPartImage.NodeList["ComponentLength"];
IntPtr pImageBuffer = multiPartImage.Buffer;
BGAPI2.Image component = null;
System.Drawing.Bitmap bitmap1;
System.Drawing.Bitmap bitmap2;
System.Drawing.Bitmap bitmap3;
System.Drawing.Bitmap bitmap4;
OpenCvSharp.Mat Matgray1 = new Mat();
OpenCvSharp.Mat Matgray2 = new Mat();
OpenCvSharp.Mat Matgray3 = new Mat();
OpenCvSharp.Mat Matgray4 = new Mat();
int CountIndex = 0;
foreach (string sComponentCur in sComponents)
{
componentSelector.Value = sComponentCur;
if (componentEnable.Value == true)
{
CountIndex = CountIndex + 1;
ulong partLength = (ulong)componentLength.Value;
if (partLength > 0)
{
// Part present - direct access to a single part
ulong partOffset = (ulong)componentOffset.Value;
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap((int)width, (int)height, (int)width,
System.Drawing.Imaging.PixelFormat.Format8bppIndexed, (IntPtr)((ulong)(pImageBuffer) + partOffset));
#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;
#endregion
if (CountIndex == 1)
{
Matgray1 = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);//用bitmap转换为mat
}
if (CountIndex == 2)
{
Matgray2 = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);//用bitmap转换为mat
}
if (CountIndex == 3)
{
Matgray3 = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);//用bitmap转换为mat
}
if (CountIndex == 4)
{
Matgray4 = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);//用bitmap转换为mat
}
//string strtime = DateTime.Now.ToString("yyyyMMddhhmmssfff");
//string saveimagepath = sComponentCur + ".jpg";
//bitmap.Save(saveimagepath, System.Drawing.Imaging.ImageFormat.Bmp);
}
}
}
long currenttime = (long)mBufferFilled.Timestamp;
DateTime sdasd = GetTime(currenttime, true);
#region//对四张图像进行基础拼接
Mat panorama1 = new Mat();
Mat panorama2 = new Mat();
Mat panoramaResult = new Mat();
Cv2.VConcat(Matgray1, Matgray2, panorama1);
Cv2.VConcat(Matgray3, Matgray4, panorama2);
Cv2.HConcat(panorama1, panorama2, panoramaResult);
Bitmap bmp = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(panoramaResult);//用mat转换为bitmap
panorama1.Dispose(); panorama2.Dispose(); panoramaResult.Dispose();
#endregion
#region//回调函数保存图像功能
if (bSaveImg)
{
if (!AutoSaveCheck.Checked & !ContinueSave.Checked)
{
//使用bitmap自带函数保存
string strtime = DateTime.Now.ToString("yyyyMMddhhmmssfff");
string saveimagepath = pImgFileDir + "\\" + strtime + ".jpg";
bmp.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);
//}
bSaveImg = false;//变量控制单次保存图像
}
if (AutoSaveCheck.Checked)
{
//使用bitmap自带函数保存
string strtime = DateTime.Now.ToString("yyyyMMddhhmmssfff");
string saveimagepath = pImgFileDir + "\\" + strtime + ".jpg";
//bmp.Save(saveimagepath, System.Drawing.Imaging.ImageFormat.Jpeg);
Thread SaveImagesThread1 = new Thread((ThreadStart)delegate() { AutoSaveImageRun(bmp, saveimagepath); });
SaveImagesThread1.Start();
SaveImagesThread1.Join();
AutoSaveCount = AutoSaveCount + 1;
if (AutoSaveCount == AutoSaveNum0)
{
AutoSaveCount = 0;
bSaveImg = false;
AutoSaveCheck.Checked = false;
}
}
if (ContinueSave.Checked)
{
//使用bitmap自带函数保存
string strtime = DateTime.Now.ToString("yyyyMMddhhmmssfff");
string saveimagepath = pImgFileDir + "\\" + strtime + ".jpg";
//bmp.Save(saveimagepath, System.Drawing.Imaging.ImageFormat.Jpeg);
Thread SaveImagesThread1 = new Thread((ThreadStart)delegate() { AutoSaveImageRun(bmp, saveimagepath); });
SaveImagesThread1.Start();
SaveImagesThread1.Join();
}
}
#endregion
#region//bitmap的图像数据复制pBitmap
Bitmap clonebitmap = (Bitmap)bmp.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)clonebitmap.Width; prcSource.Height = (int)clonebitmap.Height;
System.Drawing.Graphics graph = System.Drawing.Graphics.FromHwnd(pictureBoxA.Handle);
graph.DrawImage(pBitmap, prcPBox, prcSource, GraphicsUnit.Pixel);
#endregion
clonebitmap.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;
}
//------------------------------------------------------------------------------
/* Setup the Baumer GAPI to calculate the requested polarization component from the raw
polarized image */
static ulong EnableComponents(BGAPI2.Image image, SortedSet<string> sComponents)
{
BGAPI2.Node componentSelector = image.NodeList["ComponentSelector"];
BGAPI2.Node componentEnable = image.NodeList["ComponentEnable"];
BGAPI2.NodeMap components = componentSelector.EnumNodeList;
ulong componentsAvailable = components.Count;
ulong componentsEnabled = 0;
for (ulong i = 0; i < componentsAvailable; i++)
{
componentSelector.Value = i;
bool bState = componentEnable.Value;
if (sComponents.Contains(componentSelector.Value) != true)
{
componentEnable.Value = false;
}
else
{
componentEnable.Value = true;
componentsEnabled++;
}
}
return componentsEnabled;
}
3:OpenCVSharp合并偏振相机4个角度的图像的功能
下面为在在C#环境开启相机连接相机后通过BGAPI SDK联合OpenCVSharp合并偏振相机4个角度的图像的核心代码。
如下所示:
#region//对四张图像进行基础拼接
Mat panorama1 = new Mat();
Mat panorama2 = new Mat();
Mat panoramaResult = new Mat();
Cv2.VConcat(Matgray1, Matgray2, panorama1);
Cv2.VConcat(Matgray3, Matgray4, panorama2);
Cv2.HConcat(panorama1, panorama2, panoramaResult);
Bitmap bmp = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(panoramaResult);//用mat转换为bitmap
panorama1.Dispose(); panorama2.Dispose(); panoramaResult.Dispose();
#endregion
效果如下图所示:
Baumer工业偏振相机获取多角度偏振图像的优点
1、它们使用偏振滤光片来捕捉在单一方向上振动的光波,减少眩光和闪亮表面的反射。这导致了更清晰和更精确的图像,使其更容易识别高反射表面的缺陷或异常情况。
2、偏光相机还提供更好的对比度和颜色精度,允许精确的颜色测量和分析。
3、偏光相机可以在恶劣的环境条件下使用,并能捕捉到普通相机难以看到的物体的图像。
Baumer工业偏振相机获取多角度偏振图像的行业应用
偏光工业相机通常用于各种工业应用,如质量控制、缺陷检查、材料分析和表面检查。
它们有助于消除眩光和反射,提高玻璃、塑料、金属等各种材料的图像对比度和准确性。
偏光工业相机在检测隐藏的缺陷或污染物、识别材料中的应力点和检查隐藏结构方面也很有用。它们通常用于汽车、航空航天、电子和制造业等行业。
-
检查和质量控制: 工业偏振照相机可用于获取产品和材料的多角度偏振图像,以便进行详细的检查和质量控制。这在食品和饮料、制药和电子制造等行业特别有用。
-
材料分析: 工业偏振照相机可用于分析材料的偏振特性,如塑料、织物和金属。这在取证、产品开发和研究与发展中很有用。
-
表面检查: 通过分析光从表面反射的偏振,工业偏振照相机可以用来检测缺陷、划痕和其他瑕疵。这在汽车制造、航空航天和电子等行业都很有用。
-
机器视觉: 工业偏振照相机可以被集成到机器视觉系统中,允许实时分析和处理多角度的偏振图像。这在自动检测和质量控制过程中很有用。
总的来说,工业偏振照相机为获取详细和复杂的图像提供了强有力的工具,可用于改善各行业的生产过程、产品质量和材料分析。