海康工业相机SDK + OpenCV实例(5):

相机双线程读写缓存策略


文章目录

  • 海康工业相机SDK + OpenCV实例(5):
  • 相机双线程读写缓存策略
  • 前言
  • 一、双线程
  • 二、缓存区容量为2的生产消费思想
  • 三、相机双线程读写缓存策略

前言

本文讲解对海康相机的双线程读写缓存的策略,首先这里的双线程指的是,线程1进行相机的图像的调用并写入缓存区,线程2进行缓存区的读取,可以理解为生产者和消费者的关系。
由于线程1读入相机图像是持续不断,每当有图像,会刷新缓存区域,倘若缓存区容量为1,可能会产生生产者进程不断刷新缓存区,而消费者不能第一时间读到的情况,考虑设置缓存区容量为2。


一、双线程

对于缓存区域的写入和读取操作是并发进行的,因此需要设置双线程,代码如下:

#include <thread>
void WriteBuffer();
void ReadBuffer();
int main()
{thread cameraThread, serverThread;cameraThread = thread(WriteBuffer);serverThread = thread(ReadBuffer);cameraThread.join();serverThread.join();return 0;
}

二、缓存区容量为2的生产消费思想

生产者消费者模型是CS的核心课程《操作系统》的重要模型,缓存区作为临界资源,当缓存区容量为1,同一时刻,只能允许一个生产者进行生产或者一个消费者进行消费,对于缓存区的写入和读取操作是互斥的。我们可以设置互斥信号mutex,确保对于使用临界资源的互斥性。

#include <mutex>
mutex mutexBufferA, mutexBufferB;

互斥信号mutex控制对于某一缓存区同一时间只能有一个线程进行读取或者写入操作。

mutexBufferA.lock();
wirteBufferA or readBufferA
mutexBufferA.unlock();

当缓存区满的时候,才能进行读取操作,当缓存区空的时候,才能进行写入操作,需要设置缓存区当前的状态量bufferFull,但状态量的修改与进程或线程的执行顺序相关。例如:若进程A设置bufferFull=false,此时进程B读取bufferFull状态,读入与bufferFull何时写入内存是有关联性的。
考虑设置bufferFull为原子变量atomic,atomic变量类型对于变量的操作是原子操作,可以理解为是一步完成,即读入写回一气呵成。

#include <atomic>
atomic_bool bufferAFull = false;
atomic_bool bufferBFull = false;

鉴于上述阐述,尝试模拟缓存区容量为2的读写策略。

#include <atomic>
#include <thread>
#include <mutex>
#include <windows.h>
using namespace std;
int bufferAData,bufferBData ;
mutex mutexBufferA, mutexBufferB;
atomic_bool bufferAFull = false;
atomic_bool bufferBFull = false;
void writeBuffer()
{while (true){if (bufferAFull == false){mutexBufferA.lock();bufferAData = 1;bufferAFull = true;mutexBufferA.unlock();}else{if (bufferBFull == false){mutexBufferB.lock();bufferBData = 2;bufferBFull = true;mutexBufferB.unlock();}else{bufferAFull == false;mutexBufferA.lock();bufferAData = 3;bufferAFull = true;mutexBufferA.unlock();}}}
}
void  readBuffer()
{while (true){if (bufferAFull == true){mutexBufferA.lock();cout<<bufferAData<<endl;bufferAFull = false;mutexBufferA.unlock();}else{if (bufferBFull == true){mutexBufferB.lock();cout<<bufferBData<<endl;bufferBFull = false;mutexBufferB.unlock();}else{Sleep(10);}}}return true;
}

主要阐述两点
(1)当bufferA与bufferB都是满的状态,写入进程会默认刷新bufferA,其实这是不对的,倘若某时间段读取进程较慢,写入进程会持续刷新bufferA,导致bufferB保持过去的数据,当读入bufferB的时候,会是很久远的数据;考虑设置bufferRefreshA标志位,每当写入bufferA,设置bufferRefreshA=false,每当写入bufferB,设置bufferRefreshA=false,因此当读入进程堵塞时,写入进程会循环刷新。
(2)当bufferA与bufferB都是空的状态,读入进程会等待10ms,这会造成无限等待的情况,可以考虑设置计时器countTime,当计时器等待1s后,会跳出循环。


