Qt(C++)项目中使用 Basler 工业相机(1 枚举相机)

最近的一个项目中用到Basler 的GigE 接口的工业相机。为此花了好几天时间研究了pylon 的用法。本文就是学习过程中做的笔记。

Pylon 的结构可以参考下图。

图 1 Pylon 的结构
整个pylon 对 GenICam 接口进行了封装,但是这个封装并不是特别的彻底。只有理解了GenICam 的设计思想才能真正明白pylon 是怎么回事。GenICam 是Generic Interface for Cameras 的缩写,GenICam 的目标就是建立一个统一的 API接口,用这个接口可以操作 GigE、USB、Camera Link 等各种类型的工业相机。

GenApi 是GenICam 的一个模块。这个模块的作用就是用来描述相机的功能和控制方法。最核心的就是保存在相机中的一个 xml 文件,这个 xml 文件称为相机的描述文件,记录了这台相机对外都有哪些功能接口,如何去访问这些功能接口。

在 pylon 中这个描述文件被解析为所谓的GenApi Node Maps。相机的每个具体的参数对应一个Node。

GenTL 是GenICam 的另一个重要模块。这里 TL 是 transport layer 的缩写。所谓传输层就是对具体的物理层面的传输(比如GigE传输、USB传输)的一种抽象。这个模块规范了如何去发现枚举系统中的相机、如何获取相机图像等。

pylon 就是将GenApi 和 GenTL 进一步封装了一下,使得用起来更方便。

传输层(transport layer)与传输层工厂(transport layer factory)

Pylon 支持四种传输层:
1. PylonGigE
2. Pylon1394
3. PylonUsb
4. PylonCLSer

对应的C++接口是Pylon::ITransportLayer,这个是个接口类,无法直接生成。需要用传输层工厂(Pylon::CTlFactory)来获取。例如下面的代码:

CTlFactory& TlFactory = CTlFactory::GetInstance();
ITransportLayer* pTl = TlFactory.CreateTl( CBaslerGigECamera::DeviceClass() );

执行之后 pTl 就指向一个 PylonGigE 类型的Pylon::ITransportLayer 了。上述代码的 CBaslerGigECamera::DeviceClass()实际上返回的是一个字符串 “BaslerGigE”。

利用 Pylon::CTlFactory 我们还可以枚举系统中支持的所有的传输层,下面是示例代码:

    Pylon::CTlFactory &TlFactory = CTlFactory::GetInstance();TlInfoList_t lstInfo;int n = TlFactory.EnumerateTls(lstInfo);TlInfoList_t::const_iterator it;for ( it = lstInfo.begin(); it != lstInfo.end(); ++it ){qDebug() << "FriendlyName: " << it->GetFriendlyName ();qDebug() << "FullName: " << it->GetFullName();qDebug() << "VendorName: " << it->GetVendorName() ;qDebug() << "DeviceClass: " << it->GetDeviceClass() ;qDebug() << "";
}

这个代码在我的电脑上执行的结果是:

FriendlyName:  USB
FullName:  USB/BaslerUsb 5.0.9.10388
VendorName:  Basler
DeviceClass:  BaslerUsbFriendlyName:  GigE
FullName:  GigE/BaslerGigE 5.0.9.10388
VendorName:  Basler
DeviceClass:  BaslerGigE

可以看到我的电脑支持两种传输层。分别是 USB和GigE。
上面的代码中其实还涉及另一种类:Pylon::CTlInfo。这个类顾名思义是用来获取传输层的信息的。通过这个类可以获取传输层的Full Name、DeviceClass 等信息。当然这个类还有其他的方法,不过对于我们来说知道这些也就够了。

获得了一个传输层对象后就可以枚举这个传输层上的相机了。枚举过程与枚举传输层很类似。下面是代码片段:

    Pylon::CTlFactory &TlFactory = CTlFactory::GetInstance();ITransportLayer * pTl = TlFactory.CreateTl("BaslerGigE");DeviceInfoList_t lstDevices;int n = pTl->EnumerateDevices(lstDevices);if(n == 0){qDebug() << "Cannot find any camera!";
        return;}DeviceInfoList_t::const_iterator it;for ( it = lstDevices.begin(); it != lstDevices.end(); ++it ){qDebug() << "SerialNumber : " << it->GetSerialNumber  ();qDebug() << "UserDefinedName: " << it->GetUserDefinedName();qDebug() << "ModelName: " << it->GetModelName() ;qDebug() << "DeviceVersion: " << it->GetDeviceVersion() ;qDebug() << "DeviceFactory: " << it->GetDeviceFactory() ;qDebug() << "XMLSource: " << it->GetXMLSource() ;qDebug() << "FriendlyName: " << it->GetFriendlyName() ;qDebug() << "FullName: " << it->GetFullName() ;qDebug() << "VendorName: " << it->GetVendorName() ;qDebug() << "DeviceClass: " << it->GetDeviceClass() ;qDebug() << "";}

