Baumer工业相机中偏振相机如何使用Baumer堡盟GAPI SDK来进行偏振数据的计算转换输出(C++)

Posted 格林威

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Baumer工业相机中偏振相机如何使用Baumer堡盟GAPI SDK来进行偏振数据的计算转换输出(C++)相关的知识,希望对你有一定的参考价值。

项目场景

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

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

Baumer工业相机的BGAPI SDK给新型偏振照相机提供了测量所获图像的强度和偏振的能力。因此,它能够在应用程序中利用偏振信息。本应用说明描述了如何获得偏振信息。

工业相机产品:
Baumer堡盟VCXU-50MP和堡盟VCXG-50MP,GAPI SDK v2.9.2及以上。

Baumer工业相机的偏振功能的详细介绍应用可以参考下面的技术博客,本文只介绍偏振数据的使用:

Baumer工业相机堡盟相机如何使用偏振功能(偏振相机优点和行业应用)(C++)_格林威的博客-CSDN博客


技术背景

Baumer工业相机的BGAPI SDK可以提供相机的图像原始数据,Halcon具有极为巨大的图像处理库,在图像处理领域非常强大,功能丰富,使用于工业视觉检测。

工业相机的SDK(Software Development Kit)是为了方便开发人员对工业相机进行控制和图像采集而提供的一套软件工具。而Halcon是一款强大的机器视觉软件,能够进行图像处理、分析、识别等多种任务。

 Baumer工业相机中的偏振相机是基于索尼IMC250MZR传感器的。该传感器涂有一层金属网,可以过滤4个相邻像素的偏振信息。偏振角度被过滤以0°、45°、90°、135°的方式排列。
有了这些信息,就可以计算出以下数据:
偏振角(AOP)。
直线极化度(DOLP)
角度和直角极化度(ADOLP)
图像的强度。

使用BGAPI SDK的偏振相机的用法:
该相机只提供有关偏振的原始数据。不同偏振格式的计算格式的计算在主机系统上通过堡盟GAPI SDK完成。

这就减少了接口的必要带宽,因为数据只传输一次,而不是针对每种偏振格式(AOP、DOLP、ADOLP.Intensity)单独传输、强度)分别传输。


功能分析

偏振相机功能的描述
使用标准化的SFNC特性 "ComponentSelector "和 "ComponentEnable",GenICam
兼容的软件可以识别该相机提供原始偏振数据。这些特征不能被改变(只读)。
为了进行识别,应检查以下特征:
ComponentSelector = PolarizedRaw
ComponentEnable = True
为了实现对广泛的GenICam兼容软件的兼容性,堡盟没有引入自定义图像格式。
原始偏振数据使用标准格式Mono8、Mono10、Mono12或Mono13传输、Mono10、Mono12或Mono12p。
此外,该相机还提供了用于校准相机的必要功能,这些功能属于以下类别"校准控制" 这些功能充满了堡盟的校准值。

如有必要,还可使用"DeviceResetToDeliveryState "将把这些值重置为堡盟提供的校准值。


代码分析

为了确保计算尽可能少地使用资源并实现高帧率,有两种方法方法来处理数据。这里我们解释一下最重要的配置和使用的软件功能的使用。
如果一个应用只需要一种偏振格式(AOP、DOLP或ADOLP),最好使用一个单部分图像对象。单部分图像对象正好包含一个图像。

核心代码如下所示:

// A Baumer Polarization Camera can be recognized by checking that the feature
// ComponentSelector has the value "PolarizedRaw"
if (pDevice->GetRemoteNodeList()->GetNodePresent("ComponentSelector"))

if (pDevice->GetRemoteNode("ComponentSelector")->GetValue() == "PolarizedRaw")

// I'm a Polarization Camera


// Acquire an image to a buffer
BGAPI2::Buffer* pBufferFilled = pDataStream->GetFilledBuffer(1000);
bo_uint width = static_cast<bo_uint>(pBufferFilled->GetWidth());
bo_uint height = static_cast<bo_uint>(pBufferFilled->GetHeight());
void* pBufferData = pBufferFilled->GetMemPtr();
bo_uint64 bufferDataSize = pBufferFilled->GetMemSize();
bo_uint64 imageOffset = pBufferFilled->GetImageOffset();

// Enable all polarized formats (AOP, DOLP, ADOLP, Intensity)
BGAPI2::Node* pCompSelector = pImage->GetNode("ComponentSelector");
BGAPI2::NodeMap*pComponents = pCompSelector->GetEnumNodeList();
for (bo_uint64 i = 0; i < pComponents->GetNodeCount(); i++)

    pCompSelector->SetInt(i);
    pImage->GetNode("ComponentEnable")->SetBool( true );

