机器视觉之Basler工业相机使用和配置方法(C++)

basler工业相机做双目视觉用,出现很多问题记录一下:

首先是多看手册:https://zh.docs.baslerweb.com/software

手册内有所有的源码和参考示例,实际上在使用过程中,大部分都是这些源码,具体项目选择对应的示例代码。

一、相机和镜头选型

可以通过balser的镜头选型工具,按照自己需要策略目标的距离,目标大小等信息进行配置选择,地址在这;界面如下:
在这里插入图片描述
相机的焦距大小一般和测量的目标距离有关系,一般对应的选择方式总结如下:
(1)焦距越小,测量的范围越大,相应的,目标一般都看起来很小,类似于手机拍照的最小倍数拍摄目标;
(2)焦距越大,测量范围就越窄,对远距离小目标的检查就比较好,但是太大的焦距会导致大目标容易拍不全,类似与手机拍照放大倍数拍摄目标;
(3)具体有计算公式,可以参考,建议直接通过basler的配置工具进行选择

二、相机安装和使用

(1)balser相机使用需要网线和电源线(12V供电),可以在官网找对应的线材;
(2)相机接上电源,网线连接计算机后,去官网下载相机软件和驱动,一般windows下安装后,会在目录下生成对应的文件夹,包括C++对应的库和参考代码示例等,linux下直接下载tar.gz包,解压防止到对应的文件目录下,执行:source pylon目录/bin/pylon-setup-env.sh ./pylon目录 即可,例如我安装的是pylon7.3.0,解压后的目录为:/opt/pylon7,里面直接就是inlcude这些文件夹,在linux下目录执行:

source /opt/pylon7/bin/pylon-setup-env.sh /opt/pylon7

完成linux下相机驱动和环境的安装。
(3)配置相机IP,windows下配置相机IP可以使用basler的工具:
ipconfigurator,Linux下如果安装的系统有GUI界面,一样可以使用,配置相机IP地址,保证IP地址和接计算机的接口IP地址在同一网段即可,子网掩码推荐255。255.255.0,厂家说其他的可能会出现异常断开错误;
(4)IP配置完成后,在windows下启动pylon Viewer工具,查看相机,能找到相机说明IP配置正确,确保计算机和相机处于同一个网段内
(5)要保持basler相机的帧率,需要保证千兆网,如果是两个相机,连交换机之后就要求是2000M的网,依次类推,才可以达到最大帧率,否则会出现相机丢帧等问题,直连相机到计算机不影响,开启巨帧数就行了。

三、C++调用相机环境部署

1.相机驱动和软件安装完成后,有以下文件夹:

开发环境在development文件夹下,linux下解压之后是:
在这里插入图片描述
2.可以使用visua studio等C++ IDE开发工具进行编程,将依赖库和头文件等信息通过链接include和lib文件,即可开始相机调用;

四、C++相机调用

1.相机初始化:

相机初始化包括寻找相机,匹配对应相机,还可以设置相机的曝光,帧率,增益等,两个相机的初始化,依据API文档整理如下:
参加API:Grab_MultipleCameras

