Qt调用工业相机之巴斯勒相机

作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

开发环境

操作系统:Windows 10 1903 18362.778
相机型号:BASLER acA 1300-60gm
相机软件:pylon_Runtime_6.0.0.17906,Basler_pylon_5.0.10.10613
软件版本:Qt 5.12.8, vs2017 Community
通信方式:GigE - 千兆以太网通信协议

驱动与SDK

开发包和驱动下载地址
提取码:lg0i

驱动安装完成之后需要完成一些配置才能成功连接相机

  1. 将相机通电,使用网线将相机与电脑连接。确保相机与电脑处于连接状态。可以观察网
    络连接中,本地连接的状态;
  2. 网络连接中,右键本地连接,选择属性。在属性界面中点击”配置”按钮,进入”高级”选项卡,设置 Jumbo Packet (巨型帧)为当前可设置的最大值。点击确定保存参数;
    在这里插入图片描述
    在这里插入图片描述
  3. 在网络连接中,右键”本地连接”,双击 “Internet 协议版本 4”,在弹出界面中勾选 “自动获得 IP 地址”
    ,点击确定保存参数;
    在这里插入图片描述
    在这里插入图片描述
  4. 打开 “Pylon IP Configurator”工具,在列表中选择当前连接的相机。选择相机后,选择 “DHCP”,点击保存。”Refresh” 确保相机的 “Status” 为 ”OK”,并且界面右下角没有警告;
    在这里插入图片描述

安装驱动和开发包完成之后,可以找到以下目录:

  1. C:\Program Files\Basler\pylon 5
    在这里插入图片描述
  • Applications - 应用程序 pylon Viewer 和 pylon IP Configurator;
  • Development - 开发文档、头文件、库文件、示例程序源代码等等;
  • License - 开发许可证;
  • Runtime - 运行时需要的依赖库(打包程序时需要包含);
  • Release Notes.txt - 发行笔记;

相机原理介绍

巴斯勒相机实时获取图像的原理就是对每一帧数据的处理,即 拍照 - 处理数据 - 拍照 - 处理数据 …
SDK中提供了两种方式来处理图像,我们先来看一下最主要的开始抓取图像的函数 StartGrabbing:
virtual void StartGrabbing( EGrabStrategy strategy = GrabStrategy_OneByOne,
EGrabLoop grabLoopType = GrabLoop_ProvidedByUser);

来看一下函数的两个参数代表什么含义

  • One by One Grab Strategy
    这种模式是最简单的,也是 CInstantCamera 默认的图像获取策略。
    获取到的图像放到一个FIFO 队列中。每次我们从队列中取的(RetrieveResult)都是最早放到队列中的图像

  • Latest Image Only Grab Strategy
    这个策略下只有最新到的图像保存在输出队列中。
    如果一份旧图像还没被读取新图像就又来了,那么旧图像就被舍弃。这样可以保证读取到图像永远都是读取时刻最新的。

  • Latest Images Grab Strategy
    这个模式下输出队列可以保存不止一张图像,具体最多能保存几张图象由 CInstantCamera::OutputQueueSize 来指定。
    当新的图像来了,而队列已满时,旧的图像被舍弃。
    当 CInstantCamera::OutputQueueSize 为 1 时就是 Latest Image Only Grab Strategy。
    当 CInstantCamera::OutputQueueSize = CInstantCamera::MaxNumBuffer,就和 One by One Grab Strategy 一样了。

  • Upcoming Image Grab Strategy
    这个模式很特别,只有当 CInstantCamera::RetrieveResult() 被调用后才会采集图像。USB 相机不支持这种策略。

  • GrabLoop_ProvidedByUser
    用户在代码中循环调用RetrieveResult() 来处理抓取的图像和相机事件。默认使用这种模式

  • GrabLoop_ProvidedByInstantCamera
    抓取循环线程由即时相机提供。它会不断循环调用RetrieveResult()。抓取的图像由注册的图像事件处理程序处理。抓取循环线程在抓取启动时启动