我的电脑上只接了一个相机,所以显示结果是这样的:

SerialNumber :  22099564
UserDefinedName:
ModelName:  acA2440-20gc
DeviceVersion:  107213-06
DeviceFactory:  GigE/BaslerGigE 5.0.9.10388
XMLSource:  N/A
FriendlyName:  Basler acA2440-20gc (22099564)
FullName:  Basler acA2440-20gc#00305320096C#192.168.1.98:3956
VendorName:  Basler
DeviceClass:  BaslerGigE

上面的代码只是枚举了一个传输层的相机。如果我们要枚举所有传输层的相机,还可以利用传输层工厂,下面是代码:

    Pylon::CTlFactory &TlFactory = CTlFactory::GetInstance();DeviceInfoList_t lstDevices;TlFactory.EnumerateDevices( lstDevices );if ( ! lstDevices.empty() ){DeviceInfoList_t::const_iterator it;for ( it = lstDevices.begin(); it != lstDevices.end(); ++it ){qDebug() << "SerialNumber : " << it->GetSerialNumber  ();qDebug() << "UserDefinedName: " << it->GetUserDefinedName();qDebug() << "ModelName: " << it->GetModelName() ;qDebug() << "DeviceVersion: " << it->GetDeviceVersion() ;qDebug() << "DeviceFactory: " << it->GetDeviceFactory() ;qDebug() << "XMLSource: " << it->GetXMLSource() ;qDebug() << "FriendlyName: " << it->GetFriendlyName() ;qDebug() << "FullName: " << it->GetFullName() ;qDebug() << "VendorName: " << it->GetVendorName() ;qDebug() << "DeviceClass: " << it->GetDeviceClass() ;qDebug() << "";}}elseqDebug() << "No devices found!" << endl;

有时,我们的系统里有很多个相机,我们又只想枚举其中的某类相机。这时可以用EnumerateDevices() 函数的第二个参数传进一个filter。比如下面的例子,我们只枚举型号为”SCA750-60FC” 和 “SCA780-54FC” 的相机。

    CTlFactory& TlFactory = CTlFactory::GetInstance();DeviceInfoList_t filter;filter.push_back( CDeviceInfo().SetModelName( "SCA750-60FC"));filter.push_back( CDeviceInfo().SetModelName( "SCA780-54FC"));DeviceInfoList_t lstDevices;TlFactory.EnumerateDevices( lstDevices, filter );if ( ! lstDevices.empty() ){DeviceInfoList_t::const_iterator it;for ( it = lstDevices.begin(); it != lstDevices.end(); ++it )qDebug() << it->GetFullName();}elseqDebug() << "No devices found!" << endl;

我们知道在 Qt 中有两个类 QCamera 和 QCameraInfo 用来访问相机。这里也仿照这个模式。将 pylon 的相关功能封装到 BaslerCameraInfo 和 BaslerCamera 两个类中。

BaslerCameraInfo 用来返回相机的信息,其实就是对 CDeviceInfo 的一个封装。封装之后我们就不用与传输层打交道了。下面是类的声明:

class BaslerCameraInfo
{friend class BaslerCamera;
public:BaslerCameraInfo();explicit BaslerCameraInfo(const BaslerCamera &camera);BaslerCameraInfo(const BaslerCameraInfo &other);//explicit BaslerCameraInfo(Pylon::CDeviceInfo deviceInfo);//QString description() const;//QString deviceName() const;//bool isNull() const {return m_deviceInfo == Pylon::CDeviceInfo();}int orientation() const {return 0;}bool operator!=(const BaslerCameraInfo &other) const;//BaslerCameraInfo & operator=(const BaslerCameraInfo &other);//bool operator==(const BaslerCameraInfo &other) const;//static QList<BaslerCameraInfo> availableCameras();//static BaslerCameraInfo defaultCamera();///// 下面是 Basler 相机 CDeviceInfo 的接口,QCameraInfo 类没有这些接口QString serialNumber();QString userDefinedName();QString modelName () ;QString deviceVersion ();QString deviceFactory ();QString XMLSource ();QString friendlyName ();QString fullName () ;QString vendorName ();QString deviceClass () ;bool setSerialNumber (QString serialNumberValue);~BaslerCameraInfo(){}
private:Pylon::CDeviceInfo m_deviceInfo;
};