// Calculate all the polarization formats from the raw image to a multi-part Image object.
BGAPI2::Image* pMultiPartImage = pImageProcessor->CreateTransformedImage(pImage, "Mono8");
// Get necessary information about each multi-part
BGAPI2::Node* pComponentSelector = pMultiPartImage->GetNode("ComponentSelector");
BGAPI2::Node* pComponentEnable = pMultiPartImage->GetNode("ComponentEnable");
BGAPI2::Node* pComponentOffset = pMultiPartImage->GetNode("ComponentOffset");
BGAPI2::Node* pComponentLength = pMultiPartImage->GetNode("ComponentLength");
const void* const pImageBuffer = pMultiPartImage->GetBuffer();
// Loop through the multi-part Image object to extract all the parts
for (std::set<std::string>::const_iterator it = sComponents.begin(); it != sComponents.end();it++)

    pComponentSelector->SetValue(it->c_str());
    std::string sComponent = pComponentSelector->GetValue().get();
    if (pComponentEnable->GetBool()) 
    bo_uint64 partLength = pComponentLength->GetInt();
    BGAPI2::Image* pComponent = NULL;
    if (partLength > 0)
    
        // Part is valid
        bo_uint64 partOffset = pComponentOffset->GetInt();
        pComponent = pImageProcessor->CreateImage(width, height, "Mono8"
        , (char*)(pImageBuffer)+partOffset, partLength);
    
    else
    
        // Part is empty
        if (sComponent == "ADOLP") 
        
            // ADOLP is calculated from the AOP and DOLP images, therefore this
            // second transformation is necessary.
            pComponent = pImageProcessor->CreateTransformedImage(pMultiPartImage, "RGB8");
        
    
    if (pComponent)
    
        // Whatever needs to be done with the polarization data goes here
        // doCustomCalculation(pComponent, sComponent);
        // Release the data when not needed anymore
        pComponent->Release();
    
    


CameraExplorer软件使用偏振功能

我们可以通过CameraExplorer软件用于查看和保存以下格式的偏振数据
AOP、DOLP、ADOLP和Intensity。
配置是可以在基本视图中使用 "偏振 "类别来完成。

如下图所示:

 

 

 

