当前位置: 首页 > news >正文

机器视觉之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左右。其中 cameras.StartGrabbing()可以放在初始化中,这样就不停的抓取,能够保证1秒20帧,不用频繁开始抓取和停止抓取,实际上很耗时。

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手册
在这里插入图片描述

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

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

4.grab time out 抓取超时

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

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

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

相关文章:

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

basler工业相机做双目视觉用&#xff0c;出现很多问题记录一下&#xff1a; 首先是多看手册&#xff1a;https://zh.docs.baslerweb.com/software 手册内有所有的源码和参考示例&#xff0c;实际上在使用过程中&#xff0c;大部分都是这些源码&#xff0c;具体项目选择对应的…...

Centos nginx配置文档

1、安装nginx: yum install nginx 2、Nginx常用命令 查看版本:nginx -v 启动:nginx -c /etc/nginx/nginx.conf 重新加载配置:nginx -s reload 停止:nginx -s stop 3、Nginx反向代理配置 nginx配置详解 1、Nginx配置图 详情可以查看:http://nginx.org/ru/docs/example…...

2023/9/14 -- C++/QT

作业&#xff1a; 仿照Vector实现MyVector&#xff0c;最主要实现二倍扩容 #include <iostream>using namespace std;template <typename T> class MyVector { private:T *data;size_t size;size_t V_capacity; public://无参构造MyVector():data(nullptr),size(…...

golang在goland编译时获取环境变量失效

在golang中&#xff0c; 我们通常使用os包来获取环境变量&#xff0c;如&#xff1a; os.Getenv() os.LookupEnv() 等。 但如果我们使用goland编译器&#xff0c;在编译是&#xff0c;这时操作环境变量&#xff0c;会发现os包读取到的环境变量值不变&#xff1a; 新增后&am…...

一款非常容易上手的报表工具,简单操作实现BI炫酷界面数据展示,驱动支持众多不同类型的数据库,可视化神器,免开源了

一款非常容易上手的报表工具&#xff0c;简单操作实现BI炫酷界面数据展示&#xff0c;驱动支持众多不同类型的数据库&#xff0c;可视化神器&#xff0c;免开源了。 在互联网数据大爆炸的这几年&#xff0c;各类数据处理、数据可视化的需求使得 GitHub 上诞生了一大批高质量的…...

蓝桥杯 题库 简单 每日十题 day3

01 约数个数 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 1200000 有多少个约数&#xff08;只计算正约数&#xff09;。 解题思路 枚举&#xff0c;从1开始一直到1200000本身都作为1200000的除数&#xff0c;…...

基于SSM+Vue的高校实验室管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…...

C语言天花板——指针(初阶)

&#x1f320;&#x1f320;&#x1f320; 大家在刚刚接触C语言的时候就肯定听说过&#xff0c;指针的重要性以及难度等级&#xff0c;以至于经常“谈虎色变”&#xff0c;但是今天我来带大家走进指针的奇妙世界。&#x1f387;&#x1f387;&#x1f387; 一、什么是指针&…...

关于第一届全球电子纸创新应用金奖征集评选及报名指南

重要通知 &#xff5c;关于第一届全球电子纸创新应用金奖征集评选及报名指南https://mp.weixin.qq.com/s/RWsZtmJ20-NZXMG0k0rwPA?wxwork_useridEPIA 从2004年&#xff0c;Sony推出全球首款电纸书阅读器至今20载&#xff0c;这期间&#xff0c;到底诞生了多少种创新产品&#…...

idea搭建项目找不到Tomcat

idea搭建项目找不到Tomcat_idea没有tomcat配置项_ZYRL的博客-CSDN博客...

类和对象三大特性之继承

全文目录 继承的概念定义格式继承关系和访问限定符final 基类和派生类对象赋值转换继承中的作用域派生类的六个默认成员函数构造函数拷贝构造函数operator析构函数 友元和静态成员友元静态成员 各种继承形式菱形继承虚继承菱形虚拟继承对象模型 继承和组合 继承的概念 通过继承…...

Debian 12安装Docker

1.更新系统包 #apt update 2.安装依赖包 #apt install apt-transport-https ca-certificates curl gnupg lsb-release 3.添加Docker源 &#xff08;1&#xff09;添加Docker 官方GPG密钥 #curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/s…...

小谈设计模式(4)—单一职责原则

小谈设计模式&#xff08;4&#xff09;—单一职责原则 专栏介绍专栏地址专栏介绍 单一职责原则核心思想职责的划分单一变化原则高内聚性低耦合性核心总结 举例图书类&#xff08;Book&#xff09;用户类&#xff08;User&#xff09;图书管理类&#xff08;Library&#xff09…...

ATF(TF-A) EL3 SPMC威胁模型-安全检测与评估

安全之安全(security)博客目录导读 ATF(TF-A) 威胁模型汇总 目录 一、简介 二、评估目标 1、数据流图 三、威胁分析 1、信任边界 2、资产 3、威胁代理 4、威胁类型 5、威胁评估 5.1 端点在直接请求/响应调用中模拟发送方FF-A ID 5.2 端点在直接请求/响应调用中模拟…...

AI绘画Stable Diffusion原理之扩散模型DDPM

前言 传送门&#xff1a; stable diffusion&#xff1a;Git&#xff5c;论文 stable-diffusion-webui&#xff1a;Git Google Colab Notebook部署stable-diffusion-webui&#xff1a;Git kaggle Notebook部署stable-diffusion-webui&#xff1a;Git AI绘画&#xff0c;输入一段…...

NSS [西湖论剑 2022]real_ez_node

NSS [西湖论剑 2022]real_ez_node 考点&#xff1a;ejs原型链污染、NodeJS 中 Unicode 字符损坏导致的 HTTP 拆分攻击。 开题。 附件start.sh。flag位置在根目录下/flag.txt app.js(这个没多大用) var createError require(http-errors); var express require(express); v…...

MySQL常用函数集锦 --- 字符串|数值|日期|流程函数总结

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】&#x1f388; 本专栏旨在分享学习MySQL的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、字符…...

GaussDB(DWS)云原生数仓技术解析:湖仓一体,体验与大数据互联互通

文章目录 前言一、关于数据仓库需求场景分类二、数据仓库线下部署场景2.1、线下部署场景介绍及优劣势说明2.2、线下部署场景对应的客户需求 三、数据仓库公有云部署场景3.1、公有云部署场景介绍及优劣势说明3.2、公有云部署场景对应的客户需求 四、为何重视数据共享&#xff08…...

Navicat历史版本下载及地址组成分析

下载地址组成 https://download3.navicat.com/download/navicat161_premium_cs_x64.exe 地址逻辑&#xff1a;前缀 版本 类型 语言 位数 前缀: http://download.navicat.com/download/navicat版本: 三位数&#xff0c;前两位是大版本&#xff0c;后一位是小版本&#xff…...

avue之动态切换表格样式问题

动态切换 a\b 两个表格 &#xff0c;a表格高度变成b的高度等问题&#xff0c; 解决方案&#xff1a;...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...