【重明】机器视觉QT/C++实现工业相机二次开发框架

工业相机二次开发是机器视觉行业必不可少的技能之一。
而如何实现一个框架,能够兼容所有工业相机二次开发,从而支持多种类型的工业相机,就是机器视觉行业的进阶技能了。
请添加图片描述
重明工业相机二次开发项目就是在实现相机二开框架的基础上,完成了海康工业相机的二次开发。
项目源码下载地址:
https://www.roundvision.cc/softwaredevelopment/qt/chongming/
技术栈:
1、C++
2、 QT 5.14.2
3、Opencv 4.5.5
4、工业相机SDK二次开发
重明工业相机二次开发项目框架如下图所示:
在这里插入图片描述
整个项目分前端部分的界面设计,和后端部分的工业相机框架设计。

1、界面GUI实现

重明的界面实现非常简洁,主要为三个部分:
左侧的相机列表,中间的图像显示,右侧的相机参数属性列表。
在这里插入图片描述
控制窗口的实现非常简单,其实就是一排按钮加一个QListWidget列表,用来显示所有检测到的工业相机。
视觉窗口用来显示图像,采用QT的视图模型框架,采用QGrapicsScene来实现的。
属性窗口主要涉及到了QT的MVD框架,即Model-View-Delegate框架,模型-视图-代理,通过视图代理,完成了对各个不同属性参数类型的支持,完成了相机参数属性Int,double,bool,cmd,string等多种类型的显示。

2、后端框架接口

实现了前端界面,现在我们可以考虑,如何抽象工业相机接口类,实现对不同工业相机的无差别接入,达到工业相机二次开发框架的效果呢?
这里可以借用QT插件的便利性,来设计工业相机抽象插件接口:

 //相机接口类
class CameraInterface
{
public:CameraInterface(const CameraMetaInfo& info){m_cameraInfo = info;}virtual ~CameraInterface() {}//获取相机用户定义名称virtual std::string UserName(){return m_cameraInfo.UserDefineID;}//获取相机序列号virtual std::string Serial(){return m_cameraInfo.Serial;}//获取相机参数列表virtual uint32_t getParamList(std::vector<CameraParam>& paramList) = 0;//判断相机是否连接virtual bool isConnect() = 0;//判断相机是否拉流virtual bool isGrabbing() = 0;//初始化相机对象virtual uint32_t acquire() = 0;//释放相机virtual uint32_t release() = 0;//连接相机virtual uint32_t connect() = 0;//断开连接virtual uint32_t disconnect() = 0;//创建拉流资源virtual uint32_t creatStream() = 0;//销毁拉流资源virtual uint32_t destroyStream() = 0;//开启拉流virtual uint32_t startGrabbing() = 0;//停止拉流virtual uint32_t stopGrabbing() = 0;//导入配置文件virtual uint32_t loadConfig(const std::string path) = 0;//导出配置文件virtual uint32_t saveConfig(const std::string path) = 0;//获取配置文件格式virtual std::string configFormat() = 0;//读取相机参数virtual uint32_t readParam(CameraParam& param) = 0;//写入相机参数virtual uint32_t writeParam(CameraParam& param) = 0;//获取实时图像virtual uint32_t getImageLast(cv::Mat& image) = 0;//获取图像队列virtual CameraImageQueue& ImageQueue(){return m_imageQueue;}protected:CameraImageQueue m_imageQueue;//图像队列std::vector<CameraParam> m_cameraParams;//相机参数列表CameraMetaInfo m_cameraInfo;//相机元信息
};

通过抽象设计统一的相机行为接口,在通过层层封装,即可达到框架效果。

如何实现相机图像队列

相机出图速度是有差异的,而我们处理相机出图也会有所耗时,如果你是出一张图像处理一张,然后再去拿一张图像,那很容易造成丢帧的问题。所以设计一个缓冲队列是非常有必要的。

我们的图像队列内部会包含两个队列,一个空闲队列,一个工作队列。
在我们相机图像队列这个应用场景下,生产者就是相机SDK的回调函数,该回调函数会生成相机的原始图像数据,我们在回调函数内将原始图像数据加入到队列中。
加入到队列是先看空闲队列有没有位置,如果有则加入到空闲队列,然后触发信号量激活消费者。如果空闲队列没有位置,则从工作队列取出最旧的图像,将原始数据加入到该位置。
我们的消费者,就是我们的取图线程,我们软件会不停的从队列中的工作队列中尝试取出图像,当工作队列为空时,会阻塞在信号量中,当生产者生产了一张图像后,会激活该信号量使取图线程取到图像。
图像队列代码实现:


#define TIME_OUT_MS		5000	//取图超时时间
#define ImageQueueSize	10		//图像队列长度宏定义class CameraImageQueue
{
public:CameraImageQueue();CameraImageQueue(int maxSize);//向图像队列中加入图像uint32_t Put(const cv::Mat& m);//从图像队列中取出图像uint32_t Take(cv::Mat& m);//队列是否为空bool Empty();//队列是否为满bool Full();//队列当前长度size_t Size();
private:bool isFull() const{bool full = workImageQueue.size() >= m_queueSize;return full;}bool isEmpty() const{bool empty = workImageQueue.empty();return empty;}bool NotFull() const{bool full = workImageQueue.size() >= m_queueSize;return !full;}bool NotEmpty() const{bool empty = workImageQueue.empty();return !empty;}private:std::mutex m_mutex;std::condition_variable m_condition;std::queue<cv::Mat> freeImageQueue;//空闲队列std::queue<cv::Mat> workImageQueue;//工作队列uint8_t m_queueSize;bool m_needStop;
};