StartGrabbing的第一个参数代表获取图像的策略,第二个参数代表的是使用哪个循环线程来抓取图像。由第二个参数我们就可以分两种方式来处理图像数据:

  1. 用户自己处理,步骤如下:
  • 调用 StartGrabbing 开始抓取图像
    m_baslerCamera.StartGrabbing(GrabStrategy_OneByOne, GrabLoop_ProvidedByUser);
  • 用户自己循环调用 RetrieveResult
    m_baslerCamera.RetrieveResult(1000, ptrGrabResult, TimeoutHandling_ThrowException);
  • 处理数据 ptrGrabResult
    CImagePersistence::Save(ImageFileFormat_Bmp, filename, ptrGrabResult);
  1. 使用相机的循化线程,步骤如下:
  • 注册图像事件处理程序
    m_baslerCamera.RegisterImageEventHandler(this, RegistrationMode_Append, Cleanup_Delete);
  • 重写图像处理函数 OnImageGrabbed
    virtual void OnImageGrabbed(CInstantCamera &camera, const CGrabResultPtr &grabResult) override;
  • 调用 StartGrabbing 开始抓取图像
    m_baslerCamera.StartGrabbing(GrabStrategy_OneByOne, GrabLoop_ProvidedByInstantCamera);
  • 注意事项:相机获取到图像就会调用回调函数 OnImageGrabbed,图像处理是在不同的线程所以需要加锁

我的代码

这里需要说明一下,博主自定义的相机控制类 BBaslerCamerControl 使用了多继承的方式,这个方法不是很好。我们在开发项目中还是要倡导多用组合,少用继承,博主在这里偷懒了。

实现功能:相机图像的实时显示,并且可以在某一时刻拍照保存图片到本地

首先需要在pro中配置头文件和库文件

INCLUDEPATH += $$PWD/include/ \
               $$PWD/include/pylon

windows {
    contains(DEFINES, WIN64) {
        LIBS += -L$$PWD/lib/x64/ -lGCBase_MD_VC120_v3_0_Basler_pylon_v5_0
        LIBS += -L$$PWD/lib/x64/ -lGenApi_MD_VC120_v3_0_Basler_pylon_v5_0
        LIBS += -L$$PWD/lib/x64/ -lPylonBase_MD_VC120_v5_0
        LIBS += -L$$PWD/lib/x64/ -lPylonC_MD_VC120
        LIBS += -L$$PWD/lib/x64/ -lPylonGUI_MD_VC120_v5_0
        LIBS += -L$$PWD/lib/x64/ -lPylonUtility_MD_VC120_v5_0
    } else {
        LIBS += -L$$PWD/lib/Win32/ -lGCBase_MD_VC120_v3_0_Basler_pylon_v5_0
        LIBS += -L$$PWD/lib/Win32/ -lGenApi_MD_VC120_v3_0_Basler_pylon_v5_0
        LIBS += -L$$PWD/lib/Win32/ -lPylonBase_MD_VC120_v5_0
        LIBS += -L$$PWD/lib/Win32/ -lPylonC_MD_BCC55
        LIBS += -L$$PWD/lib/Win32/ -lPylonC_MD_VC120
        LIBS += -L$$PWD/lib/Win32/ -lPylonGUI_MD_VC120_v5_0
        LIBS += -L$$PWD/lib/Win32/ -lPylonUtility_MD_VC120_v5_0
    }
}

自定义 BBaslerCamerControl 相机控制类

#ifndef BBASLERCAMERCONTROL_H
#define BBASLERCAMERCONTROL_H

#include <QObject>
#include <QMutex>
#include <QImage>
#include "PylonIncludes.h"

using namespace std;
using namespace Pylon;
using namespace GenApi;

class BBaslerCamerControl : public QObject, public Pylon::CImageEventHandler
{
    Q_OBJECT
public:
    explicit BBaslerCamerControl(QObject *parent = nullptr);

    enum BaslerCameraProperty {
        DeviceModelName,            // 相机名称
        DeviceID,                   // 相机SN号
        ResultingFrameRateAbs,      // 相机帧率
        AcquisitionFrameRateAbs,    // 相机频率
        Freerun,                    // 相机内触发
        Line1,                      // 相机外触发
        ExposureTimeAbs,            // 相机曝光时间
        GainRaw,                    // 相机增益
        SensorWidth,                // 传感器宽度
        SensorHeight,               // 传感器高度
        Width,                      // 图片宽度
        Height,                     // 图片高度
        PixelFormat,                // 图片的格式
    };

    void initCamera();              // 初始化相机
    void destroyCamera();           // 销毁相机

    int openCamera();               // 打开相机
    int closeCamera();              // 关闭相机

    int startWork();                // 开始工作
    int stopWork();                 // 停止工作

    QString GetCameraProperty(BBaslerCamerControl::BaslerCameraProperty type);                  // 获取相机参数
    void SetCameraProperty(BBaslerCamerControl::BaslerCameraProperty type, double value = 0.0); // 设置相机参数

