文章目录
前言
本文介绍了Baumer相机BGAPI 2的使用方法以及相机采集Demo的开发流程 。
一、BGAPI2是什么?
Baumer GAPI是 Baumer Generic Application Programming Interface(堡盟通用应用程序编程接口)的缩写。通过这个API,Baumer提供了一个对堡盟相机的最佳集成和控制的接口。Baumer GAPI的基本基础是GenICam(相机通用接口)标准和GenTL作为标准化接口的使用。Baumer GAPI提供了与多种编程语言的接口,如C++的接口和.NET™框架在®操作系统上的应用,这反过来说,该API又允许使用其他语言,如C#或VB。
二、使用说明
1.Baumer BGAPI2 文件内容的分布
如果您手边还没有Baumer BGAPI 2.12的整套文件开发包,请在以下链接下载您需要的文件:
链 接 :https://bianchenghao.cn/s/1jyozD7v4mfchzbv2GtnGig 提取码:puol
在您下载完成整个文件包后,解压缩以后可以看到如下图所示的整个文件夹中子文件夹及文件的分布。
如下图示
BGAPI2的主要内容分布如下:
1)bin:包括开发需要的一些库文件
2)docs :主要是一些说明文档,包括开发说明,软件说明,相机说明以及数据手册等;
3)drivers:里面是USB3.0和GigE驱动,软件安装的时候。默认安装USB3.0的驱动,千兆网的Filter Driver需要手动安装;
4)examples:里面是一些开发例程
5)include,lib:里面是开发用的头文件
6)tools:里面是使用操作Baumer相机用到的文件,包括整体的采集软件,GigE相机的IP配置工具等;
2.使用VC++用到的库文件,引用文件分析
在使用VC++的时候,要用到一些库文件,如上面文件布局分析中提到的我们在文件夹中会用到如下的文件:
其中比较重要的是Bin文件夹里面的文件以及include、lib文件夹里面的文件;
引用文件介绍
1)其中Bin文件夹中,如图所示 注:开发时注意区分Baumer_GAPI_SDK_2.12.0_win_x86_cpp和Baumer_GAPI_SDK_2.12.0_win_x86_64_cpp,内部的内容是一样的,只不过一个是针对Windows 32位系统,一个针对Windows 64位系统;
文件夹里是在相机二次开发编程过程中使用到的System文件,内部分Baumer BGAPI 2.x SDK支持的两种接口相机所需要的System文件,即USB3.0、GigE两种接口;
所谓的System实际上就是创建不同类型接口相机的最上层的管理者,所有资源起始于System,首先通过创建System来搜索创建对应接口类型的相机设备;
2) include、lib文件夹里面是客户二次开发所需要的库文件,头文件等 内部分布如下图所示:
①C_C++ 是使用C或C++二次开发所需要的头文件和lib库文件;
②C_Sharp 是使用VB.net 或 C#开发所需要的引用文件“bgapi2_genicam_dotnet.dll”(该文件在Bin文件夹中)
3)Examples文件夹为C++和C#开发的例程。
C++和C#的例程为都是基于控制台的程序,其中C++的例程需要使用CMake来针对使用的Visual Studio的版本来生成对应的工程,
CMake的安装文件在上层Baumer_GAPI_SDK_2.12.0_win_x86_64_cpp\tools\CMake的文件夹中,请安装使用;
3.怎样在VC++下开发第一个Baumer相机的应用程序
以VC++平台下MFC程序为例,一步一步介绍怎样开发一个VC++的程序,由于Baumer相机具有太多的功能,不可能在有限的篇幅下将所有的功能的代码一一详述,在此只针对客户常用的几个功能做叙述,由于Baumer相机的SDK功能的编程上面几乎是全部相通的,
因此掌握其中常用的几个功能之后,基本上的流程也就基本上掌握了,然后配合Baumer提供的帮助文件,基本上也可以独立解决绝大多数问题了;
下面开始介绍,怎样来使用VC++来开Baumer相机使用的程序:
该例程的详细代码,请到下面的链接下载,参阅学习,该例程仅包含了Baumer相机的图像采集显示,曝光,增益调节,保存单张图像,相机的Trigger设置这几个功能
① 首先创建一个VC++下的MFC应用程序,并做命名,并命名为BGAPI2Demo,如下图所示;
并创建一个基于对话框的MFC程序,如下图所示: 创建完成之后,接下来,做好窗体上控件的添加布局之后,就可以正式的开始编程了;
②添加工程开发Baumer应用程序所需要的引用文件,如下面所示请在 请首先早工程目录下,已上面创建的BGAPI2Demo为例,在BGAPI2Demo.vcxproj文件所在的目录下,创建两个文件夹,分别为Inc和Lib文件夹,分别用来存放程序工程所需要的开发头文件以及lib文件(也可以根据自己的喜好选择路径),如下图所示:
请将上面开始部分介绍的Baumer_GAPI_SDK_2.12.0_win_x86_64_cpp\include中的文件拷贝到此工程目录下上面创建的Inc文件夹中, 将Baumer_GAPI_SDK_2.12.0_win_x86_64_cpp\lib文件拷贝到上面创建的Lib文件夹中,如下图所示;
③完成上述工作之后,完成工程的设置,包括工程所需头文件,库文件的属性设置,让工程获取头文件,库文件的目录及要添加的添加的库文件:
1)头文件的目录添加 如下图所示,请在BGAPI2Demo上面 右键---属性,在BGAPI2Demo属性页中 配置属性—C/C++,然后在 附加包含目录 中输入头文件相对路径 ./Inc (路径的输入请根据具体头文件的存储目录输入合适的值,上面的相对路径只是因为创建工程时的需要而作的选择,也可以自己使用合适的相对路径或绝对路径)
2)库文件的引用于路径添加 如下图所示,请在BGAPI2Demo上面 右键---属性,在BGAPI2Demo属性页中配置属性 ---链接器----常规 中的 附加库目录 中输入相对路径 ./Lib (路径的输入请根据具体头文件的存储目录输入合适的值,上面的相对路径只是因为创建工程时的需要而作的选择,也可以自己使用合适的相对路径或绝对路径)
3)在添加完库文件的相对路径之后,添加库文件的名称,请在BGAPI2Demo上面 右键---属性,在BGAPI2Demo属性页中配置属性 ---链接器----输入 中的 附加依赖项 中输入 bgapi2_genicam.lib,如下图所示: 在添加成功后,开始下一步的编程;
编程的第一步,请导入需要的库,Baumer相机二次开发中在添加引用之后,需在工程的目录里面加入
#include "bgapi2_genicam.hpp"
using namespace BGAPI2;
Baumer在VC++下在不涉及参数调节的情况涉及两套类对象,一种为对象容器(List)类,这些类顾名思义就是用来存储所有需要创建具体操作对象的一个容器对象,
主要包含:
BGAPI2::SystemList、BGAPI2::InterfaceList、BGAPI2:: DeviceList 、 BGAPI2::StreamList、BGAPI2::BufferList
第二种为操作对象类,主要包含:
BGAPI2::System、BGAPI2::Interface、BGAPI2:: Device 、 BGAPI2::Stream、BGAPI2::Buffer
其中
System的实际意义为:定义的某种接口总称,该API下分为U3V(USB3.0相机的System总称)和GEV(千兆网口相机的System总称),所有的System存在于SystemList中需要逐一创建,实例化;
Interface的实际意义是:针对网口则是对应的具体一个网络端口,针对USB3是一个实际的USB3.0接口,InterfaceList是存储了所有同一个System下Interface的容器;通过遍历InterfaceList中的Interface来实例化某个接口;
Device的实际意义是: 具体的某一个设备,如U3相机或者网口相机,为物理意义上的设备对象,相机的可调参数基本上由Device对象来实现,DeviceList为同一Inteface下存储所有Device的容器,比如说某一个具体的网口下可能连着1台GigE相机,或者通过交换机连接有多个GigE相机;
Stream的实际意义为:特定Device设备与PC端数据交互的一个数据流通道,一般一台相机只有一个数据流通道,而StreamList为存储Stream的一个容器;
Buffer的实际意义是:用来接收图像的缓存区,可以定义一定数目的Buffer,并添加到具体的Stream中,用来接收相机传输的数据,理论上Stream里面的buffer越多,相机传输的越稳定;
如下图所示:
④ 在正式开始代码编写之前请先将上面提到过的System相关的文件拷贝, 在程序调试(Debug)或者发布(Release)的可执行文件(.exe)文件夹中去,
具体的文件目录为:Baumer_GAPI_SDK_2.12.0_win_x86_64_cpp\bin
如图所示,Debug文件夹下拷贝入相关文件:
以上共25个文件,请务必拷贝到上面所述的对应文件夹中;
⑤ 正式开始编程,以下将叙述从相机创建,捕捉图像的整体过程,整个开发的过程依次顺序如下;
整个的开发流程如下:
注:BGAPI2所有代码都没有错误返回值,只能通过Try.....Catch(BGAPI2::Exceptions::IException& ex)抛出的异常来判断里面的指令是否正常执行,然后在ex中可以来定位错误代码和错误的描述,具体请参看BGAPI2::Exceptions::IException的定义
1.实例化SystemList
m_pSystemList = SystemList::GetInstance(); m_pSystemList->Refresh();
注:SystemList为单例模式的对象,在最后请使用ReleaseInstance来释放,如果安装了Baumer的软件,SystemList会自动搜索Baumer定义的环境变量指定的位置的系统文件,如果没有安装Baumer的软件,请将Baumer_GAPI_SDK_2.12.0_win_x86_64_cpp\bin内的文件复制至创建的工程的工作目录下;
2.实例化SystemList中的System类,在此例程中我们仅初始化一个GigE的System
如果同时使用USB3和GigE接口相机,则需要创建两个System,并分别实例化;
try { BGAPI2::SystemList *systemList = BGAPI2::SystemList::GetInstance(); systemList->Refresh(); for (BGAPI2::SystemList::iterator it_s = systemList->begin(); it_s != systemList->end() && camfound == 0; it_s++) { BGAPI2::System *pSystem = *it_s; // gige, usb3, .. pSystem->Open(); } if (camfound == 0) { std::cout << "no camera found on any system or interface." << std::endl; } } catch (BGAPI2::Exceptions::IException& ex) { returncode = (returncode == 0) ? 1 : returncode; std::cout << "Error in function: " << ex.GetFunctionName() << std::endl << "Error description: " << ex.GetErrorDescription() << std::endl << std::endl; } BGAPI2::SystemList::ReleaseInstance(); std::cout << "Input any number to close the program:"; int endKey = 0; std::cin >> endKey; return returncode;
3.实例化其下面连接的Device多余一个的Interface对象
注: 此处只实例化一个Interface,如果有多个相机,并且多个相机挂载在不同的Interface(如:网口)下那么就需要使用一个容器(如vector)来将所有的下面挂载≧1个Device的Interface实例化;
4.实例化一个Device,其为具体实例化的某个Interface下的Device
注: 此处只实例化一个Device,而且该Device来源于上面创建的Interface,如果有多个Interface下挂载≧1个相机Device,则需要每个Interface都要来寻找DeviceList; 如果每个Interface下所有的相机(如使用交换机,则每个Interface下有多个相机Device)都要创建,就需要使用一个容器(如vector)来将所有的Device实例化; 当然如果没有使用交换机,那么每个Interface下就只有1个Device,打开创建Device对象就可以了;
5.实例化DataStream,其为具体的某个Device下的DataStream:
6.实例化多个Buffer对象,并将其添加到该相机的BufferList中:
注: 此处只实例化了4个Buffer用来接收图像,原理上Buffer越多,采集图像越稳定,但是要考虑PC实际的内存大小,以及所选相机的每帧图像大小
7.注册回调函数,并开启连续采集模式
其中回调函数的定义原型如下:
其中pBufferFilled为每帧图像传输过来的数据;
内部需要做的工作主要
注: 每次进入回调函数之后在取完之后一定要执行pBufferFilled->QueueBuffer();使其继续进入BufferList中用来接收图像,否则在BufferList里的Buffer取完(上面例子中4个Buffer)之后,相机将不再传输图像
8.资源释放,在软件关闭,程序退出的时候,需要将创建的资源逐一关闭并释放,资源关闭释放的顺序跟创建的顺序正好相反;
4.相机参数的设置
BGAPI2有一个比较方便的特性就是,所有相机的参数全部都是同一个函数接口,唯一不同的是该函数参数的字符串,以及该相机参数值得属性(字符,整数,浮点数,Bool型)
相机开始采集的代码: 1)m_pDevice->GetRemoteNode("AcquisitionStart")->Execute(); 相机暂停采集的代码: 2)m_pDevice->GetRemoteNode("AcquisitionStop")->Execute(); 相机曝光时间的设置代码为: 3)m_pDevice->GetRemoteNode("ExposureTime")->SetDouble(6000.00); 相机增益设置的代码为: 4)m_pDevice->GetRemoteNode("Gain")->SetDouble(2.100); 开启相机触发模式的设置代码为: 5)m_pDevice->GetRemoteNode("TriggerMode")->SetString(“On”); 相机触发源的代码为: 6)m_pDevice->GetRemoteNode("TriggerSource")->SetString(“Line0”); 开启相机帧率固定模式的设置代码为: 7)m_pDevice->GetRemoteNode("AcquisitionFrameRateEnable")->SetBool(true); 开启相机图像ROI的高度的设置代码为: 8)m_pDevice->GetRemoteNode("Height")->SetInt(800);
根据相机某个参数值得属性来设置修改相机的参数,使用的是参数的命名,并且函数接口全部为 Node* Device::GetRemoteNode(String name),有兴趣的话可以查看Node的定义来加深认识;
在使用过程中,可能会存在想使用修改某些参数,但是却苦于不知道该相机参数的命名是什么,这个时候该怎么办呢,Baumer提供的CameraExplorer可以帮助您很方便的完成参数的设定: Baumer的CameraExplorer评估软件,所有的操作信息都可以在界面上显示
对应上面的次序与标号,分别如何在CameraExplorer上如何操作,以及在信息输出部分对应操作的实现方式,都可以一一显示,在不知道相机某个属性的命名的时候,只需要在Baumer提供的CameraExplorer上操作一遍,然后在复制命名加入到自己的代码中就可以了:
5.Short Example代码,供参考
/* Copyright 2019-2020 Baumer Optronic */ #include <stdio.h> #include <iostream> #include "bgapi2_genicam/bgapi2_genicam.hpp" int main() { int returncode = 0; int camfound = 0; try { BGAPI2::SystemList *systemList = BGAPI2::SystemList::GetInstance(); systemList->Refresh(); for (BGAPI2::SystemList::iterator it_s = systemList->begin(); it_s != systemList->end() && camfound == 0; it_s++) { BGAPI2::System *pSystem = *it_s; // gige, usb3, .. pSystem->Open(); BGAPI2::InterfaceList *interfaceList = pSystem->GetInterfaces(); interfaceList->Refresh(100); for (BGAPI2::InterfaceList::iterator it_i = interfaceList->begin(); it_i != interfaceList->end() && camfound == 0; it_i++) { BGAPI2::Interface *pInterface = *it_i; pInterface->Open(); BGAPI2::DeviceList *deviceList = pInterface->GetDevices(); deviceList->Refresh(100); if (deviceList->size() > 0) { BGAPI2::Device *pDevice = *(deviceList->begin()); pDevice->Open(); std::cout << pDevice->GetModel() << "(" << pDevice->GetSerialNumber() << ")" << std::endl; pDevice->GetRemoteNode("TriggerMode")->SetString("Off"); BGAPI2::String sExposureNodeName = ""; if (pDevice->GetRemoteNodeList()->GetNodePresent("ExposureTime")) { sExposureNodeName = "ExposureTime"; } else if (pDevice->GetRemoteNodeList()->GetNodePresent("ExposureTimeAbs")) { sExposureNodeName = "ExposureTimeAbs"; } pDevice->GetRemoteNode(sExposureNodeName)->SetDouble(10000.0); BGAPI2::DataStreamList *datastreamList = pDevice->GetDataStreams(); datastreamList->Refresh(); BGAPI2::DataStream *pDataStream = (*datastreamList)[0]; pDataStream->Open(); BGAPI2::BufferList *bufferList = pDataStream->GetBufferList(); BGAPI2::Buffer * pBuffer = NULL; for (int i = 0; i < 4; i++) { pBuffer = new BGAPI2::Buffer(); bufferList->Add(pBuffer); pBuffer->QueueBuffer(); } pDataStream->StartAcquisitionContinuous(); pDevice->GetRemoteNode("AcquisitionStart")->Execute(); BGAPI2::Buffer * pBufferFilled = NULL; for (int i = 0; i < 12; i++) { pBufferFilled = pDataStream->GetFilledBuffer(1000); if (pBufferFilled == NULL) { std::cout << "Error: Buffer Timeout after 1000 msec" << std::endl; } else if (pBufferFilled->GetIsIncomplete() == true) { std::cout << "Error: Image is incomplete" << std::endl; pBufferFilled->QueueBuffer(); } else { std::cout << " Image " << pBufferFilled->GetFrameID() << " received. " << std::endl; pBufferFilled->QueueBuffer(); } } if (pDevice->GetRemoteNodeList()->GetNodePresent("AcquisitionAbort")) { pDevice->GetRemoteNode("AcquisitionAbort")->Execute(); } pDevice->GetRemoteNode("AcquisitionStop")->Execute(); pDataStream->StopAcquisition(); bufferList->DiscardAllBuffers(); while (bufferList->size() > 0) { pBuffer = *(bufferList->begin()); bufferList->RevokeBuffer(pBuffer); delete pBuffer; } pDataStream->Close(); pDevice->Close(); camfound = 1; } pInterface->Close(); } pSystem->Close(); } if (camfound == 0) { std::cout << "no camera found on any system or interface." << std::endl; } } catch (BGAPI2::Exceptions::IException& ex) { returncode = (returncode == 0) ? 1 : returncode; std::cout << "Error in function: " << ex.GetFunctionName() << std::endl << "Error description: " << ex.GetErrorDescription() << std::endl << std::endl; } BGAPI2::SystemList::ReleaseInstance(); std::cout << "Input any number to close the program:"; int endKey = 0; std::cin >> endKey; return returncode; }
今天的文章
Baumer(堡盟)工业相机SDK开发 C++分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/104525.html