之后是具体的实现代码:

BaslerCameraInfo::BaslerCameraInfo()
{}BaslerCameraInfo::BaslerCameraInfo(const BaslerCamera &camera)
{
    Pylon::IPylonDevice *  pDevice = camera.m_device;m_deviceInfo = pDevice->GetDeviceInfo();
}BaslerCameraInfo::BaslerCameraInfo(const BaslerCameraInfo &other)
{m_deviceInfo = other.m_deviceInfo;
}BaslerCameraInfo::BaslerCameraInfo(CDeviceInfo deviceInfo)
{m_deviceInfo = deviceInfo;
}QString BaslerCameraInfo::description() const
{return QString(m_deviceInfo.GetFullName());
}QString BaslerCameraInfo::deviceName()const
{return QString(m_deviceInfo.GetModelName());
}QString BaslerCameraInfo::serialNumber()
{return QString(m_deviceInfo.GetSerialNumber());
}bool BaslerCameraInfo::setSerialNumber (QString serialNumberValue)
{if(m_deviceInfo.IsSerialNumberAvailable()){m_deviceInfo.SetSerialNumber(serialNumberValue.toLocal8Bit());return true;}return false;
}QString BaslerCameraInfo::userDefinedName()
{return QString(m_deviceInfo.GetModelName());
}QString BaslerCameraInfo::modelName ()
{return QString(m_deviceInfo.GetModelName());
}QString BaslerCameraInfo::deviceVersion ()
{return QString(m_deviceInfo.GetDeviceVersion());
}QString BaslerCameraInfo::deviceFactory ()
{return QString(m_deviceInfo.GetDeviceFactory());
}QString BaslerCameraInfo::XMLSource ()
{return QString(m_deviceInfo.GetXMLSource());
}QString BaslerCameraInfo::friendlyName ()
{return QString(m_deviceInfo.GetFriendlyName ());
}QString BaslerCameraInfo::fullName ()
{return QString(m_deviceInfo.GetFullName());
}QString BaslerCameraInfo::vendorName ()
{return QString(m_deviceInfo.GetVendorName());
}QString BaslerCameraInfo::deviceClass ()
{return QString(m_deviceInfo.GetDeviceClass());
}BaslerCameraInfo BaslerCameraInfo::defaultCamera()
{
    Pylon::CTlFactory& TlFactory = CTlFactory::GetInstance();
    Pylon::DeviceInfoList_t lstDevices;TlFactory.EnumerateDevices( lstDevices );BaslerCameraInfo info;if(!lstDevices.empty() ){info = BaslerCameraInfo(lstDevices[0]);}return info;
}bool BaslerCameraInfo::operator!=(const BaslerCameraInfo &other) const
{return !(m_deviceInfo == other.m_deviceInfo);
}BaslerCameraInfo & BaslerCameraInfo::operator=(const BaslerCameraInfo &other)
{m_deviceInfo = other.m_deviceInfo;return *this;
}bool BaslerCameraInfo::operator==(const BaslerCameraInfo &other) const
{return (m_deviceInfo == other.m_deviceInfo);
}QList<BaslerCameraInfo> BaslerCameraInfo::availableCameras()
{
    Pylon::CTlFactory& TlFactory = CTlFactory::GetInstance();
    Pylon::DeviceInfoList_t lstDevices;TlFactory.EnumerateDevices( lstDevices );QList<BaslerCameraInfo> info;if ( !lstDevices.empty() ){
        DeviceInfoList_t::const_iterator it;for ( it = lstDevices.begin(); it != lstDevices.end(); ++it ){info.append(BaslerCameraInfo(*it));}}return info;
}