    void printCameraProperty();     // 打印相机所有配置信息

    // Overwrite the GrabberListener methods we need.
    virtual void OnImageGrabbed(CInstantCamera &camera, const CGrabResultPtr &grabResult) override;

    void takeAPicture();            // 拍照

    QImage Pk8bitGrayToQIm(const BYTE *pBuffer, const int &bufWidth, const int &bufHight);      // 图像数据转成QImage

signals:
    void updateImage(QImage image);

private:
    CInstantCamera m_baslerCamera;  // 实例化相机对象
    INodeMap *m_nodeMap;            // 相机属性节点
    QString m_currentMode;          // 相机触发模式
    bool m_isWorkStarted = false;   // 相机是否处于工作中
    bool m_isOpened = false;        // 相机是否打开
    QMutex m_qMutex;                // 锁
    bool savePic = false;           // 是否保存图像到本地
};

#endif // BBASLERCAMERCONTROL_H
#include "bbaslercamercontrol.h"
#include <QDebug>
#include <QMessageBox>

BBaslerCamerControl::BBaslerCamerControl(QObject *parent) : QObject(parent)
{
    // When using the grab loop thread provided by the Instant Camera object,
    // an image event handler processing the grab results must be created and registered.
    m_baslerCamera.RegisterImageEventHandler(this, RegistrationMode_Append, Cleanup_Delete);    // 注册图像事件处理程序
}

void BBaslerCamerControl::initCamera()
{
    qDebug() << "Init Camera !";
    Pylon::PylonInitialize();   // 调用其他 pylon 函数之前必须调用 PylonInitialize 完成初始化
    CTlFactory &factory = CTlFactory::GetInstance();    // 获取传输层的工厂单例
    TlInfoList_t infoList;
    factory.EnumerateTls(infoList); // 获取可用的传输层列表
    for ( auto &device : infoList ) {
        qDebug() << "FriendlyName: " << device.GetFriendlyName();
        qDebug() << "FullName: " << device.GetFullName();
        qDebug() << "VendorName: " << device.GetVendorName();
        qDebug() << "DeviceClass: " << device.GetDeviceClass() ;
    }

    // 创建由传输层的设备类标识符指定的传输层对象,这里使用的是 GigE-以太网传输。还可以用USB、FireWire 和 Camera Link 等方式
    ITransportLayer *pTl = factory.CreateTl("BaslerGigE");
    DeviceInfoList_t devices;
    int n = pTl->EnumerateDevices(devices); // 获取可用的设备列表
    if (n) {
        qDebug() << "Camera Count: " << n;
    } else {
        qDebug() << "Cannot Find Any Camera !";
    }
}

void BBaslerCamerControl::destroyCamera()
{
    qDebug() << "Destroy Camera !";

    if (m_isWorkStarted) {
        stopWork();
    }

    if (m_isOpened) {
        closeCamera();
    }
    
    m_baslerCamera.DeregisterImageEventHandler(this);   // 撤销图像事件处理程序
    Pylon::PylonTerminate();                            // 释放 pylon 运行时系统分配的资源
}

int BBaslerCamerControl::openCamera()
{
    if (m_isOpened) {
        return -1;
    }

    try {
        /*
        CDeviceInfo deviceInfo;
        String_t str = String_t(serialNumber.toStdString().c_str());
        deviceInfo.SetSerialNumber(str);            // 通过传入的序列号打开相机
        deviceInfo.SetModelName("acA1300-60gm");    // 通过传入的相机名打开相机
        deviceInfo.SetUserDefinedName("Camera1");   // 通过传入的UserID打开相机
        m_baslerCamera.Attach(CTlFactory::GetInstance().CreateDevice(deviceInfo));  // 实例化相机
        */

        // 如果连接了多个相机,可以通过上述传参的方式打开指定的相机,这里只有一个相机
        m_baslerCamera.Attach(CTlFactory::GetInstance().CreateFirstDevice());   //实例化找到的第一个相机
        m_baslerCamera.Open();  // 打开相机

        qDebug() << "Open Camera !";
        m_isOpened = true;
        m_nodeMap = &m_baslerCamera.GetNodeMap();   // 获取相机属性节点
        m_currentMode = GetCameraProperty(Line1);   // 获取相机触发模式
    } catch (GenICam::GenericException &e) {
        qDebug() << "Open Camera Error: " << QString(e.GetDescription());
        return -2;
    }
    return 0;
}