Baumer工业相机堡盟相机如何使用BGAPI SDK和Opencv联动实现图像转换成视频(C#)

Baumer工业相机堡盟相机如何使用BGAPI SDK和Opencv联动实现图像转换成视频


Baumer工业相机

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

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

Baumer工业相机的BGAPI SDK可以和OpenCV进行联合实现图像转换成视频的功能。

Baumer工业相机SDK技术背景

Baumer工业相机的BGAPI SDK可以提供相机的图像原始数据,Halcon具有极为巨大的图像处理库,在图像处理领域非常强大,功能丰富,使用于工业视觉检测。

工业相机的SDK(Software Development Kit)是为了方便开发人员对工业相机进行控制和图像采集而提供的一套软件工具。而Halcon是一款强大的机器视觉软件,能够进行图像处理、分析、识别等多种任务。

Baumer工业相机软件CameraExplorer 3.3.2版本下载路径如下:

https://download.csdn.net/download/xianzuzhicai/87426794(Baumer工业相机软件CameraExplorer-Windows-x64版本)

代码分析

本文介绍使用BGAPI SDK对Baumer工业相机进行开发时,使用OpenCV作为图像处理库进行视频生成的相关功能。

第一步:先引用OpenCV库

本文使用“opencv_ffmpeg410_64.dll”和其它常用OpenCV库作为功能应用显示视频生成功能
C#环境下引用OpencCV库代码如下所示:

using OpenCvSharp;
using OpenCvSharp.Dnn;
using OpenCvSharp.Extensions;

第二步:引用图像文件夹生成视频

后续进行图像转换成视频的核心代码,如下所示:

string VideoSavePath = AppDomain.CurrentDomain.BaseDirectory;  
string videopath = "";
private void CreateVideo_Click(object sender, EventArgs e)

    //string VideoSavePath = AppDomain.CurrentDomain.BaseDirectory;            
    FolderBrowserDialog dlg = new FolderBrowserDialog();
    dlg.Description = "请选择视频保存路径";
    dlg.SelectedPath = VideoSavePath;
    if (DialogResult.OK == dlg.ShowDialog())
    
        VideoSavePath = dlg.SelectedPath;
        SaveVideoPathDisplay.Text = VideoSavePath;
        videopath = VideoSavePath+"\\\\" + "OutputVideo.avi";
        string task_path = pImgFileDir;
        if (!Directory.Exists(task_path))
        
            MessageBox.Show("未选择生成视频的源图片文件夹路径");
            return;
        
        DirectoryInfo dir = new DirectoryInfo(task_path);
        int imagecount = 0; int width1 = 0; int height1 = 0;
        DateTime dt1 = DateTime.Now;
        foreach (FileInfo file in dir.GetFiles("*.bmp", SearchOption.AllDirectories))
        
            imagecount = imagecount + 1;
            string Imagepath = file.FullName;

            //Bitmap image0 = file2img(Imagepath);
            //Mat matimg = OpenCvSharp.Extensions.BitmapConverter.ToMat(image0); 

            Mat mat_res_8 = Cv2.ImRead(Imagepath, ImreadModes.Grayscale);
                    
            width1 = mat_res_8.Width; height1 = mat_res_8.Height;
            break;
        
        if (imagecount > 0 & width1 > 0 & height1 > 0)
        
            int fpsint = (Int32)numericUpDown3.Value;
            video = new VideoWriter(videopath, VideoWriter.FourCC('X', 'V', 'I', 'D'), fpsint,
                    new OpenCvSharp.Size((double)width1, (double)height1), false);
            OnNotifyShowRecieveMsg("开始生成视频");
            foreach (FileInfo file in dir.GetFiles("*.bmp", SearchOption.AllDirectories))
            
                string Imagename = file.Name;
                string Imagepath = file.FullName;
                Mat mat_res_8 = Cv2.ImRead(Imagepath, ImreadModes.Grayscale);
                //CreateVideoFromImage(mat_res_8);
                video.Write(mat_res_8);
                if (Cv2.WaitKey(1) == 27)//隐藏指令:按ESC可停止生成视频
                
                    break;
                
            
            video.Release();
            OnNotifyShowRecieveMsg("生成视频已完成");
            DateTime dt2 = DateTime.Now;
            TimeSpan ts = dt2.Subtract(dt1);
            double bb = (dt2 - dt1).Ticks / 10000000;//转换成秒
            Int32 NowMinu = (Int32)ts.TotalSeconds;
            OnNotifyShowRecieveMsg("生成时间:" + NowMinu+"S");
            string ExplorPath = VideoSavePath;
            //if (Directory.Exists(ExplorPath))
            //    System.Diagnostics.Process.Start(ExplorPath);
            if (Directory.Exists(ExplorPath))
            
                if (File.Exists(videopath))
                
                    OnNotifyShowRecieveMsg("自动打开视频路径");
                    string pathnew = "/select," + videopath;
                    System.Diagnostics.Process.Start("Explorer.exe", @pathnew);
                                      
            
                    
        
        else
        
            MessageBox.Show("选择路径下无对应图片,无法生成视频");
        
               
              
          


工业相机图像通过OpenCV转为视频的优点

  1. 低水平图像处理: OPENCV为低级别的图像处理提供了一套丰富的库。它允许轻松访问图像特征,如对比度、亮度和颜色校正。

  2. 实时视频处理: 使用OPENCV,你可以实时处理视频流,允许对处理过程进行即时反馈和调整。

  3. 精确的物体检测: OPENCV提供先进的物体检测和识别算法,能够准确识别和跟踪视频流中的物体。

  4. 高效的硬件利用: OPENCV的设计旨在最大限度地提高硬件利用率,使其成为一个高效的视频处理平台。

  5. 跨平台兼容性: OPENCV与多种操作系统兼容,使其易于集成到现有的软件系统中。

总的来说,通过OPENCV将工业相机图像转换为视频,可以实现高效、准确、实时的图像处理和分析,使其成为工业应用的有力工具。

工业相机图像转为视频的行业应用

  1. 制造业: 工业相机可用于捕捉装配线、机器和设备的图像,这些图像可转换为视频,用于监测生产和质量控制。

  2. 医疗:工业相机用于医疗成像设备,如X射线、MRI、CT扫描和超声波。将这些图像转换为视频后,医生和医疗专业人员可以实时查看和分析图像。

  3. 安全和监视: 工业相机被用于公共场所、办公室和家庭的安全和监控。将图像转换为视频可以进行连续监控,并更容易分析。

  4. 交通: 工业相机被用于交通系统,如机场、高速公路和火车,以监测交通和确保安全。将图像转换为视频可以对交通模式和潜在的安全隐患进行实时监控和分析。

  5. 农业: 工业相机被用于农业,以监测作物、牲畜和机械。将这些图像转换为视频后,农民和农业专业人员可以监测和分析作物和牲畜的健康和生长情况。

以上是关于Baumer工业相机中偏振相机如何使用Baumer堡盟GAPI SDK来进行偏振数据的计算转换输出(C++)的主要内容,如果未能解决你的问题,请参考以下文章

Baumer工业相机堡盟工业相机如何通过BGAPISDK里的图像处理库进行图像转换(C++)

ni vision builder如何与工业相机连接?

Dalsa Sherlock 直连千兆网相机(通用驱动)

如何理解工业相机的标定

工业相机镜头选型

工业相机镜头选型