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

news/2024/4/17 11:05:33

系列文章目录

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


文章目录

  • 系列文章目录
  • 前言
  • 一、创建线程类
  • 二、关联线程对象
  • 三、示例完整代码
  • 四、下载链接
  • 总结


前言

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

项目效果
请添加图片描述


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

一、创建线程类

在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);
}

修改后的项目结构如下:
请添加图片描述

二、关联线程对象

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

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_OBJECTpublic: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_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic: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
请添加图片描述

四、下载链接

我的示例百度网盘链接: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:
共同学习,共同进步,如果还有相关问题,可在评论区留言进行讨论。


http://www.ppmy.cn/news/913175.html

相关文章

2.CSS布局

1盒子模型的宽度 (offsetwidth)=content宽度+padding左+pading右+boder左+border右 (不含margin) 2 margin纵向重叠 指相邻的两个元素如果同时设置了margin-top和margin-bottom会发生重叠现象。

光学AG喷涂镀膜的机械设计

光学AG喷涂镀膜的机械设计 定义起始点平板移动速度喷枪移动速度双循环

什么是真空镀膜?

生活中为了能满足产品耐腐蚀、耐磨损等性能&#xff0c;需要在金属表面做一层防护处理&#xff0c;传统的金属表面处理方法主要包括&#xff1a;镀锌、电泳&#xff0c;发蓝&#xff0c;发黑&#xff0c;钝化&#xff0c;磷化&#xff0c;喷涂&#xff0c;着色&#xff0c;烤漆…

介绍了光学镀膜

介绍了光学镀膜   光学涂层被用来操纵一个光学元件的反射率和透射率。典型的光学涂层的例子包括&#xff1a;增透膜而降低光在给定波长或波长范围反射的光量;窄带滤波器允许的波长只有一个给定的窗口来传输;和高反射涂料&#xff0c;在制作反射镜使用。更具体地&#xff0c;定…

汽车模具是汽车工业的重要基础工艺装备

汽车模具是汽车工业的重要基础工艺装备。在汽车生产中&#xff0c;90&#xff05;以上的零部件都需要依靠模具成形&#xff0c;60&#xff05;&#xff5e;70&#xff05;的金属零部件需经塑性加工成形。冲压是金属塑性成形的一种最基本、最传统&#xff0c;也是最重要的金属加…

汽车前大灯模具设计

成型零件设计 由于模具为大型模具&#xff0c;分型面复杂&#xff0c;故成型零件和模板采用一体式结构&#xff0c;即模具的定模A板就是定模成型零件&#xff0c;模具的动模B板就是动模成型零件。这种结构的优点是结构紧凑&#xff0c;强度刚性好&#xff0c;模具体积小&#…

汽车车身覆盖件冲压工艺模具设计

目 录 摘 要 1 Abstract 2 第一章绪论 3 1.1冲压模具介绍 3 1.2冲压模具的现况 4 1.3冲压模具的未来展望 4 1.4本文研究内容 5 第二章 产品工艺分析 7 2.1产品材料和性能分析 7 2.2产品的零件结构 7 2.2.1 几何形状 7 2.2.2最小圆角半径 7 2.2.3冲裁件上的悬臂和凹槽 8 2.2.4冲…

电镀工艺基础理论

电镀工艺基础理论 一、电镀概述 简单来说&#xff0c;电镀指借助外界直流电的作用&#xff0c;在溶液中进行电解反应&#xff0c; 使导电体例如金属的表面沉积一金属或合金层。我们以硫酸铜的电镀作例子: 硫酸铜镀液主要有硫酸铜 、硫酸和水&#xff0c;甚至也有其它添加剂。…

汽车新能源电子器件焊接表面油脂污染度清洁度检测方案

汽车新能源电子器件焊接表面油脂污染度清洁度检测方案&#xff0c;激光焊是一种以聚焦的激光束作为能源轰击焊件所产生的热量进行焊接的方法。由于激光具有折射、聚焦等光学性质&#xff0c;使得激光焊非常适合于微型零件和可达性很差的部位的焊接。激光焊还有热输入低&#xf…