void initCamera()
{try{PylonInitialize();	//初始化CTlFactory& tlFactory = CTlFactory::GetInstance();pTL = dynamic_cast<IGigETransportLayer*>(tlFactory.CreateTl( BaslerGigEDeviceClass ));if (pTL == NULL){throw RUNTIME_EXCEPTION( "No GigE cameras available." );}DeviceInfoList_t allDeviceInfos;if (pTL->EnumerateDevices( allDeviceInfos ) == 0){throw RUNTIME_EXCEPTION( "No GigE cameras available." );}DeviceInfoList_t usableDeviceInfos;string left_camera_ip="172.16.105.21"//left_camera_ip 用于区分两个相机,可以通过配置的IP,序列号等进行区分if (string(allDeviceInfos[0].GetIpAddress()) == left_camera_ip) {usableDeviceInfos.push_back(allDeviceInfos[0]);subnet = allDeviceInfos[0].GetSubnetAddress();//主相机usableDeviceInfos.push_back(allDeviceInfos[1]);LOG(INFO)<<"主相机:"<<allDeviceInfos[0].GetIpAddress()<<endl;LOG(INFO)<<"副相机:"<<allDeviceInfos[1].GetIpAddress()<<endl;}else if(string(allDeviceInfos[1].GetIpAddress()) == left_camera_ip) {usableDeviceInfos.push_back(allDeviceInfos[1]);subnet = allDeviceInfos[1].GetSubnetAddress();//主相机usableDeviceInfos.push_back(allDeviceInfos[0]);LOG(INFO)<<"主相机IP:"<<allDeviceInfos[1].GetIpAddress()<<endl;LOG(INFO)<<"SubnetAddress:"<<allDeviceInfos[1].GetSubnetAddress()<<endl;LOG(INFO)<<"DefaultGateway:"<<allDeviceInfos[1].GetDefaultGateway()<<endl;LOG(INFO)<<"SubnetMask:"<<allDeviceInfos[1].GetSubnetMask()<<endl;LOG(INFO)<<"副相机IP:"<<allDeviceInfos[0].GetIpAddress()<<endl;LOG(INFO)<<"SubnetAddress:"<<allDeviceInfos[0].GetSubnetAddress()<<endl;LOG(INFO)<<"DefaultGateway:" <<allDeviceInfos[0].GetDefaultGateway()<<endl;LOG(INFO)<<"SubnetMask:"<<allDeviceInfos[0].GetSubnetMask()<<endl;}else{LOG(INFO) << "Camera IP is error ,please set IP" << endl;}// CInstantCameraArray cameras = { 2 };//初始化两个相机for (size_t i = 0; i < 2; ++i){cameras[i].Attach(tlFactory.CreateDevice(usableDeviceInfos[i]));const CBaslerGigEDeviceInfo& di = cameras[i].GetDeviceInfo();LOG(INFO) << "Camera serial: " << di.GetSerialNumber() << endl;}//        srand( (unsigned) time( NULL ) );
//        DeviceKey = rand();
//        GroupKey = 0x112233;for (size_t i = 0; i < cameras.GetSize(); ++i){cameras[i].Attach( tlFactory.CreateDevice( usableDeviceInfos[i] ) );//cameras[i].RegisterConfiguration( new CActionTriggerConfiguration( DeviceKey, GroupKey, AllGroupMask ), RegistrationMode_Append, Cleanup_Delete );//cameras[i].SetCameraContext( i );const CBaslerGigEDeviceInfo& di = cameras[i].GetDeviceInfo();cout << "Using camera " << i << ": " << di.GetSerialNumber() << " (" << di.GetIpAddress() << ")" << endl;}cameras.Open();//相机基本设置SetCamera(cameras[0], Type_Basler_ExposureTimeAbs, expore_time_l);			//曝光时间SetCamera(cameras[0], Type_Basler_GainRaw, gain_l);						//增益SetCamera(cameras[0], Type_Basler_AcquisitionFrameRateAbs, fps_l);			//频率SetCamera(cameras[0], Type_Basler_Width, 2448);SetCamera(cameras[0], Type_Basler_Height, 2048);SetCamera(cameras[1], Type_Basler_ExposureTimeAbs, expore_time_r);			//曝光时间SetCamera(cameras[1], Type_Basler_GainRaw, gain_r);						//增益SetCamera(cameras[1], Type_Basler_AcquisitionFrameRateAbs, fps_r);			//频率SetCamera(cameras[1], Type_Basler_Width, 2448);SetCamera(cameras[1], Type_Basler_Height, 2048);//设置相机触发模式 	TriggerSelector//TriggerSoftware//主相机设置为软件触发,输出设置为exposure active//SetCamera(cameras[0], Type_Basler_Freerun, 0);//从相机设置:触发模式为外触发,IO设置为1//SetCamera(cameras[1], Type_Basler_Line1, 0);}catch (const GenericException& e){if(cameras.IsGrabbing())cameras.StopGrabbing();// Error handlingLOG(INFO) << "init,An exception occurred." << endl<< e.GetDescription() << endl;}
}

2.调用相机

调用相机时,最容易出现的问题是,grab image丢帧,在抓取图像丢帧的原因中,主要是由相机帧率设置过大,带宽不足等问题导致。
其中:
if(cameras.IsGrabbing()) 这句可以改成while循环,这样就可以持续输出,if表示就近输出了,根据实际使用情况而定,基本上抓取一帧在50ms左右。

void GetCameraImage() {try {//pTL->IssueActionCommand(DeviceKey, GroupKey, AllGroupMask, subnet );//1秒内抓取了多少张图,全部存下来int skiptime = 1000;//LOG(INFO)<<"采集图像的最长时间:"<<skiptime<<" ms"<<endl;cameras.StartGrabbing(GrabStrategy_OneByOne,GrabLoop_ProvidedByUser);if(cameras.IsGrabbing()) {std::chrono::high_resolution_clock::time_point tStartTime(std::chrono::high_resolution_clock::now());int lTimeAloInterval = 0;count_grab_once++;cameras[0].RetrieveResult(skiptime, ptrGrabResultl, TimeoutHandling_ThrowException);cameras[1].RetrieveResult(skiptime, ptrGrabResultr, TimeoutHandling_ThrowException);if (ptrGrabResultl->GrabSucceeded() && ptrGrabResultr->GrabSucceeded() ) {intptr_t cameraContextValuel = ptrGrabResultl->GetCameraContext();intptr_t cameraContextValuer = ptrGrabResultr->GetCameraContext();const uint8_t *pImageBufferl = (uint8_t *) ptrGrabResultl->GetBuffer();const uint8_t *pImageBufferr = (uint8_t *) ptrGrabResultr->GetBuffer();// 将 pylon image转成OpenCV image.Mat SaveImagel = cv::Mat(ptrGrabResultl->GetHeight(), ptrGrabResultl->GetWidth(), CV_8UC1,(uint8_t *) pImageBufferl);Mat SaveImager = cv::Mat(ptrGrabResultr->GetHeight(), ptrGrabResultr->GetWidth(), CV_8UC1,(uint8_t *) pImageBufferr);}lTimeAloInterval =std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1, 1000> >>(std::chrono::high_resolution_clock::now() - tStartTime).count();LOG(INFO) << "------------ single Grab image cost time:----------------" << lTimeAloInterval << " ms" << endl;}cameras.StopGrabbing();}catch (const GenericException& e){if(cameras.IsGrabbing())cameras.StopGrabbing();// Error handlingLOG(INFO) << "An exception occurred." << endl<< e.GetDescription() << endl;}}

3.关闭相机

相机及时关闭:

void CloseCamera()
{//最后终止Pylon相机,即调用PylonTerminate。//关闭摄像头try{if (cameras.IsOpen()) {cameras.DetachDevice();cameras.Close();cameras.DestroyDevice();//关闭库LOG(INFO) << "SBaslerCameraControl deleteAll: PylonTerminate";PylonTerminate();}}catch (const Pylon::GenericException& e){LOG(INFO) << "close camera failed..." << e.what();}
}

五、常见问题

1.相机连不上

IP配置不正确,确保在同一网段,子网掩码相同。

2.连接后丢帧

 Error: e1004 The bufer was incopletely gratbed. This can be caused by perfomnane problens of the metwork hardware used,fer underuns can also case ina loss.To fix this, us the pylonbioEtonfigurator tol to optinize your setip and use more uffers for aratbin in your aplication to prerent buferunderruns

常见于连接多个相机的时候出现,确保开启巨帧,相机帧率和网络传输的帧率是否满足要求,[参加API手册]。(https://zh.docs.baslerweb.com/network-configuration-%28gige-cameras%29)
在这里插入图片描述

3.相机连接后,使用过程中出现找得到相机,但卡住不动了

这种问题不知道是什么原因导致的,可能是长时间没调用导致相机休眠,关机重启下可解决。

4.grab time out 抓取超时

一般是设置waittime时间太短导致,可以改大一些:

 cameras[1].RetrieveResult(waittime, ptrGrabResultr, TimeoutHandling_ThrowException);

还有一种可能是相机连上之后一直么有抓取成功,导致等待时间过长,需要检查代码,常见有时候做触发的操作导致。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《PostgreSQL物化视图:创建、维护与应用》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

Unreal Engine Loop 流程

引擎LOOP 虚幻引擎的启动是怎么一个过程。 之前在分析热更新和加载流程过程中&#xff0c;做了一个图。记录一下&#xff01;&#xff01; ![在这里插入图片描述](https://img-blog.csdnimg.cn/f11f7762f5dd42f9b4dd9b7455fa7a74.png#pic_center 只是记录&#xff0c;以备后用…

Android相机调用-CameraX【外接摄像头】【USB摄像头】

Android相机调用有原生的Camera和Camera2&#xff0c;我觉得调用代码都太复杂了&#xff0c;CameraX调用代码简洁很多。 说明文档&#xff1a;https://developer.android.com/jetpack/androidx/releases/camera?hlzh-cn 现有查到的调用资料都不够新&#xff0c;对于外接摄像…

机器学习实战-系列教程7:SVM分类实战2线性SVM(鸢尾花数据集/软间隔/线性SVM/非线性SVM/scikit-learn框架)项目实战、代码解读

&#x1f308;&#x1f308;&#x1f308;机器学习 实战系列 总目录 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 SVM分类实战1之简单SVM分类 SVM分类实战2线性SVM SVM分类实战3非线性SVM 3、不同软间隔C值 3.1 数据标准化的影响 如图左边是没…

Vue3样式绑定

文章目录 Vue3样式绑定1. class 属性绑定1.1 v-bind:class 设置一个对象&#xff0c;从而动态的切换 class1.2 在对象中传入更多属性用来动态切换多个 class1.3 直接绑定数据里的一个对象1.4 绑定一个返回对象的计算属性。这是一个常用且强大的模式1. 5 数据语法1.6 errorClass…

设计模式之模板模式

文章目录 豆浆制作问题模板方法模式基本介绍模板方法模式原理类图对原理类图的说明-即(模板方法模式的角色及职责)模板方法模式解决豆浆制作问题模板方法模式的钩子方法模板方法模式的注意事项和细节 豆浆制作问题 编写制作豆浆的程序&#xff0c;说明如下: 制作豆浆的流程 选…

誉天在线项目~ElementPlus Tag标签用法

效果图 页面展现 <el-form-item label"课程标签"><el-tagv-for"tag in dynamicTags":key"tag"class"mx-1"closable:disable-transitions"false"close"handleClose(tag)"style"margin:5px;">…

的修大数据管理平台有哪些功能模块?它可以为企业带来什么好处?

的修大数据管理平台的功能比较强大&#xff0c;它提供了报修、维修、巡检、能耗、智识库、管线智慧云等应用场景服务&#xff0c;同时还可以为企业提供维保进度追踪、员工考核、服务流程管控、设备资产管理等一站式解决方案。平台通过多渠道报修、“一站式”投诉建议服务、企业…

CocosCreator3.8研究笔记(八)CocosCreator 节点和组件的使用

我们知道&#xff0c;在CocosCreator 节点和组件的修改有两种方法&#xff1a; 属性检查器中的设置脚本中的动态修改 脚本中动态修改&#xff0c;能实现各种各样的游戏逻辑&#xff0c;例如响应玩家输入&#xff0c;删除、修改、销毁节点或组件。 不过想要实现这些游戏逻辑&a…

spring boot-Resolved element must not contain multiple elements 警告

首先强调一下&#xff0c;此问题不影响程序运行。 报错信息&#xff1a; package org.springframework.util; ...public abstract class Assert ...public static void state(boolean expression, String message) {if (!expression) {throw new IllegalStateException(messa…

Transformers-Bert家族系列算法汇总

&#x1f917; Transformers 提供 API 和工具&#xff0c;可轻松下载和训练最先进的预训练模型。使用预训练模型可以降低计算成本、碳足迹&#xff0c;并节省从头开始训练模型所需的时间和资源。这些模型支持不同形式的常见任务&#xff0c;例如&#xff1a; &#x1f4dd; 自…

特斯拉Dojo超算:AI训练平台的自动驾驶与通用人工智能之关键

特斯拉公开Dojo超算架构细节&#xff0c;AI训练算力平台成为其自动驾驶与通用人工智能布局的关键一环 在近日举行的Hot Chips 34会议上&#xff0c;特斯拉披露了其自主研发的AI超算Dojo的详细信息。Dojo是一个可定制的超级计算机&#xff0c;从芯片到系统全部由特斯拉自主设计…