三、相机双线程读写缓存策略

上一节简述了读写缓存策略的主要思想,在这一节,结合OpenCV的Mat矩阵与相机SDK,使用两个线程分别进行相机的取图与缓存区的读出。实例如下:

//define buffer region
cv::Mat srcImageA, srcImageB;
mutex mutexBufferA, mutexBufferB;
atomic_bool bufferAFull = false;
atomic_bool bufferBFull = false;
atomic_bool bufferRefreshA = false;
bool CameraGrabImage()
{nRet = MV_CC_GetImageBuffer(handle, &stImageInfo, 20000);if (nRet == MV_OK){}else{printf("No data[0x%x]\n", nRet);return false;}if (bufferAFull == false){mutexBufferA.lock();srcImageA = cv::Mat(stImageInfo.stFrameInfo.nHeight, stImageInfo.stFrameInfo.nWidth, CV_8UC1, stImageInfo.pBufAddr).clone();bufferRefreshA = false;bufferAFull = true;mutexBufferA.unlock();}else{if (bufferBFull == false){mutexBufferB.lock();srcImageB = cv::Mat(stImageInfo.stFrameInfo.nHeight, stImageInfo.stFrameInfo.nWidth, CV_8UC1, stImageInfo.pBufAddr).clone();bufferRefreshA = true;bufferBFull = true;mutexBufferB.unlock();}else{if (bufferRefreshA){bufferAFull == false;mutexBufferA.lock();srcImageA = cv::Mat(stImageInfo.stFrameInfo.nHeight, stImageInfo.stFrameInfo.nWidth, CV_8UC1, stImageInfo.pBufAddr).clone();bufferRefreshA = false;bufferAFull = true;mutexBufferA.unlock();}else{bufferBFull == false;mutexBufferB.lock();srcImageB = cv::Mat(stImageInfo.stFrameInfo.nHeight, stImageInfo.stFrameInfo.nWidth, CV_8UC1, stImageInfo.pBufAddr).clone();bufferRefreshA = true;bufferBFull = true;mutexBufferB.unlock();}}}nRet = MV_CC_FreeImageBuffer(handle, &stImageInfo);return true;}
bool  ReadBuffer(cv::Mat &srcImage)
{int waitTimeCount = 0;while (true){if (bufferAFull == true){mutexBufferA.lock();srcImage = srcImageA;bufferAFull = false;mutexBufferA.unlock();break;}else{if (bufferBFull == true){mutexBufferB.lock();srcImage = srcImageB;bufferBFull = false;mutexBufferB.unlock();break;}else{Sleep(10);waitTimeCount++;if (waitTimeCount == 100){printf("ReadBuffer Over Time, waiting........\n");return false;}}}}return true;
}

(1)MV_CC_GetImageBuffer从相机缓存取图。
(2)相机缓存节点获取图像后,首先转化为mat格式,并写入本地缓存区域。
(3)srcImageA与srcImageB是两个缓存区域,都是OpenCV的Mat格式。
(4)readBuffer会等待1s,读不到会报错。