int BBaslerCamerControl::closeCamera()
{
    if(!m_isOpened) {
        return -1;
    }

    try {
        if ( m_baslerCamera.IsOpen() ) {
            m_baslerCamera.DetachDevice();  // 分离连接的 pylon 设备
            m_baslerCamera.Close();         // 关闭连接的 pylon 设备

            qDebug() << "Close Camera !";
            m_isOpened = false;
            m_nodeMap = nullptr;            // 相机属性节点置空
            m_currentMode = "";             // 相机触发模式置空
        }
    } catch (GenICam::GenericException &e) {
        qDebug() << "Close Camera Error: " << QString(e.GetDescription());
        return -2;
    }
    return 0;
}

int BBaslerCamerControl::startWork()
{
    if ( !m_baslerCamera.IsOpen() ) {
        QMessageBox::warning(NULL, "Warning", "Camera is not open !", QMessageBox::Ok);
        return -1;
    }
    
    if (m_isWorkStarted) {
        QMessageBox::warning(NULL, "Warning", "Grabber already in live-mode !", QMessageBox::Ok);
        return -1;
    }

    try {
        // 开始抓取图像
        if( m_currentMode == "Freerun" )  {
            m_baslerCamera.StartGrabbing(GrabStrategy_LatestImageOnly, GrabLoop_ProvidedByInstantCamera);
        } else if( m_currentMode == "Software" ) {
            m_baslerCamera.StartGrabbing(GrabStrategy_LatestImageOnly);
        } else if( m_currentMode == "Line1" ) {
            m_baslerCamera.StartGrabbing(GrabStrategy_OneByOne, GrabLoop_ProvidedByInstantCamera);
        } else if( m_currentMode == "Line2" ) {
            m_baslerCamera.StartGrabbing(GrabStrategy_OneByOne);
        }

        qDebug() << "Start Work !";
        m_isWorkStarted = true;
        qDebug() << "The Current Work Mode Is: " << m_currentMode;
    } catch (GenICam::GenericException &e) {
        qDebug() << "Start Work Error: " << QString(e.GetDescription());
        return -2;
    }
    return 0;
}

int BBaslerCamerControl::stopWork()
{
    if (!m_isWorkStarted) {
        QMessageBox::warning(NULL, "Warning", "Grabber already in unlive-mode !", QMessageBox::Ok);
        return -1;
    }

    try {
        if ( m_baslerCamera.IsGrabbing() ) {
            m_baslerCamera.StopGrabbing();  // 停止抓取图像

            qDebug() << "Stop Work !";
            m_isWorkStarted = false;
        }
    } catch (GenICam::GenericException &e) {
        qDebug() << "Stop Work Error: " << QString(e.GetDescription());
        return -2;
    }
    return 0;
}

QString BBaslerCamerControl::GetCameraProperty(BBaslerCamerControl::BaslerCameraProperty type)
{
    QString ret = "";
    switch (type) {
    case DeviceModelName: {
        const CStringPtr deviceModelName = m_nodeMap->GetNode("DeviceModelName");
        ret = QString::fromLocal8Bit(deviceModelName->ToString().c_str());
    } break;
    case DeviceID: {
        const CStringPtr deviceID = m_nodeMap->GetNode("DeviceID");
        ret = QString::fromLocal8Bit(deviceID->ToString().c_str());
    } break;
    case ResultingFrameRateAbs: {
        const CFloatPtr resultingFrameRateAbs = m_nodeMap->GetNode("ResultingFrameRateAbs");
        ret = QString::number(resultingFrameRateAbs->GetValue());
    } break;
    case AcquisitionFrameRateAbs: {
        const CBooleanPtr acquisitionFrameRateEnable = m_nodeMap->GetNode("AcquisitionFrameRateEnable");
        acquisitionFrameRateEnable->SetValue(TRUE);
        const CFloatPtr acquisitionFrameRateAbs = m_nodeMap->GetNode("AcquisitionFrameRateAbs");
        ret = QString::number(acquisitionFrameRateAbs->GetValue());
    } break;
    case Freerun:
    case Line1: {
        const CEnumerationPtr triggerSelector = m_nodeMap->GetNode("TriggerSelector");
        triggerSelector->FromString("FrameStart");
        CEnumerationPtr triggerSource = m_nodeMap->GetNode("TriggerSource");
        ret = QString::fromLocal8Bit(triggerSource->ToString().c_str());
    } break;
    case ExposureTimeAbs: {
        const CFloatPtr exposureTimeAbs = m_nodeMap->GetNode("ExposureTimeAbs");
        ret = QString::number(exposureTimeAbs->GetValue());
    } break;
    case GainRaw: {
        const CIntegerPtr gainRaw = m_nodeMap->GetNode("GainRaw");
        ret = QString::number(gainRaw->GetValue());
    } break;
    case SensorWidth: {
        const CIntegerPtr sensorWidth = m_nodeMap->GetNode("SensorWidth");
        ret = QString::number(sensorWidth->GetValue());
    } break;
    case SensorHeight: {
        const CIntegerPtr sensorHeight = m_nodeMap->GetNode("SensorHeight");
        ret = QString::number(sensorHeight->GetValue());
    } break;
    case Width: {
        const CIntegerPtr width = m_nodeMap->GetNode("Width");
        ret = QString::number(width->GetValue());
    } break;
    case Height: {
        const CIntegerPtr height = m_nodeMap->GetNode("Height");
        ret = QString::number(height->GetValue());
    } break;
    case PixelFormat: {
        const CEnumerationPtr pixelFormat = m_nodeMap->GetNode("PixelFormat");
        ret = QString::fromLocal8Bit(pixelFormat->ToString().c_str());
    } break;
    default: ret = ""; break;
    }
    return ret;
}

