(二)Qt下多线程实现多个海康工业相机内触发采集回调取流显示

这篇具有很好参考价值的文章主要介绍了(二)Qt下多线程实现多个海康工业相机内触发采集回调取流显示。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录

提示:这里是该系列文章的所有文章的目录
第一章:(一)Qt下实现多个海康工业相机内触发采集回调取流显示
第二章:(二)Qt下多线程实现多个海康工业相机内触发采集回调取流显示



前言

在本系列的上一篇文章中,我们讲述了实现海康工业相机的连接,采用内触发采集模式,并使用回调取流的方式来获取图像并实现界面上两个相机的显示,但是发现在多个相机下要写多个回调函数是不太合适的,所以在这里增加了一个线程类,使用多线程的方式对前文的demo进行优化,这里对该示例进行讲解,以便大家学习,如有错误之处,欢迎大家批评指正。

项目效果
(二)Qt下多线程实现多个海康工业相机内触发采集回调取流显示,Qt+OpenCV+海康工业相机,qt,海康工业相机


提示:以下是本篇文章正文内容,下面案例可供参考

一、创建线程类

在HikSdk文件夹下添加GrabImgThread类,在类的构造函数中赋值相应的相机号,以区分多个相机,在线程类中设置相机指针和相机回调函数,以及添加一个signal_imageReady信号

//回调函数
void __stdcall GrabImgThread::ImageCallback(unsigned char * pData,MV_FRAME_OUT_INFO_EX* pFrameInfo,void* pUser)
{
    LOGDEBUG<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz ")<<"回调函数执行了";
    GrabImgThread* pThread = static_cast<GrabImgThread *>(pUser);

    //创建QImage对象
    QImage showImage = QImage(pData,pFrameInfo->nWidth,pFrameInfo->nHeight,QImage::Format_RGB888);

    //发送信号,通知主界面更新图像
    emit pThread->signal_imageReady(showImage,pThread->m_cameraId);
}

修改后的项目结构如下:
(二)Qt下多线程实现多个海康工业相机内触发采集回调取流显示,Qt+OpenCV+海康工业相机,qt,海康工业相机

二、关联线程对象

图像显示流程与之前还是一样的,只不过在这里将相机对象与线程对象进行了关联,在初始化的按钮槽函数中注册了线程对象中的回调函数,开启采集后线程对象通过信号与槽的方式将回调函数中的图像数据发送到主界面进行显示

for(int i=0;i<2;i++)
{
	//相机对象
    m_myCamera[i] = new CMvCamera;

    //线程对象
    m_grabThread[i] = new GrabImgThread(i);
    connect(m_grabThread[i],SIGNAL(signal_imageReady(QImage,int)),this,SLOT(slot_imageReady(QImage,int)),Qt::BlockingQueuedConnection);
	
	···
	
	//设置线程对象中的回调函数
	m_grabThread[i]->setCameraPtr(m_myCamera[i]);
}

三、示例完整代码

1.grabimgthread.h

#ifndef GRABIMGTHREAD_H
#define GRABIMGTHREAD_H

#include <QThread>
#include <QImage>
#include <QDateTime>
#include "HikSdk/cmvcamera.h"

class GrabImgThread : public QThread
{
    Q_OBJECT

public:
    explicit GrabImgThread(int cameraId);
    ~GrabImgThread();

    void setCameraPtr(CMvCamera *camera);

    void run();

signals:
    void signal_imageReady(const QImage &image,int cameraId);

private:
    static void __stdcall ImageCallback(unsigned char * pData,MV_FRAME_OUT_INFO_EX* pFrameInfo,void* pUser);

private:
    int m_cameraId;
    CMvCamera *m_cameraPtr;

};

#endif // GRABIMGTHREAD_H

2.grabimgthread.cpp

#include "grabimgthread.h"

GrabImgThread::GrabImgThread(int cameraId)
    : m_cameraId(cameraId)
{

}

GrabImgThread::~GrabImgThread()
{

}