发动机涂胶质量照相检测

涂胶质量照相检测。如发动机油底壳、油封、罩盖、前盖涂胶等。视觉检测防错过程为照相检测涂胶轨迹与断胶&#xff0c;通过检测得出胶线轨迹&#xff0c;对整个轨迹进行检测&#xff0c;任意点出现轨迹偏移或断胶则相机报警&#xff0c;工件不能流入到下一个工位。 发动机前盖涂…

AUTOSAR从入门到精通-【应用篇】基于 LIN 总线的雨量传感器与雨刷器控制系统的研究

目录 前言 汽车雨刷器的发展历程与发展趋势 车用雨量传感器研究现状 LIN 总线技术

电影类平台如何选择服务器

1、数据存储 电影网站对服务器的要求是比较高的&#xff0c;对存储空间的需求特别大&#xff0c;所以在服务器选择上首先要确保足够大的存储空间。另外&#xff0c;当你的网站内容特别多时&#xff0c;内存不够用&#xff0c;可以选择增加内存&#xff0c;这一服务大多数服务商…

互联网电影院5G让3D体验更流畅

移动电影院V2.0&#xff0c;推出了“约亲友”、“约影迷”、“专业场”、“首映礼”等不同场景选择&#xff0c;在打“个性化观影”的同时&#xff0c;兼顾用户在不同场景下的观影需求&#xff0c;实现了用户的“观影社交化”。 更新升级后的移动巨幕体验和移动3D效果&#xf…

AI读图片问题和多通道问题

numpy 和 opencv image.io 是RGB格式 而opencv是BGR模式 # opencv转imageio cv_img v2.cvtColor(image_io_img , cv2.COLOR_RGB2BGR) image_io_img v2.cvtColor(cv_img , cv2.COLOR_BGR2RGB)# opencv转PIL pil_img Image.fromarray(cv2.cvtColor(cv_img, cv2.COLOR_BGR2RG…

买票看电影的问题

Question: 有 2n 个人排队进电影院&#xff0c;票价是 50 美分。在这 2n 个人当中&#xff0c;其中 n 个人 只有 50 美分&#xff0c;另外 n 个人有 1 美元&#xff08;纸票子&#xff09;。愚蠢的电影院开始卖票时 1 分 钱也没有。 问&#xff1a; 有多少种排队方法 使得 每当…

牛客小白月赛76 MoonLight的运算问题(经典错误)

月色哥哥手中有一个数字 xxx&#xff0c;最初 x0x0x0。 给出一个长度为 nnn 的序列 aaa&#xff0c;月色哥哥会从序列的第一个元素 a1​ 按顺序看到序列的最后一个元素 an​。对于序列的第 i个元素 ai&#xff0c;月色哥哥可以进行下面的操作之一&#xff1a; 令 xx⋅ai​&am…

通过动态IP解决网络数据采集问题

动态地址的作用 说到Python网络爬虫&#xff0c;很多人都会遇到困难。最常见的就是爬取过程中IP地址被屏蔽。虽然大部分都是几个小时内自动解封的&#xff0c;但这对于分秒必争的python网络爬虫来说&#xff0c;是一个关键性的打击&#xff01;当一个爬虫被阻塞时&#xff0c;…

还在寻找会声会影破解版?有了这些快捷事半功倍(内涵资源)

本期跟大家分享一下在会声会影剪辑视频中经常使用到的一些快捷键&#xff0c;熟练地掌握可以很大程度上提高我们剪辑视频的效率。&#xff08;福利在文章尾&#xff01;&#xff09; 首先是菜单命令快捷键&#xff08;会声会影右上角的那一栏&#xff09;&#xff1a;Ctrl N&a…

【多线程】(三)阻塞式队列和生产者消费者模型

文章目录 一、什么是阻塞式队列二、Java库中的阻塞式队列三、阻塞式队列的模拟实现四、生产者消费者模型4.1 什么是生产者消费者模型4.2 基于阻塞队列实现简单的生产者消费者模型 一、什么是阻塞式队列 阻塞式队列&#xff08;Blocking Queue&#xff09; 是一种特殊的队列&am…
最新文章