Qt(C++)项目中使用 Basler 工业相机(1)相关推荐

  1. Qt(C++)项目中使用 Basler 工业相机(2 参数设置)

    Qt(C++)项目中使用 Basler 工业相机(2 参数设置) 上一篇博客介绍了 pylon 的基本结构和如何枚举系统中的相机.这一篇主要讲讲如何设置相机的各个参数. 在设置相机参数之前,先要获取相 ...

  2. Qt(C++)项目中使用 Basler 工业相机(图像获取策略)

    Qt(C++)项目中使用 Basler 工业相机(图像获取策略) Pylon 中的 CInstantCamera 类支持四种图像获取策略,分别称为: One by One Grab Strategy ...

  3. linux编译taglib,在Windows上将TagLib编译到Qt C项目中

    我目前正试图通过使用Qt / C从C#转移并摆脱我的平台边界. 我在我的旧项目中使用TagLibSharp,但我现在正尝试使用此处找到的原始C源: 我正处于一个受伤的世界,试图将其编译到我的应用程序中 ...

  4. qt的项目中单个文件加载样式表

    引言 编写一个项目后,通过加载样式表来设置项目中的所有控件的样式,我之前习惯的是在main.cpp文件中加载一个样式表,该样式表含有程序中所有控件的样式,也就是整个程序只需要加载一遍样式文件.但是多人 ...

  5. Linux环境中对海康威视工业相机SDK进行二次开发(QT+CMake+Opencv+海康SDK)

    关于在Windows环境中对海康威视工业相机SDK进行二次开发的话,可以参考这两篇博客. 海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(一) 海康威视工业相机SDK二 ...

  6. 解决在使用 Qt 编译项目时出现 “C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode格式以防止数据丢失“ 的警告

    解决在使用 Qt 编译项目时出现 "C4819: 该文件包含不能在当前代码页(936)中表示的字符.请将该文件保存为 Unicode格式以防止数据丢失" 的警告 警告出现的原因:编 ...

  7. Qt项目中,用QPainter进行绘制图形时,边角显示不完整问题的梳理

    总第42篇 本文主要梳理总结了我自己在项目开发过程中经常遇到的一个问题,就是用QPainter进行图形绘制时,边角显示不完整的现象.这个问题虽然比较简单,但是很容易忘记,每次绘图时都要调试一下,故总结 ...

  8. 在Qt项目中添加pri文件

    在Qt项目框架里,很多人都喜欢用pri文件来管理项目.那么今天就来讲讲这个pri文件. 目录 前言 创建pri文件的步骤 一.创建Qt项目 二.创建pri空文件 三.调试 前言 一般我们创建Qt项目工 ...

  9. Qt项目中,绘制只有两个圆角的矩形及QPainterPath类的应用

    总第39篇 本文主要梳理总结了在Qt项目开发过程中,某些特殊场合绘制只有两个圆角矩形的方法,并在此基础上详细介绍了类QPainterPath的用法. 1.两个圆角矩形的绘制方法 在Qt项目中,绘制只有 ...

最新文章

  1. Word 最后一页无法删除-解决办法
  2. 在 JavaScript 中创建 JSON 对象
  3. Mac下ssh支持auto complete
  4. c语言实验5上机刘若慧2017年,《《 C语言程序设计案例教程》》.ppt
  5. redis原理及实现
  6. React-Native 之 GD (十三)数据持久化(realm) 及 公共Cell
  7. .NET与COM互操作系列
  8. 0基础学python要多久-27岁0基础自学Python,多久可以找到工作?
  9. 关于滚动条ScrollView
  10. cad灯具图标_CAD图纸灯具图例
  11. Linux系统下挂载Windows分区的方法和技巧
  12. 华为6108v9刷机U盘的注意事项
  13. vs213开发php,vs厂年度大作沛纳海213追针计时手表详解 - n厂手表
  14. R语言 AHP层次分析法——如何验证矩阵一致性
  15. 拳皇觉醒服务器维护,拳魂觉醒活动什么时候开 服务器开区活动时间顺序
  16. 《C#程序设计》猜猜看游戏开发总结
  17. Studio 3T 试用期破解(含破解补丁) - 解决办法
  18. 液晶屏 TTL屏、LVDS屏、TMDS屏区别
  19. [COGS 2583]南极科考旅行
  20. 展讯LOG抓取及简单分析

热门文章

  1. ajax 随机,基于JQuery及AJAX实现名人名言随机生成器
  2. python 贪吃蛇 turtle_关于python:用Python实现童年小游戏贪吃蛇
  3. VMware Tools驱动工具安装
  4. k8s中部署jira-8.1.0
  5. Android 11整合Mopria联盟的代码贡献以实现增强的打印功能
  6. word插入图片为何无法显示?
  7. 太极框架阴阳之门(设备管理员)激活的种种困难
  8. FPGA视觉从入门到放弃——懒人的支持向量机
  9. c语言 threads.h 创建简单的通用多线程模块实例
  10. WIN7下 Absinthe2.0 已停止工作