Baumer工业相机堡盟工业相机如何通过BGAPI SDK获取偏振相机4个角度的图像转换和显示(C#)

简介: Baumer工业相机堡盟工业相机如何通过BGAPI SDK获取偏振相机4个角度的图像转换和显示(C#)

Baumer工业相机

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


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

Baumer工业相机的BGAPI SDK给新型偏振相机提供了测量所获图像的强度和偏振的能力。因此,它能够在应用程序中利用偏振信息。本应用说明描述了如何同时获得偏振相机4个角度图像数据并进行转换和显示的功能。


Baumer工业相机的偏振功能的详细介绍应用可以参考下面的技术博客,本文介绍如何同时获取4个角度偏振数据的功能:

Baumer工业相机堡盟相机如何使用偏振功能(偏振相机优点和行业应用)(C++)


已经如何使用ADOLP的偏振图像数据进行显示的技术博客:


Baumer工业相机堡盟工业相机如何通过BGAPISDK转换和显示偏振相机的图像(C#)


Baumer工业相机偏振相机的技术背景

工业相机中的偏振相机是基于偏振光原理实现的。偏振光是指在光的传播过程中,光的振动方向只在一个特定平面内振荡的光,与之相对的光称为自然光。偏振相机通过使用偏振片或偏振镜来控制光线的振动方向,使得只有具有特定偏振方向的光线经过相机镜头,从而达到特定的筛选或测量功能。


偏振相机在工业品质检测、医学诊断、材料分析等领域有着广泛的应用。例如,在工业品质检测中,偏振相机可以检测材料的应力分布、表面缺陷等信息,从而确定产品的质量;在医学诊断中,偏振相机可以用于检测组织和染色质等生物样本的材料学特征;在材料分析中,偏振相机可以用于检测材料中的畸变和裂缝等缺陷。


总的来说,偏振相机在工业自动化和科学研究等领域中具有重要的应用价值,可以实现快速、准确、高效的检测和分析。

Baumer工业相机中的偏振相机是基于索尼IMC250MZR传感器的。该传感器涂有一层金属网,可以过滤4个相邻像素的偏振信息。偏振角度被过滤以0°、45°、90°、135°的方式排列。


这里主要描述如何在C#的平台下通过BGAPI SDK同时获取偏振相机四个偏振角度图像的核心代码


代码案例分享

本文介绍使用BGAPI SDK对Baumer的工业相机进行开发时,获取偏振相机四个偏振角度图像并进行显示功能


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


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获取偏振相机四个偏振角度的图像

下面为在在C#环境开启相机连接相机后通过BGAPISDK获取偏振相机四个偏振角度的图像的核心代码。


如下所示:

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.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";
    #region//获取四个角度的偏振角度图像原始数据
            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);                        
            } 
    #endregion
    #region//形成包含四组偏振角度信息的图像
            BGAPI2.Image multiPartImage = pImgProcessor.CreateTransformedImage(imagePolarized, "Mono8");
            #endregion
            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;
    #region//从原始图像中分出四个偏振角度的图像
    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)
                        {
                           bitmap1 = bitmap;
                        }
                        if (CountIndex == 2)
                        {
                            bitmap2 = bitmap;
                        }
                        if (CountIndex == 3)
                        {
                            bitmap3 = bitmap;
                        }
                        if (CountIndex == 4)
                        {
                            bitmap4 = bitmap;
                        }
                    }
                }
            }
    #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
            long 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);                
                bSaveImg = false;//变量控制单次保存图像
            }
            #endregion
            #region//bitmap的图像数据复制pBitmap
            Bitmap 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);
            #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:使用BGAPI SDK同时获取偏振相机四个角度的图像的功能

下面为在在C#环境开启相机连接相机后通过BGAPI SDK同时获取偏振相机四个角度的图像转换并显示的核心代码。


如下所示:

#region//获取四个角度的偏振角度图像原始数据
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);
}
#endregion
#region//形成包含四组偏振角度信息的图像
BGAPI2.Image multiPartImage = pImgProcessor.CreateTransformedImage(imagePolarized, "Mono8");
#endregion
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;
#region//从原始图像中分出四个偏振角度的图像
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)
            {
                bitmap1 = bitmap;
            }
            if (CountIndex == 2)
            {
                bitmap2 = bitmap;
            }
            if (CountIndex == 3)
            {
                bitmap3 = bitmap;
            }
            if (CountIndex == 4)
            {
                bitmap4 = bitmap;
            }
        }
    }
}
#endregion

Baumer工业偏振相机获取多角度偏振图像的优点

1、它们使用偏振滤光片来捕捉在单一方向上振动的光波,减少眩光和闪亮表面的反射。这导致了更清晰和更精确的图像,使其更容易识别高反射表面的缺陷或异常情况。


2、偏光相机还提供更好的对比度和颜色精度,允许精确的颜色测量和分析。


3、偏光相机可以在恶劣的环境条件下使用,并能捕捉到普通相机难以看到的物体的图像。


Baumer工业偏振相机获取多角度偏振图像的行业应用