void BBaslerCamerControl::SetCameraProperty(BBaslerCamerControl::BaslerCameraProperty type, double value)
{
    switch (type) {
    case AcquisitionFrameRateAbs: {
        const CBooleanPtr acquisitionFrameRateEnable = m_nodeMap->GetNode("AcquisitionFrameRateEnable");
        acquisitionFrameRateEnable->SetValue(TRUE);
        const CFloatPtr acquisitionFrameRateAbs = m_nodeMap->GetNode("AcquisitionFrameRateAbs");
        acquisitionFrameRateAbs->SetValue(value);
    } break;
    case Freerun: {
        CEnumerationPtr triggerSelector = m_nodeMap->GetNode ("TriggerSelector");
        triggerSelector->FromString("FrameStart");
        CEnumerationPtr triggerMode = m_nodeMap->GetNode("TriggerMode");
        triggerMode->SetIntValue(1);
        CEnumerationPtr triggerSource = m_nodeMap->GetNode("TriggerSource");
        triggerSource->FromString("Software");
    } break;
    case Line1: {
        CEnumerationPtr triggerSelector = m_nodeMap->GetNode ("TriggerSelector");
        triggerSelector->FromString("FrameStart");
        CEnumerationPtr triggerMode = m_nodeMap->GetNode ("TriggerMode");
        triggerMode->SetIntValue(1);
        CEnumerationPtr triggerSource = m_nodeMap->GetNode ("TriggerSource");
        triggerSource->FromString("Line1");
    } break;
    case ExposureTimeAbs: {
        const CFloatPtr exposureTimeAbs = m_nodeMap->GetNode("ExposureTimeAbs");
        exposureTimeAbs->SetValue(value);
    } break;
    case GainRaw: {
        const CIntegerPtr gainRaw = m_nodeMap->GetNode("GainRaw");
        gainRaw->SetValue(value);
    } break;
    case Width: {
        const CIntegerPtr width = m_nodeMap->GetNode("Width");
        width->SetValue(value);
    } break;
    case Height: {
        const CIntegerPtr height = m_nodeMap->GetNode("Height");
        height->SetValue(value);
    } break;
    default: break;
    }
}

void BBaslerCamerControl::printCameraProperty()
{
    if ( m_baslerCamera.IsOpen() ) {
        qDebug() << "************************************************************";
        qDebug() << "DeviceModelName: \t\t"         << GetCameraProperty(DeviceModelName);
        qDebug() << "DeviceID: \t\t"                << GetCameraProperty(DeviceID);
        qDebug() << "ResultingFrameRateAbs: \t"     << GetCameraProperty(ResultingFrameRateAbs);
        qDebug() << "AcquisitionFrameRateAbs: \t"   << GetCameraProperty(AcquisitionFrameRateAbs);
        qDebug() << "CurrentMode: \t\t"             << GetCameraProperty(Freerun);
        qDebug() << "ExposureTimeAbs: \t\t"         << GetCameraProperty(ExposureTimeAbs);
        qDebug() << "GainRaw: \t\t\t"               << GetCameraProperty(GainRaw);
        qDebug() << "SensorWidth: \t\t"             << GetCameraProperty(SensorWidth);
        qDebug() << "SensorHeight: \t\t"            << GetCameraProperty(SensorHeight);
        qDebug() << "Width: \t\t\t"                 << GetCameraProperty(Width);
        qDebug() << "Height: \t\t\t"                << GetCameraProperty(Height);
        qDebug() << "PixelFormat: \t\t"             << GetCameraProperty(PixelFormat);
        qDebug() << "************************************************************";
    }
}