THE END

项目源码下载地址:
https://www.roundvision.cc/softwaredevelopment/qt/chongming/
项目由丰富的视频教程,见BiliBili:
在这里插入图片描述
视频链接:https://www.bilibili.com/video/BV1pp4y1n7X9

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/345215.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NetApp E系列(E-Series)OEM产品介绍以及如何收集日志和保存配置信息

NetApp E系列是NetApp收购LSI存储后建立的一条新的产品线&#xff0c;由于LSI存储的历史悠久&#xff0c;所以这条产品线给NetApp带来了很多的OEM产品&#xff0c;可以说E系列是世界上OEM给最多公司的存储产品线也不为过&#xff0c;因为最早LSI的产品销售测率就是OEM&#xff…

阿尔泰科技——PXIe8912/8914/8916高速数据采集卡

阿尔泰科技PXIe8912/8914/8916高速数据采集卡是2通道同步采样数字化仪&#xff0c;专为输入信号高达 100M 的高频和高动态范围的信号而设计。 与Labview无缝连接&#xff0c;提供图形化API函数。模拟输入范围可以通过软件编程设置为1V 或者5V。配备了容量高达 2GB的板载内存。…

代码随想录 Leetcode160. 相交链表

题目&#xff1a; 代码(首刷看解析 2024年1月13日&#xff09;&#xff1a; class Solution { public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode *A headA, *B headB;while (A ! B) {A A ! nullptr ? A->next : headB;B B ! nullpt…

云端绘影,让青玉案跃然眼前

编辑&#xff1a;阿冒 设计&#xff1a;沐由 “东风夜放花千树&#xff0c;更吹落&#xff0c;星如雨。宝马雕车香满路。凤箫声动&#xff0c;玉壶光转&#xff0c;一夜鱼龙舞。” 每每诵读这首《青玉案》&#xff0c;那种花灯耀眼、乐声盈耳的元夕盛况就会立刻浮现在脑海中&am…

冷风机系统的拟定和制冷循环的热力计算

一&#xff0c;冷风机系统的概述 单元式冷风机是一种不带加湿器的非热泵型单元式空气调节机&#xff0c;只能用于夏季降温&#xff0c;按标准 GB/T 17758-1999《单元式空气调节机组》的规定1&#xff0c;单元式冷风机应能使室内温度保持在(18℃-25℃)1℃&#xff0c;相对温度 (…

自定义数据实现SA3D

SA3D&#xff1a;Segment Anything in 3D with NeRFs 实现了3D目标分割 原理是利用SAM(segment anything) 模型和Nerf分割渲染3D目标&#xff0c; SAM只能分块&#xff0c;是没有语义标签的&#xff0c;如何做到语义连续&#xff1f; SA3D中用了self-prompt, 根据前一帧的mask…

Altium开源硬件

1、FMC ADC 250M 16B 4CHA 2、VME FMC Carrier VFC 3、armadillo 4、FMC DEL 1ns 4cha 5、FMC Carrier tester 6、FMC ADC 1G 8b 2cha 7、HiCCE-FMC-128 8、FMC ADC 130M 16b 4cha 9、VME ADC 250k 16b 36cha 10、FMC DIO 32ch TTL a 11、FMC DAC 600M 12b 1cha DD…

多无人机编队避障(人工势场法)

matlab2020正常运行&#xff0c;预设编队类型&#xff0c;目标位置&#xff0c;障碍物 多无人机编队避障&#xff08;人工势场法&#xff09;资源-CSDN文库

数据仓库研发规范

数据仓库研发规范 本文将介绍数据仓库研发规范的阶段规划、角色职责和整体流程。 在大数据时代&#xff0c;规范地进行数据资产管理已成为推动互联网、大数据、人工智能和实体经济深度融合的必要条件。贴近业务属性、兼顾研发各阶段要点的研发规范&#xff0c;可以切实提高研…

RocketMQ源码阅读-Producer发消息

RocketMQ源码阅读-Producer发消息 1. 从单元测试入手2. 启动过程3. 同步消息发送过程4. 异步消息发送过程5. 小结 Producer是消息的生产者。 Producer和Consummer对Rocket来说都是Client&#xff0c;Server是NameServer。 客户端在源码中是一个单独的Model&#xff0c;目录为ro…

HackTheBox - Medium - Linux - Faculty

Faculty Faculty 是一台中型 Linux 机器&#xff0c;具有 PHP Web 应用程序&#xff0c;该应用程序使用的库容易受到本地文件包含的影响。利用该库中的 LFi 会泄露一个密码&#xff0c;该密码可用于通过 SSH 以名为“gbyolo”的低级用户身份登录。用户“gbyolo”有权作为“dev…

whistle代理+mock轻松解决“页面端“测试接口没数据难题

0、whistle是什么&#xff1f;怎么用&#xff1f; 自行百度&#xff0c;此处不再赘述&#xff01; 1、示例演示&#xff08;交易订单测试&#xff09; 背景和痛点最近在测试一个小需求&#xff0c;需要涉及订单侧服务商品库侧服务库存侧服务财务侧线下交易服务。痛点主要在订…