偏光工业相机通常用于各种工业应用,如质量控制、缺陷检查、材料分析和表面检查。

它们有助于消除眩光和反射,提高玻璃、塑料、金属等各种材料的图像对比度和准确性。

偏光工业相机在检测隐藏的缺陷或污染物、识别材料中的应力点和检查隐藏结构方面也很有用。它们通常用于汽车、航空航天、电子和制造业等行业。


检查和质量控制: 工业偏振照相机可用于获取产品和材料的多角度偏振图像,以便进行详细的检查和质量控制。这在食品和饮料、制药和电子制造等行业特别有用。


材料分析: 工业偏振照相机可用于分析材料的偏振特性,如塑料、织物和金属。这在取证、产品开发和研究与发展中很有用。


表面检查: 通过分析光从表面反射的偏振,工业偏振照相机可以用来检测缺陷、划痕和其他瑕疵。这在汽车制造、航空航天和电子等行业都很有用。


机器视觉: 工业偏振照相机可以被集成到机器视觉系统中,允许实时分析和处理多角度的偏振图像。这在自动检测和质量控制过程中很有用。


总的来说,工业偏振照相机为获取详细和复杂的图像提供了强有力的工具,可用于改善各行业的生产过程、产品质量和材料分析。

目录
相关文章
|
3月前
|
监控 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C#)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C#)
73 0
|
3月前
|
监控 API 开发工具
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C++)
Baumer工业相机堡盟工业相机如何通过NEOAPI SDK获取每张图像的微秒时间和FrameID功能(C++)
59 0
|
3月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
150 3
|
3月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
162 3
|
16天前
|
存储 C#
揭秘C#.Net编程秘宝:结构体类型Struct,让你的数据结构秒变高效战斗机,编程界的新星就是你!
【8月更文挑战第4天】在C#编程中,结构体(`struct`)是一种整合多种数据类型的复合数据类型。与类不同,结构体是值类型,意味着数据被直接复制而非引用。这使其适合表示小型、固定的数据结构如点坐标。结构体默认私有成员且不可变,除非明确指定。通过`struct`关键字定义,可以包含字段、构造函数及方法。例如,定义一个表示二维点的结构体,并实现计算距离原点的方法。使用时如同普通类型,可通过实例化并调用其成员。设计时推荐保持结构体不可变以避免副作用,并注意装箱拆箱可能导致的性能影响。掌握结构体有助于构建高效的应用程序。
39 7
|
2天前
|
安全 C# 开发者
【C# 多线程编程陷阱揭秘】:小心!那些让你的程序瞬间崩溃的多线程数据同步异常问题,看完这篇你就能轻松应对!
【8月更文挑战第18天】多线程编程对现代软件开发至关重要,特别是在追求高性能和响应性方面。然而,它也带来了数据同步异常等挑战。本文通过一个简单的计数器示例展示了当多个线程无序地访问共享资源时可能出现的问题,并介绍了如何使用 `lock` 语句来确保线程安全。此外,还提到了其他同步工具如 `Monitor` 和 `Semaphore`,帮助开发者实现更高效的数据同步策略,以达到既保证数据一致性又维持良好性能的目标。
7 0
|
2月前
|
存储 C# 开发者
C# 编程基础:注释、变量、常量、数据类型和自定义类型
C# 编程基础:注释、变量、常量、数据类型和自定义类型
28 1
|
3月前
|
开发框架 .NET Java
探索 C#编程的奥秘与魅力
【4月更文挑战第20天】C#是微软开发的现代、面向对象的编程语言,以其简洁语法、强大功能和跨平台支持脱颖而出。它支持自动垃圾回收、泛型、委托、LINQ,并广泛应用于桌面、Web、移动和游戏开发。C#拥有活跃的开发者社区和丰富的资源,是Unity游戏开发的首选语言。随着.NET Core,C#可在多个操作系统上运行,持续创新,未来发展潜力巨大。
156 11
|
3月前
|
存储 安全 网络安全
C#编程的安全性与加密技术
【4月更文挑战第21天】C#在.NET框架支持下,以其面向对象和高级特性成为安全软件开发的利器。本文探讨C#在安全加密领域的应用,包括使用System.Security.Cryptography库实现加密算法,利用SSL/TLS保障网络传输安全,进行身份验证,并强调编写安全代码的重要性。实际案例涵盖在线支付、企业应用和文件加密,展示了C#在应对安全挑战的同时,不断拓展其在该领域的潜力和未来前景。
220 5
|
3月前
|
IDE 程序员 C#
C#编程入门:从零开始的旅程
【4月更文挑战第20天】本文引导初学者入门C#编程,从环境搭建开始,推荐使用Visual Studio Community版作为IDE。接着,通过编写&quot;Hello, World!&quot;程序,介绍基本语法,包括数据类型、运算符和表达式。文章还涉及控制结构、函数和方法,以及面向对象编程概念。通过学习,读者将对C#有初步了解,并激发进一步探索编程世界的兴趣。
94 4