void BBaslerCamerControl::OnImageGrabbed(CInstantCamera &camera, const CGrabResultPtr &grabResult)
{
    camera.IsGrabbing();

    m_qMutex.lock();

    if (savePic) {
        // Save this frame of data to local.
        static int num = 1;
        char filename[MAX_PATH];
        sprintf_s( filename, "image%02i.bmp", num );
        num++;
        CImagePersistence::Save(ImageFileFormat_Bmp, filename, grabResult);
        qDebug() << "Saved " << QString::fromUtf8(filename) << " to local !";

        savePic = false;
    }
    
//    uchar* buff = (uchar*)grabResult->GetBuffer();
//    int nWidth = grabResult->GetWidth();
//    int nHeight = grabResult->GetHeight();
//    QImage image = Pk8bitGrayToQIm(buff, nWidth, nHeight);

    CImagePersistence::Save(ImageFileFormat_Bmp, "GrabbedImage.bmp", grabResult);
    QImage image("GrabbedImage.bmp", "bmp");
    emit updateImage(image);

    m_qMutex.unlock();
}

void BBaslerCamerControl::takeAPicture()
{
    if ( !m_baslerCamera.IsGrabbing() ) {
        QMessageBox::warning(NULL, "Warning", "Grabber is in unlive-mode !", QMessageBox::Ok);
        return;
    }

    savePic = true;
}

QImage BBaslerCamerControl::Pk8bitGrayToQIm(const BYTE *pBuffer, const int &bufWidth, const int &bufHight)
{
    // 对参数的有效性进行检查
    assert((pBuffer != NULL) && (bufWidth>0) && (bufHight>0));

    QVector<QRgb> vcolorTable;

    for (int i = 0; i < 256; i++)
    {
        vcolorTable.append(qRgb(i, i, i));
    }

    int biBitCount = 8; // 灰度图像像素bit数
    int lineByte = (bufWidth * biBitCount/8 + 3) / 4 * 4; // bmp行byte数(格式宽度,为4的倍数)

    if (bufWidth == lineByte) // 判断图像宽度与格式宽度
    {
        QImage qIm = QImage(pBuffer, bufWidth, bufHight, QImage::Format_Indexed8);  // 封装QImage
        qIm.setColorTable(vcolorTable); // 设置颜色表

        return qIm;
    }
    else
    {
        BYTE *qImageBuffer = new BYTE[lineByte * bufHight]; // 分配内存空间
        uchar *QImagePtr = qImageBuffer;

        for (int i = 0; i < bufHight; i++) // Copy line by line
        {
            memcpy(QImagePtr, pBuffer, bufWidth);
            QImagePtr += lineByte;
            pBuffer += bufWidth;
        }

        QImage qImage = QImage(qImageBuffer, bufWidth, bufHight, QImage::Format_Indexed8);  // 封装QImage
        qImage.setColorTable(vcolorTable); // 设置颜色表

        return qImage;
    }
}

使用比较简单,直接调用就行

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "bbaslercamercontrol.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_startBtn_clicked();

    void on_endBtn_clicked();

    void on_picBtn_clicked();

private:
    Ui::MainWindow *ui;
    BBaslerCamerControl* m_control = nullptr;
};

#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_control = new BBaslerCamerControl(this);
    m_control->initCamera();
    m_control->openCamera();
    m_control->printCameraProperty();

    connect(m_control, &BBaslerCamerControl::updateImage, [=](QImage img) {
        ui->label->setPixmap(QPixmap::fromImage(img));
    });
}

MainWindow::~MainWindow()
{
    m_control->destroyCamera();
    delete ui;
}

void MainWindow::on_startBtn_clicked()
{
    m_control->startWork();
}

void MainWindow::on_endBtn_clicked()
{
    m_control->stopWork();
}

void MainWindow::on_picBtn_clicked()
{
    m_control->takeAPicture();
}

其他请参考 Qt调用工业相机之映美精相机

发布了73 篇原创文章 · 获赞 361 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_34139994/article/details/105653286