Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。
Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度可扩展性等特点。
Baumer工业相机的BGAPISDK可以在C#的环境下提供原始的图像数据,直接将Buffer的数据转为Halcon的Hoject数据信息,再通过使用Halcon的图像算法实现图像的处理。
Baumer工业相机的BGAPI SDK可以提供相机的图像原始数据,Halcon具有极为巨大的图像处理库,在图像处理领域非常强大,功能丰富,使用于工业视觉检测。
工业相机的SDK(Software Development Kit)是为了方便开发人员对工业相机进行控制和图像采集而提供的一套软件工具。而Halcon是一款强大的机器视觉软件,能够进行图像处理、分析、识别等多种任务。
将工业相机的SDK图像转换为Halcon图像,是为了实现将工业相机采集到的图像数据导入到Halcon环境中进行处理和分析。这样可以充分利用Halcon的各种图像处理和分析工具,提高图像处理的效率和精度。
本文这里只简单使用Baumer工业相机联合Halcon进行图像字体提取的图像算法。
下面介绍在C#里Baumer工业相机在回调函数里联合Halcon直接进行线性灰度变换图像增强的演示,
先将Bitmap图像转为Halcon的图像Hobject,然后使用Halcon的区域分割、特征提取等功能,最后将Hobject图像转换为Bitmap。
代码如下(示例):
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 BGAPI2;
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 HalconDotNet;
代码如下(示例),C#调用代码如下所示:
void 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 again
mBufferFilled.QueueBuffer();
}
else
{
#region//获取当前FrameID
FrameIDInt = (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;
#endregion
#region//回调函数保存图像功能
if (bSaveImg)
{
//使用bitmap自带函数保存
string strtime = DateTime.Now.ToString("yyyyMMddhhmmssfff");
string saveimagepath = pImgFileDir +"\\"+ strtime + ".jpg";
bitmap.Save(saveimagepath, System.Drawing.Imaging.ImageFormat.Bmp);
bSaveImg = false;//变量控制单次保存图像
}
#endregion
//将Bitmap数据转为Halcon的Hobject
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapDat srcBmpData=bmp.LockBits(rect,ImageLockMode.ReadOnly,
PixelFormat.Format8bppIndexed);
HOperatorSet.GenImage1(out image, "byte", bmp.Width, bmp.Height, srcBmpData.Scan0);
bmp.UnlockBits(srcBmpData);
#region//对图像进行特征提取
Hobject ImageScaled;
HOperatorSet.GenRectangle1(out ho_ROI_0, 203.865, 139.939, 402.189, 748.899);
ho_ImageReduced.Dispose();
HOperatorSet.ReduceDomain(ho_Image624055013043709531022, ho_ROI_0, out ho_ImageReduced
);
ho_Image1.Dispose();
ho_Image2.Dispose();
ho_Image3.Dispose();
HOperatorSet.Decompose3(ho_ImageReduced, out ho_Image1, out ho_Image2, out ho_Image3
);
ho_Region.Dispose();
HOperatorSet.Threshold(ho_Image2, out ho_Region, 0, 100);
ho_ConnectedRegions.Dispose();
HOperatorSet.Connection(ho_Region, out ho_ConnectedRegions);
ho_SelectedRegions.Dispose();
HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, "area",
"and", 700, 99999);
ho_RegionFillUp.Dispose();
HOperatorSet.FillUpShape(ho_SelectedRegions, out ho_RegionFillUp, "area", 1,
200);
ho_RegionUnion.Dispose();
HOperatorSet.Union1(ho_RegionFillUp, out ho_RegionUnion);
ho_ImageReduced2.Dispose();
HOperatorSet.ReduceDomain(ho_Image624055013043709531022, ho_RegionUnion, out ho_ImageReduced2
);
HObjectConvertBpp8(ImageScaled,out bmp);
#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)mBufferFilled.Width;prcSource.Height = (int)mBufferFilled.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;
}
private static void HObjectConvertBpp8(HObject image, out Bitmap res)
{
try
{
HTuple hpoint, type, width, height;
const int Alpha = 255;
int[] ptr = new int[2];
HOperatorSet.GetImagePointer1(image, out hpoint, out type, out width, out height);
res = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
ColorPalette pal = res.Palette;
for (int i = 0; i <= 255; i++)
{
pal.Entries[i] = Color.FromArgb(Alpha, i, i, i);
}
res.Palette = pal;
Rectangle rect = new Rectangle(0, 0, width, height);
BitmapData bitmapData = res.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
int PixelSize = Bitmap.GetPixelFormatSize(bitmapData.PixelFormat) / 8;
ptr[0] = bitmapData.Scan0.ToInt32();
ptr[1] = hpoint.I;
if (width % 4 == 0)
CopyMemory(ptr[0], ptr[1], width * height * PixelSize);
else
{
for (int i = 0; i < height - 1; i++)
{
ptr[1] += width;
CopyMemory(ptr[0], ptr[1], width * PixelSize);
ptr[0] += bitmapData.Stride;
}
}
res.UnlockBits(bitmapData);
}
catch(Exception ex)
{
res = null;
throw ex;
}
}
C#调用代码如下所示:
//将Bitmap数据转为Halcon的Hobject
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapDat srcBmpData=bmp.LockBits(rect,ImageLockMode.ReadOnly,
PixelFormat.Format8bppIndexed);
HOperatorSet.GenImage1(out image, "byte", bmp.Width, bmp.Height, srcBmpData.Scan0);
bmp.UnlockBits(srcBmpData);
#region//对灰度图像进行线性灰度变换算法增强
Hobject ImageScaled;
HOperatorSet.GenRectangle1(out ho_ROI_0, 203.865, 139.939, 402.189, 748.899);
ho_ImageReduced.Dispose();
HOperatorSet.ReduceDomain(ho_Image624055013043709531022, ho_ROI_0, out ho_ImageReduced
);
ho_Image1.Dispose();
ho_Image2.Dispose();
ho_Image3.Dispose();
HOperatorSet.Decompose3(ho_ImageReduced, out ho_Image1, out ho_Image2, out ho_Image3
);
ho_Region.Dispose();
HOperatorSet.Threshold(ho_Image2, out ho_Region, 0, 100);
ho_ConnectedRegions.Dispose();
HOperatorSet.Connection(ho_Region, out ho_ConnectedRegions);
ho_SelectedRegions.Dispose();
HOperatorSet.SelectShape(ho_ConnectedRegions, out ho_SelectedRegions, "area",
"and", 700, 99999);
ho_RegionFillUp.Dispose();
HOperatorSet.FillUpShape(ho_SelectedRegions, out ho_RegionFillUp, "area", 1,
200);
ho_RegionUnion.Dispose();
HOperatorSet.Union1(ho_RegionFillUp, out ho_RegionUnion);
ho_ImageReduced2.Dispose();
HOperatorSet.ReduceDomain(ho_Image624055013043709531022, ho_RegionUnion, out ho_ImageReduced2);
HObjectConvertBpp8(ImageScaled,out bmp);
#endregion
#endregion
private static void HObjectConvertBpp8(HObject image, out Bitmap res)
{
try
{
HTuple hpoint, type, width, height;
const int Alpha = 255;
int[] ptr = new int[2];
HOperatorSet.GetImagePointer1(image, out hpoint, out type, out width, out height);
res = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
ColorPalette pal = res.Palette;
for (int i = 0; i <= 255; i++)
{
pal.Entries[i] = Color.FromArgb(Alpha, i, i, i);
}
res.Palette = pal;
Rectangle rect = new Rectangle(0, 0, width, height);
BitmapData bitmapData = res.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
int PixelSize = Bitmap.GetPixelFormatSize(bitmapData.PixelFormat) / 8;
ptr[0] = bitmapData.Scan0.ToInt32();
ptr[1] = hpoint.I;
if (width % 4 == 0)
CopyMemory(ptr[0], ptr[1], width * height * PixelSize);
else
{
for (int i = 0; i < height - 1; i++)
{
ptr[1] += width;
CopyMemory(ptr[0], ptr[1], width * PixelSize);
ptr[0] += bitmapData.Stride;
}
}
res.UnlockBits(bitmapData);
}
catch(Exception ex)
{
res = null;
throw ex;
}
}
将工业相机SDK图像与Halcon连接起来可以有几个好处。
提高图像质量:Halcon是一个强大的图像处理和分析软件工具。当你将你的工业相机SDK图像连接到Halcon时,你可以利用它的功能来提高图像的质量。
更大的灵活性: 通过将工业相机SDK的图像连接到Halcon,你可以利用Halcon的灵活性和多功能性。你可以利用其先进的特性和功能,根据你的具体需要,优化你的图像处理工作流程。
更快的处理速度: Halcon对速度进行了优化,可以比其他类似工具更快地执行复杂的图像处理任务。当你将你的工业相机SDK图像链接到Halcon时,你可以受益于它的卓越性能,使你能够快速有效地处理图像。
更容易集成: Halcon的设计是为了与其他工业相机SDK和图像处理工具无缝集成。通过将你的相机SDK图像连接到Halcon,你可以得到两方面的好处:一个强大的图像处理工具和你现有的相机SDK的好处。
更好的结果: 所有这些优势最终都会带来更好的结果。通过使用Halcon来处理你的工业相机SDK图像,你可以优化你的工作流程,提高图像质量,实现更快的结果,从而获得更好的结果和更有效的流程。
质量控制和检查:
使用Halcon先进的图像处理算法,你可以开发一个质量控制和检查系统,可以识别和分类产品或部件的缺陷和异常。通过将工业相机SDK图像与Halcon连接起来,你可以获取和分析高质量的图像,并进行实时分析。
物体识别和跟踪:
可以利用Halcon的物体识别和跟踪功能来跟踪移动物体或实时识别物体。通过将工业相机SDK与Halcon集成,你可以获得高分辨率的图像,并利用Halcon的图像处理工具来准确地检测和跟踪物体。
条形码和OCR阅读:
利用Halcon的条形码和OCR读取功能,你可以开发出读取和解码工业相机拍摄的图像中的条形码和OCR文本的系统。通过将工业相机SDK图像与Halcon连接起来,你可以捕获高质量的图像,以实现准确可靠的条形码和OCR阅读。
机器人和自动化:
Halcon可用于机器人视觉系统,使机器人能够与环境互动并执行各种任务。通过将工业相机与Halcon连接,你可以在机器人自动化过程中实现实时监控和反馈。
总的来说,将工业相机SDK图像与Halcon连接起来,可以让开发者建立先进的计算机视觉应用,充分利用两种技术的能力。