Baumer工业相机堡盟工业相机如何通过BGAPISDK的软触发实现两相机同步采集(C++)

news2024/12/24 8:08:28

Baumer工业相机堡盟工业相机如何通过BGAPISDK的软触发实现两相机的同步采集(C++)

  • Baumer工业相机
  • Baumer工业相机的高速同步采集的技术背景
  • Baumer工业相机通过BGAPI SDK在回调函数里同步保存图像
    • 工业相机在回调函数BufferEvent保存
    • 工业相机使用软触发进行同步采集
    • 工业相机的软件触发命令线程函数
    • Baumer工业相机的软件触发同步采集测试图
  • Baumer工业相机的高速同步采集功能的优势
  • Baumer工业相机的高速同步采集功能的行业应用

Baumer工业相机

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

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

Baumer工业相机由于其性能和质量的优越和稳定,常用于高速同步采集领域。

Baumer工业相机的高速同步采集的技术背景

多个工业相机的高速同步采集是一个技术过程,涉及到从多个相机高速采集图像,并将其整合到一个同步系统中。这个过程需要先进的硬件和软件技术,以及对摄像机同步、数据传输和图像处理的理解。

为了实现多个工业相机的高速同步采集,有必要使用支持硬件触发并可通过先进软件进行同步的相机。例如,可以使用主时钟信号或脉冲发生器来触发摄像机,以确保所有摄像机在完全相同的时刻捕获图像。

此外,还需要一个高速数据传输网络,以确保每个摄像机捕获的大量图像数据能够快速传输到中央处理单元(CPU)进行进一步分析。这通常涉及使用高速通信协议,如千兆以太网或CoaXPress。

在图像处理方面,需要专门的软件来处理由多个摄像机产生的大量数据。这可能包括实时视频处理算法、运动检测、模式识别或其他先进技术,旨在从捕获的图像中提取有用信息。

总的来说,实现多个工业相机的高速同步采集是一项复杂的技术任务,需要多个学科的专业知识,包括硬件设计、软件开发和图像处理。

本文这里只简单介绍Baumer的两个工业相机在设置相同参数时,使用软触发进行的同步采集

Baumer工业相机通过BGAPI SDK在回调函数里同步保存图像

下面介绍在C++里两个Baumer工业相机在软触发的情况下进行同步采集

工业相机在回调函数BufferEvent保存

在回调函数里保存图像,使用毫秒级的时间戳去存储图像的名称,C++调用代码如下所示:


//图像回调函数
//==================
void BGAPI2CALL BufferHandler( void * callBackOwner, Buffer * pBufferFilled )
{
	CGigeDemoDlg* pDlg = (CGigeDemoDlg*)callBackOwner;
	unsigned char* imagebuffer = NULL;
	USES_CONVERSION;
	try
	{
		if(pBufferFilled == NULL)
		{

		}
		else if(pBufferFilled->GetIsIncomplete() == true)
		{
			// queue buffer again
			pBufferFilled->QueueBuffer();
		}
		else
		{
			
			pDlg->FrameID= pBufferFilled->GetFrameID();                                                 //获取当前图像FrameID显示帧率

			int width = 0, height = 0;
			width = (int)pBufferFilled->GetWidth();height = (int)pBufferFilled->GetHeight();			//获取当前图像像素长宽
			CString PixelFormat1 = (CString)pBufferFilled->GetPixelFormat();							//获取当前图像像素格式
			imagebuffer = (BYTE*)((bo_int64)pBufferFilled->GetMemPtr()+pBufferFilled->GetImageOffset());//获取当前图像数据
			
			#pragma region //保存图像功能
			if(pDlg->m_bSaveImage &&!pDlg->m_strDirectory.IsEmpty())
			{			
				CTime time = CTime::GetCurrentTime(); 
				CString strtime1;
				strtime1.Format(_T("\\%4d%2d%2d%2d%2d%2d"),time.GetYear(),time.GetMonth(),time.GetDay(),time.GetHour(),time.GetMinute(),time.GetSecond());
				
				SYSTEMTIME st;
				GetSystemTime(&st);  // 获取系统时间,精确到毫秒
				int msecond = st.wMilliseconds;  // 获取毫秒数
				CString strtime;
				strtime.Format(_T("\\%s-%d"),strtime1,msecond);

				CString  strpath = pDlg->m_strDirectory+strtime+"-";

				pDlg->SaveImageMono(strpath, imagebuffer,width,height);
				pDlg->m_bSaveImage = false;
			}
			#pragma endregion 

			Gdiplus::Rect rc = Gdiplus::Rect(0,0,width,height);

			#pragma region 黑白相机代码:像素格式为mono时转Bitmap的代码,彩色相机此处代码不同
			if(pDlg->m_pBitmap == NULL)
			{
				pDlg->m_pBitmap = new Gdiplus::Bitmap(width,height,PixelFormat8bppIndexed);
			}
			Gdiplus::BitmapData lockedbits;
			Gdiplus::ColorPalette * pal = (Gdiplus::ColorPalette*)new BYTE[sizeof(Gdiplus::ColorPalette)+255*sizeof(Gdiplus::ARGB)];
			pal->Count=256;
			for(UINT i=0;i<256;i++)
			{
				UINT color=i*65536+i*256+i;
				color= color|0xFF000000;
				pal->Entries[i]=color;
			}
			pDlg->m_pBitmap->SetPalette(pal);


			Gdiplus::Status ret = pDlg->m_pBitmap->LockBits(&rc,Gdiplus::ImageLockModeWrite,PixelFormat8bppIndexed,&lockedbits);
			BYTE* pixels = (BYTE*)lockedbits.Scan0;
			BYTE* src = (BYTE*)imagebuffer;
			for (int row = 0; row < height; ++row) 
			{
				CopyMemory(pixels, src, lockedbits.Stride);
				pixels += width;
				src += width;
			}
			pDlg->m_pBitmap->UnlockBits(&lockedbits);
			#pragma endregion 

			#pragma region //将图像显示在PictureControl控件上
			HDC hDC = ::GetDC(pDlg->m_stcPicture.m_hWnd);
			Gdiplus::Graphics GdiplusDC(hDC);
			CRect rcControl;
			pDlg->m_stcPicture.GetWindowRect(&rcControl);
			Gdiplus::Rect rtImage(0,0,rcControl.Width(),rcControl.Height());
			GdiplusDC.DrawImage(pDlg->m_pBitmap,rtImage,0,0,width,height, Gdiplus::UnitPixel);
		
			delete []pal;
			::ReleaseDC(pDlg->m_stcPicture.m_hWnd,hDC);

			delete pDlg->m_pBitmap ;
			pDlg->m_pBitmap =NULL;
			#pragma endregion 

			// queue buffer again
			pBufferFilled->QueueBuffer();
		}
	}
	catch (BGAPI2::Exceptions::IException& ex)
	{
		CString str;
		str.Format(_T("ExceptionType:%s! ErrorDescription:%s in function:%s"),ex.GetType(),ex.GetErrorDescription(),ex.GetFunctionName());		
	}	
}

SaveImageMono保存图像内存作为图像的函数