//设置相机指针
void GrabImgThread::setCameraPtr(CMvCamera *camera)
{
    m_cameraPtr = camera;

    //注册回调函数
    //nRet = m_myCamera[i]->RegisterImageCallBack(ImageCallback,this);    //单色相机
    int nRet = m_cameraPtr->RegisterImageCallBackRGB(ImageCallback,this);   //彩色相机
    if(MV_OK != nRet)
    {
        LOGDEBUG<<"m_cameraId:"<<m_cameraId<<"注册回调函数失败!";
        return;
    }
}

//线程运行
void GrabImgThread::run()
{

}

//回调函数
void __stdcall GrabImgThread::ImageCallback(unsigned char * pData,MV_FRAME_OUT_INFO_EX* pFrameInfo,void* pUser)
{
    LOGDEBUG<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz ")<<"回调函数执行了";
    GrabImgThread* pThread = static_cast<GrabImgThread *>(pUser);

    //创建QImage对象
    QImage showImage = QImage(pData,pFrameInfo->nWidth,pFrameInfo->nHeight,QImage::Format_RGB888);

    //发送信号,通知主界面更新图像
    emit pThread->signal_imageReady(showImage,pThread->m_cameraId);
}

3.mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDateTime>
#include "HikSdk/grabimgthread.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

    void initWidget();

    void showImage(QImage showImage,int index);

private slots:
    void slot_imageReady(const QImage &image,int cameraId);

    void on_pb_init_clicked();
    void on_pb_start_clicked();
    void on_pb_stop_clicked();

private:
    Ui::MainWindow *ui;

    CMvCamera *m_myCamera[2];             //相机对象
    GrabImgThread *m_grabThread[2];       //捕获图像线程
    MV_CC_DEVICE_INFO *m_deviceInfo[2];   //设备信息
    MV_CC_DEVICE_INFO_LIST m_stDevList;   //设备信息列表
};
#endif // MAINWINDOW_H

4.mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

MainWindow::~MainWindow()
{
    delete ui;

    for(int i=0;i<2;i++)
    {
        if(m_myCamera[i])
        {
            m_myCamera[i]->Close();
            delete m_myCamera[i];
            m_myCamera[i] = NULL;
        }
    }
}

void MainWindow::initWidget()
{
    for(int i=0;i<2;i++)
    {
        //相机对象
        m_myCamera[i] = new CMvCamera;

        //线程对象
        m_grabThread[i] = new GrabImgThread(i);
        connect(m_grabThread[i],SIGNAL(signal_imageReady(QImage,int)),this,SLOT(slot_imageReady(QImage,int)),Qt::BlockingQueuedConnection);
    }
}