海康工业相机SDK + OpenCV实例(5):相机双线程读写缓存策略相关推荐

  1. 海康工业相机SDK + OpenCV实例(4):相机参数设置详解

    海康工业相机SDK + OpenCV实例(4): 相机参数设置详解 文章目录 海康工业相机SDK + OpenCV实例(4): 相机参数设置详解 前言 一.相机参数基本接口 二.自动曝光时间调整亮度 ...

  2. 海康工业相机SDK + OpenCV实例(3):相机初始化Bug调试

    海康工业相机SDK + OpenCV实例(3): 相机初始化Bug调试 文章目录 海康工业相机SDK + OpenCV实例(3): 相机初始化Bug调试 前言 一.心跳时间设置 二.相机先关闭再打开 ...

  3. 海康工业相机SDK+OpenCV实例(2):RawDataFormatConvert详解

    海康工业相机SDK+OpenCV实例(2): RawDataFormatConvert详解 文章目录 海康工业相机SDK+OpenCV实例(2): RawDataFormatConvert详解 前言 ...

  4. 海康工业相机SDK+OpenCV实例(1):海康SDK和OPENCV的安装与编译

    海康工业相机SDK+OpenCV实例(1) 海康SDK和OPENCV的安装与编译 文章目录 海康工业相机SDK+OpenCV实例(1) 海康SDK和OPENCV的安装与编译 前言 一.海康SDK安装 ...

  5. (一)Qt+OpenCV调用海康工业相机SDK示例开发

    系列文章目录 提示:这里是该系列文章的所有文章的目录 第一章: (一)Qt+OpenCV调用海康工业相机SDK示例开发 第二章: (二)Qt多线程实现海康工业相机图像实时采集 文章目录 系列文章目录 ...

  6. python调用海康工业相机并用opencv显示(整体实现)

    python语言调用海康机器人(hikrobotics)工业相机 系列文章目录 第一章 python调用海康工业相机并用opencv显示(整体实现) 第二章 python 调用海康工业相机图像获取方式 ...

  7. Java_JDK19.0.2_Ubuntu18.04中配合海康工业相机SDK环境搭建

    Java_JDK19.0.2_Ubuntu18.04中配合海康工业相机SDK环境搭建 简介 1. JDK环境搭建 JDK下载 JDK环境安装 2. 工业相机环境SDK安装 简介 本文主要介绍在ubun ...

  8. 海康工业相机排雷笔记04-工业相机取图流程

    在刚开始使用工业相机时,大多数人(包括我)可能都会误认为工业相机二次开发中的取图过程就是把图像数据从相机内部的寄存器中拿到内存中,这也会对取图过程及耗时等方面产生很多误解,下面会简单叙述下我个人的理解 ...

  9. 海康工业相机SDK错误码常见场景解析

    在使用SDK二次开发过程中,接口的调用往往会遇到较多的错误,sdk错误码能够帮助我们快速分析错误原因,解决问题,针对常见的错误码,下面给出一下常见的问题原因,供大家分析 1.MV_OK 0x00000 ...

最新文章

  1. 共享思维导图leangoo,可以导入XMind文件了
  2. LVS:三种负载均衡方式比较+另三种负载均衡方式
  3. Centos7搭建SVN服务步骤说明
  4. python自带intertool模块找不到_Python itertools模块详解
  5. 使用console进行 性能测试 和 计算代码运行时间
  6. 大学心理学课本_2019年北京师范大学765真题分析
  7. Symbols andSymbol Tables
  8. 《简明python教程》沈洁元
  9. 立体合唱声效果器:Roland Cloud JUNO-60 Mac
  10. python批量发送邮件_EDM营销算法:python自动批量发邮件
  11. matlab 10为底指数,matlab指数函数
  12. 排序算法——选择排序
  13. mapstruct使用
  14. 光纤、光缆的基本知识(2)
  15. 前端vue-高德地图操作
  16. 关于Android import-module 和NDK_MODULE_PATH
  17. 软件构造期末复习知识点整理
  18. Go语言云原生与微服务(一)云原生架构
  19. starGAN复现及遇到问题
  20. Map小结(java)

热门文章

  1. bug汇总——golang遇到的小问题
  2. 基于C#(Visual Studio 2013)的AutoCAD2016二次开发(一)编程环境的搭建
  3. 与KMP算法的相爱相杀之-----深刻理解记忆KMP算法(祥解)
  4. Android:解决“无法解析符号R”问题
  5. Android编程实现长按Button按钮连续响应功能示例
  6. Bancor协议揭秘
  7. 易安卓打开Android系统中的解锁方式选择页面(锁屏方式选择)
  8. python token认证_理解JWT(JSON Web Token)认证及python实践
  9. pdf转换jpg转换器教程
  10. 群晖如何添加第三方源