bool CGigeDemoDlg::SaveImageMono(CString str,BYTE* bdata,int width,int height)
{		
	if (str.IsEmpty()) return false;
	
	HANDLE hFile = CreateFile(str,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
	//DWORD dwError = GetLastError();
	if (!hFile || hFile == INVALID_HANDLE_VALUE) 
		return false;
	
	// 
	BITMAPFILEHEADER	FileHeader;
	BITMAPINFOHEADER	InfoHeader;
	RGBQUAD rgbQuad[256];

	DWORD dwImageSize				= width*height;
	FileHeader.bfType				= 0x4D42; // "BM"
	FileHeader.bfSize				= sizeof(FileHeader) + sizeof(InfoHeader) + dwImageSize;
	FileHeader.bfReserved1			= FileHeader.bfReserved2 = 0;
	FileHeader.bfOffBits			= sizeof(FileHeader) + sizeof(InfoHeader);
	
	ZeroMemory(&InfoHeader, sizeof(InfoHeader));
	InfoHeader.biWidth				= width;
	InfoHeader.biHeight				= -height;
	InfoHeader.biSizeImage			= dwImageSize;
	InfoHeader.biBitCount			= 8;
	InfoHeader.biCompression		= BI_RGB;
	InfoHeader.biPlanes				= 1;
	InfoHeader.biSize				= sizeof(BITMAPINFOHEADER);
	InfoHeader.biXPelsPerMeter		= 0xEC4;
	InfoHeader.biYPelsPerMeter		= 0xEC4;

	for ( int i=0;i<256; i++ )
	{
		rgbQuad[i].rgbBlue = (BYTE)i;
		rgbQuad[i].rgbGreen = (BYTE)i;
		rgbQuad[i].rgbRed = (BYTE)i;
		rgbQuad[i].rgbReserved = 0;
	}

	DWORD Written;
	WriteFile(hFile, (LPVOID)&FileHeader,sizeof(BITMAPFILEHEADER),&Written, NULL);
	WriteFile(hFile, (LPVOID)&InfoHeader,sizeof(BITMAPINFOHEADER),&Written, NULL);
	WriteFile(hFile, (LPVOID)rgbQuad,256*sizeof(RGBQUAD),&Written,NULL);
	BYTE* src = bdata;
	//int stride = m_Width*4;
	

	//DWORD bytes = m_Width * 4;
	//for (unsigned long y = 0; y < NHEIGHT; y++) {
	WriteFile(hFile, (LPVOID)src,dwImageSize,&Written,NULL);
	//}
	CloseHandle(hFile);
	return true;
}

工业相机使用软触发进行同步采集

使用软件触发进行同步采集,C++调用代码如下所示:


m_pDevice->GetRemoteNode("TriggerMode")->SetString("Off"); //关闭触发模式,进入自由采集图片流模式
		m_pDevice->GetRemoteNode("AcquisitionStart")->Execute();
void CGigeDemoDlg::TriggerCameras()
{
	if (lisDev.Count ==2)
    {
        fullsavebmp1 = true; fullsavebmp2 = true;
        if ((lisDev[0]->GetRemoteNode("TriggerMode")->GetString() == "Software"
            || lisDev[0]->GetRemoteNode["TriggerSource"]->GetString() == "SoftwareTrigger")
            && (lisDev[1]->GetRemoteNode["TriggerSource"]->GetString() == "Software"
            || lisDev[1]->GetRemoteNode["TriggerSource"]->GetString() == "SoftwareTrigger"))
        {
            int count1 = 0;

            BGAPI2::Device * dev1 = lisDev[0];
            BGAPI2::Device * dev2 = lisDev[1];
            #pragma region 线程自动触发相机
			AfxBeginThread(AutoTriggerSoftwareThread1(dev1) , (void*)this);	
			AfxBeginThread(AutoTriggerSoftwareThread2(dev2) , (void*)this);			
			#pragma endregion  
         
        }

    }
    if (lisDev.Count == 1)
    {
        if ((lisDev[0]->GetRemoteNode("TriggerMode")->GetString() == "Software"
            || lisDev[0]->GetRemoteNode["TriggerSource"]->GetString() == "SoftwareTrigger"))
        {
                    
              dev->GetRemoteNode("TriggerSoftware")->Execute();
            
        }

    }
}

工业相机的软件触发命令线程函数

工业相机软件触发命令,C++调用代码如下所示:

UINT CGigeDemoDlg::AutoTriggerSoftwareRun1(LPVOID pParam)
{
	CGigeDemoDlg *dlg = (CGigeDemoDlg *)pParam;
	dlg->TriggerSoftwareRun1();
	return 0;
}

CString strtimeStart; 
void CGigeDemoDlg::TriggerSoftwareRun1()
{
	try
	{		
		bool m_bRun0 = true;
		while (m_bRun0)
		{
			dev->GetRemoteNode("TriggerSoftware")->Execute();    
			m_bRun0  = false;						
		}		
	}
	catch (int e)
	{
		MessageBox(_T("Camera FullFrameSaveimage Error"));
	}
}
UINT CGigeDemoDlg::AutoTriggerSoftwareRun2(LPVOID pParam)
{
	CGigeDemoDlg *dlg = (CGigeDemoDlg *)pParam;
	dlg->TriggerSoftwareRun2();
	return 0;
}

CString strtimeStart; 
void CGigeDemoDlg::TriggerSoftwareRun2()
{
	try
	{		
		bool m_bRun0 = true;
		while (m_bRun0)
		{
			dev->GetRemoteNode("TriggerSoftware")->Execute();    
			m_bRun0  = false;						
		}		
	}
	catch (int e)
	{
		MessageBox(_T("Camera FullFrameSaveimage Error"));
	}
}

`

Baumer工业相机的软件触发同步采集测试图

在这里插入图片描述

使用软件触发同步采集后保存的图像名称如下所示:
在这里插入图片描述

Baumer工业相机的高速同步采集功能的优势

  1. 高速同步采集: 堡盟工业相机具有高速同步采集功能,可以同时采集多个图像。这使它们成为时间至关重要的应用的理想选择,例如在机器视觉、机器人和自动化领域。

  2. 提高精度和准确度: 堡盟工业相机的高速同步采集使图像数据的准确性和精确性得到提高。这在需要进行高精确度测量的应用中尤为重要。

  3. 提高生产力: 堡盟工业相机具有一次采集多幅图像的能力,有助于提高制造业和其他工业流程的生产率。它们可以帮助实时识别错误和低效率,以便立即采取纠正措施。

  4. 定制化: 堡盟工业相机可进行定制,以满足不同应用的具体需求。它们提供各种选项,包括分辨率、帧率和动态范围。

  5. 耐用性: 堡盟工业相机的设计能够承受恶劣的环境,并且经久耐用。它们能抵抗冲击和振动,并能在极端温度下工作,使它们适合在工业和制造业环境中使用。

Baumer工业相机的高速同步采集功能的行业应用

  1. 汽车行业: 在汽车行业,高速相机被用来捕捉移动物体的图像,如车辆、行人和骑自行车的人。这些数据被用于各种应用,包括避免碰撞系统、高级驾驶辅助系统和自动停车系统。

  2. 制造行业: 在制造业中,高速相机被用来监测装配线和流程,检查缺陷,并确保质量控制。它们还被用来捕捉快速移动的机器和设备的图像,用于维护和排除故障。

  3. 制药业: 在制药业,高速相机被用来捕捉药物开发和测试过程的图像,包括分析液体、气溶胶和悬浮液中颗粒的行为。

  4. 体育行业: 在体育行业,高速相机被用来捕捉运动员运动中的图像,使教练和训练员能够分析技术并作出调整,以达到最佳表现。

  5. 航空航天工业: 在航天工业中,高速相机被用来捕捉飞机在测试和开发过程中的图像,包括分析风洞测试和高速飞行。

这些只是多工业相机的高速同步采集功能的几个行业应用。该技术在各行业还有很多应用。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【观察】华为:新一代楼宇网络,使能绿建智慧化

“碳达峰”、“碳中和”目标是我国生态文明建设和高质量可持续发展的重要战略安排&#xff0c;将推动全社会加速向绿色低碳转型。作为全球既有建筑和每年新建建筑量最大的国家&#xff0c;大力发展绿色建筑对中国全方位迈向低碳社会、实现高质量发展具有重要意义。 《“十四五”…

使用FirmAE 对zyxel路由器固件仿真实践 | 信息安全

一、FirmAE简介 FirmAE 是一个执行仿真和漏洞分析的全自动框架。FirmAE 使用五种仲裁技术显著提高仿真成功率&#xff08;从Firmadyne的 16.28% 提高到 79.36%&#xff09;。 FirmAE的整体架构为如上图所示。与Firmadyne类似&#xff0c;FirmAE在预先构建的自定义Linux内核和库…

Codeforces Round 816 (Div. 2)(C. Monoblock)

传送门 题意&#xff1a; 定义一个数组&#xff0c;定义它 相等连续段的个数 如1,2,2,1&#xff0c;相等连续段有[1],[2,2],[1]&#xff0c;共3个 如2,2,2,1&#xff0c;相等连续段有[2,2,2],[1]&#xff0c;共2个 给定一个数组a&#xff0c;定义g(l,r)为&#xff0c;子数组中…

fisco bcos 2.0+ 版本浏览器搭建

Fisco Bcos当前已经发布了3版本&#xff0c;在3版本中&#xff0c;Fisco摒弃了原有的区块链浏览器&#xff0c;而是提供了具有更为丰富功能的图形化区块链管理工具WeBase&#xff0c;后续也会提供对于WeBase的搭建部署教程。 文章目录 一、准备条件二、下载浏览器安装脚本1. 下…

ChatGPT4 的体验 一站式 AI工具箱 -—Poe(使用教程)

最近由于人工智能聊天机器人的爆火(ChatGPT)&#xff0c;因此各种各样的AI助手流行与网络&#xff0c;各种各样的都有&#xff0c;不论是什么样的其实都是为了我们更方便的解决问题&#xff0c;今天介绍一款AI工具箱——Poe将多种AI集成与一个界面&#xff0c;大家可以一次感受…

Mac系统brew报错“The GitHub credentials in the macOS keychain may be invalid”解决

报错信息如下&#xff1a; $ brew search nginx Warning: Error searching on GitHub: GitHub API Error: Requires authentication The GitHub credentials in the macOS keychain may be invalid. Clear them with: printf "protocolhttps\nhostgithub.com\n" | …

Python双向链表的操作

目录 一、双向链表 双向链表示例图 二、双向链表的操作 1、判断链表是否为空 2&#xff0c;链表长度 3&#xff0c;遍历整个链表 4&#xff0c;在链表头部添加元素 5、链表尾部添加元素 6&#xff0c;在指定位置插入元素 7&#xff0c;修改指定位置的元素 8&#xff0…

百度ai智能写作工具-百度ai自动写文章

百度AI智能写作工具&#xff1a;让创作更快捷、高效&#xff01; 在当今竞争激烈的文化创意市场中&#xff0c;创作一篇高质量的文章需要投入大量时间和精力。然而&#xff0c;有了百度AI智能写作工具&#xff0c;创作变得更快捷、高效了。 百度AI智能写作工具采用最先进的人…

JVM之垃圾回收器概述

目录 垃圾收集器分类 按线程数分 按照工作模式分 ​编辑 按碎片处理方式分 按工作的内存区间分 评估GC的性能指标 吞吐量 暂停时间 吞吐量 vs 暂停时间 垃圾回收器概述 垃圾收集器没有在规范中进行过多的规定&#xff0c;可以由不同的厂商、不同版本的JVM来实现。 由…

一起学 WebGL:感受三维世界之视图矩阵

大家好&#xff0c;我是前端西瓜哥。之前绘制的图形都是在 XY 轴所在的平面上&#xff0c;这次我们来加入一点深度信息 z&#xff0c;带你走入三维的世界。 视图矩阵 对于一个立方体来说&#xff0c;我们从它的正前方看&#xff0c;不管距离它多远&#xff0c;也只能看到一个…

微服务下网关聚合Swagger文档、starter统一配置Swagger

一、starter实现统一配置微服务文档 把Swagger配置中的公共部分抽取出来Swagger与SpringBoot整合中&#xff0c;可能会由于版本问题出现各种问题 1、制作starter 参考&#xff1a; 【SpringBoot】自定义启动器 Starter【保姆级教程】用starter实现Oauth2中资源服务的统一配置用…

中级软件设计师备考---数据库系统1

目录 数据库模式数据库的设计过程E-R模型关系代数与元组演算 数据库模式 三级模式、两级映射 定义&#xff1a; 三级模式&#xff1a;外模式、概念模式和内模式&#xff1b;两级映射&#xff1a;外模式-概念模式映射、概念模式-内模式映射 外模式是用户看到的数据库的部分 概…

Linux的常见指令 -掌握

前言 为什么要学命令行&#xff1f; windows/苹果图形界面&#xff0c;是商业化的产物&#xff0c;也就是使用必须简单小白&#xff0c;才能有人用&#xff0c;so what&#xff1f;严格意义上讲&#xff0c;我们必须要学一下Linux命令行。因为企业后端有大量的服务器&#xff…

Web3.0:重新定义互联网的未来

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; Web3.0&#xff1a;重新定义互联网的未来 Web3.0是指下一代互联网&#xff0c;也称为“分布式互联网”。相比于Web1.0和Web2.0&#xff0c;Web3.0具有更强的去中心化、…

如何快速查找下载外文文献,哪个文献下载网站好用

​​如何高效获取到自己需要的外文文献&#xff0c;最好的办法就是去文献来源数据库中查找&#xff0c;你需要的文献来源数据库有可能是Elsevier&#xff08;sciencedirect&#xff09;、也可能是Wiley Online Library、也有可能是IEEE等等&#xff0c;外文数据库机构太多了。这…

微信跨平台方案Donut快速上手

一、Donut简介 Donut 是微信开发出的多端框架&#xff0c;用于支持使用小程序原生语法开发移动应用的框架&#xff0c;开发者可以一次编码&#xff0c;就可以编译出小程序和 Android 以及 iOS 应用&#xff0c;实现多端开发。能够帮助企业有效降低多端应用开发的技术门槛和研发…

html画布绘制图形

一.题目要求 使用canvas标签完成直角三角形、矩形及圆形的绘制. 二.相关知识点 1.认识<canvas> 标签翻译&#xff1a;画布。 <canvas> 标签定义图形&#xff0c;比如图表和其他图像&#xff0c;您必须使用脚本来绘制图形。 <canvas> 标签只是图形容器&am…

[学习笔记] [机器学习] 2. Seaborn及练习案例

视频链接 数据集下载地址&#xff1a;https://download.csdn.net/download/weixin_44878336/87711308 目录 1. 绘制统计图形1.1 可视化数据的分布1.2 绘制单变量分布1.3 绘制双变量分布1.4 绘制成对的双变量分布 2. 用分类数据绘图2.1 类别散点图2.1.1 sns.stripplot()2.1.2 sn…

Hi3861 硬件 i2c 驱动 oled

一、前言 最近想用 3861 做个有意思的东西&#xff0c;记录一下开发过程。今天使用 3861 的硬件 i2c 驱动 oled。 硬件平台&#xff1a;Bearpi-Nano 软件SDK&#xff1a;润和sdk 二、搬一个 OLED 轮子 我之前写过一篇基于 stm32cubemx 快速使用 iic 接口 oled 的过程&#xff0…

一文搞懂C#实时调试时,程序数据库文件.pdb(符号文件)的作用。延伸搞懂Debug/Release、AnyCPU(首选32位)/x86/x64/ARM的区别

一、准备工作 MS引用&#xff1a;在 Visual Studio 调试器&#xff08;C#、C、Visual Basic、F#&#xff09;中指定符号 (.pdb) 和源文件 MS引用&#xff1a;为 C#、ASP.NET 或 Visual Basic 项目 &#xff08;.NET Framework&#xff09; 生成符号文件 MS引用&#xff1a;用…