//显示图像
void MainWindow::slot_imageReady(const QImage &image,int cameraId)
{
    QPixmap showPixmap = QPixmap::fromImage(image).scaled(QSize(250,200),Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
    if(cameraId == 0)
    {
        ui->lb_time_1->setText("相机1:" + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz"));
        ui->lb_image_1->setPixmap(showPixmap);
    }
    else
    {
        ui->lb_time_2->setText("相机2:" + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz"));
        ui->lb_image_2->setPixmap(showPixmap);
    }
}

//初始化
void MainWindow::on_pb_init_clicked()
{
    //枚举子网内所有设备
    memset(&m_stDevList,0,sizeof(MV_CC_DEVICE_INFO_LIST));
    int nRet = CMvCamera::EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE,&m_stDevList);
    if(MV_OK != nRet)
    {
        LOGDEBUG<<"枚举相机设备失败!";
        return;
    }

    int deviceNum = m_stDevList.nDeviceNum;
    LOGDEBUG<<"相机连接数量:"<<deviceNum;
    if(deviceNum > 2)
    {
        //我这里只定义了两个相机对象,所以限制为2,实际情况需要根据相机数量定义头文件中的对象数
        deviceNum = 2;
    }
    for(int i=0;i<deviceNum;i++)
    {
        MV_CC_DEVICE_INFO *pDeviceInfo = m_stDevList.pDeviceInfo[i];
        QString strSerialNumber = "";
        if(pDeviceInfo->nTLayerType == MV_GIGE_DEVICE)
        {
            strSerialNumber = (char*)pDeviceInfo->SpecialInfo.stGigEInfo.chSerialNumber;
        }
        else if(pDeviceInfo->nTLayerType == MV_USB_DEVICE)
        {
            strSerialNumber = (char*)pDeviceInfo->SpecialInfo.stUsb3VInfo.chSerialNumber;
        }
        else
        {
            LOGDEBUG<<"警告,未知设备枚举!";
            return;
        }
        LOGDEBUG<<"i:"<<i<<"   strSerialNumber:"<<strSerialNumber;
        if(i == 0)
        {
            ui->lb_name_1->setText(strSerialNumber);
        }
        else if(i == 1)
        {
            ui->lb_name_2->setText(strSerialNumber);
        }

        //根据相机序列号指定相机对象,就可以指定某个窗口进行显示
        //if(strSerialNumber == "DA0333897")
        //{
        //    m_deviceInfo[0] = pDeviceInfo;
        //}
        //else if(strSerialNumber == "DA0424312")
        //{
        //    m_deviceInfo[1] = pDeviceInfo;
        //}

        //不指定
        m_deviceInfo[i] = pDeviceInfo;

        //打开相机
        int nRet = m_myCamera[i]->Open(m_deviceInfo[i]);
        if(MV_OK != nRet)
        {
            LOGDEBUG<<"i:"<<i<<"打开相机失败!";
            return;
        }
        else
        {
            //关闭触发模式
            nRet = m_myCamera[i]->SetEnumValue("TriggerMode",0);
            if(MV_OK != nRet)
            {
                LOGDEBUG<<"i:"<<i<<"关闭触发模式失败!";
                return;
            }

            //设置线程对象中的回调函数
            m_grabThread[i]->setCameraPtr(m_myCamera[i]);
        }
    }
}

//开始取图
void MainWindow::on_pb_start_clicked()
{
    for(int i=0;i<2;i++)
    {
        int nRet = m_myCamera[i]->StartGrabbing();
        if (MV_OK != nRet)
        {
            LOGDEBUG<<"i:"<<i<<"开始取图失败!";
            return;
        }
    }
}

//停止取图
void MainWindow::on_pb_stop_clicked()
{
    for(int i=0;i<2;i++)
    {
        int nRet = m_myCamera[i]->StopGrabbing();
        if (MV_OK != nRet)
        {
            LOGDEBUG<<"i:"<<i<<"停止取图失败!";
            return;
        }
    }
}

5.mainwindow.ui
(二)Qt下多线程实现多个海康工业相机内触发采集回调取流显示,Qt+OpenCV+海康工业相机,qt,海康工业相机

四、下载链接

我的示例百度网盘链接:https://pan.baidu.com/s/1SpWcRc0WnnaBAjS1lfoyfA
提取码:xxcj


总结

通过多线程的方式,就不用写多个回调函数了,也是实现了多个海康工业相机内触发采集回调取流,这样做是比较简便的,同时也防止了整个项目代码过于冗余。文章线程类中注册回调函数中有提到单色和彩色两种相机,这个示例的是彩色相机的取图,如果是单色的,需要注意在回调函数中进行QImage类型转换的时候,要将其中的QImage::Format_RGB888修改为QImage::Format_Indexed8

常用的还可能需要转换为cv::Mat类型的图像,这里也简单介绍一下
//创建cv::Mat对象
cv::Mat showMat(pFrameInfo->nHeight,pFrameInfo->nWidth,CV_8UC1,pData); //单色
cv::Mat showMat(pFrameInfo->nHeight,pFrameInfo->nWidth,CV_8UC3,pData); //彩色


hello:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。文章来源地址https://www.toymoban.com/news/detail-575851.html

到了这里,关于(二)Qt下多线程实现多个海康工业相机内触发采集回调取流显示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 海康工业相机SDK连接demo,Qt界面显示

    在机器视觉开发过程中,经常使用工业相机采集图像,以下采用海康机器人提供的SDK开发demo,使用语言C++,界面显示使用的Qt。SDK来自MVS 3.1版本中附属的Development文件夹。完整的项目链接地址为: 海康工业相机SDK的Demo源代码C++版本 附录海康工业相机的命名方式: 海康工业相

    2024年02月13日
    浏览(59)
  • (三)Qt+OpenCV调用海康工业相机SDK抓拍示例

    提示:这里是该系列文章的所有文章的目录 第一章: (一)Qt+OpenCV调用海康工业相机SDK示例开发 第二章: (二)Qt多线程实现海康工业相机图像实时采集 第三章: (三)Qt+OpenCV调用海康工业相机SDK抓拍示例 在这系列文章中,讲述了Qt下结合OpenCV与海康工业相机的使用,对

    2024年04月08日
    浏览(88)
  • (一)Qt+OpenCV调用海康工业相机SDK示例开发

    提示:这里是该系列文章的所有文章的目录 第一章: (一)Qt+OpenCV调用海康工业相机SDK示例开发 第二章: (二)Qt多线程实现海康工业相机图像实时采集 近期在Qt环境下进行海康工业相机的使用开发,发现海康提供的示例没有Qt的demo,而其中有基于MFC框架的示例,所以在这

    2024年02月03日
    浏览(99)
  • 海康机器人工业相机 Win10+Qt+Cmake 开发环境搭建

    参考这个链接安装好MVS客户端 Qt新建一个c++项目 cmakeList中添加海康机器人的库,如下: main.cpp中添加以下代码 运行程序,出现以下内容则说明安装库成功

    2024年02月11日
    浏览(54)
  • Baumer工业相机堡盟工业相机如何通过BGAPISDK的软触发实现两相机的同步采集(C#)

    ​ Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度

    2023年04月13日
    浏览(53)
  • 相机通用类之海康相机,软触发硬触发(飞拍),并输出halcon格式对象

    整体过程其实比较简单,由于海康相机没有像一些品牌相机一样可以直接使用序列号开启相机,所以我们需要通过对相机信息进行索引,根据索引到的相机序列号来开启相机。 如何显示图像:可以访问我文章开头的博客,通过编写相机通用类即可,程序中是有继承通用类,通

    2024年02月04日
    浏览(180)
  • 海康工业相机使用教程

    (1)区分电源适配器正负极 (2)连接相机电源线缆 (3)连接完成后,相机蓝色灯常亮则成功 (1)MVS客户端下载地址(下载3.4.3windows) MVS客户端官网下载 (2)打开安装包默认安装即可 (3)双击MVS图标打开客户端软件

    2024年02月09日
    浏览(46)
  • VisionMaster连接工业相机(海康)

    工业相机一般都需要独立供电,12v接上相机的正负极,另外网口接上电脑或交换机Lan口,建议使用千兆网口,不然帧率跟不上(也可以使用网口转usb3.0). 添加图像源  点击上方相机图标  设置相机参数 选择全局相机  有枚举相机(就是全部的)  和跨网段(通过ip链接   需

    2024年02月07日
    浏览(51)
  • opencv——连接/控制工业相机(海康)

    1.自动抓取图像 通过接受前步传输的指令而实现相机的自动抓取图像 2.定时抓取图像 通过自定义设置延时时间而实现相机的定时抓取图像 3.特定按键控制抓取图像 通过自定义特定按键而实现相机的人为控制抓取图像 以上就是三种实现Python/opencv工业相机控制的方法啦!

    2024年02月12日
    浏览(38)
  • C# 开源SDK 工业相机库 调用海康相机 大恒相机

    c# 相机库,含海康、大恒品牌2D相机的常用功能。 底层采用回调+信号量模式封装 ,最大程度减小线程资源,提高采图效率。 开源地址 :https://gitee.com/laomaogu/mgcamctrl 现只兼容了大恒和海康,都是常用的 其他相机,看我老板啥时候换品牌吧,或者换老板? 当然如果小伙伴感兴

    2024年04月26日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包