最近在进行机器视觉系统的搭建,积累了经验,想和大家讨论、互相学习。相机是图像的来源。为了搭建视觉系统,完成图像分析、机器视觉任务,需要编程控制相机按工作所需的曝光、增益和帧率同步采集和存储图像。工业相机通常支持C/C++程序进行控制,提供了SDK(Software Development Kit)。这些SDK包括对相机进行基本控制的函数,利用这些函数,就可以控制相机参数(如曝光时间、增益、帧率、像素格式),满足视觉系统任务需求。

1.1相机选型

工业相机分为彩色工业(CCD芯片)相机和黑白工业相机(CMOS芯片)。芯片的三个关键参数是:靶面尺寸(感光芯片的尺寸)、分辨率(图像宽高)和像元大小。在同样的镜头焦距和同样的靶面尺寸下,分辨率越高,图像的物面分辨率就越高。相同的价格下黑白工业相机的分辨率更高、噪声更小图像处理更简单,适合用于视觉测量、工业视觉等任务场景;彩色相机能获取的信息则更为丰富,适用于人脸检测、物体识别等任务。

另外选择相机还需要注意其数据传输方式,一般有Gige和usb3.0两种。Gige数据传输更稳定,usb3.0传输速度更快。

1.2相机SDK

我参与的项目采用的是海康MV-023-10UM相机,相机分辨率230万,像元尺寸5.86um。首先下载海康SDK。https://www.hikrobotics.com/cn/machinevision/service/download?module=0。下载机器视觉工业相机客户端MVS。建议默认安装路径安装。安装好后打开下面的文件夹,这里就是海康相机的软件开发包了。

Includes文件夹下就是SDK的头文件,包括了用户可以使用的函数和变量的声明。Libraries文件夹下是静态链接库,内容应该是头文件里声明的函数的定义。Samples目录下就是二次开发示例。

我用的是VS2015,打开这个sample进行解读。因为在C盘下,所以需要给权限运行。如图选择使用不同的凭据重新启动此应用程序。

跑起来后可以看到一个的界面。可以打和初始化相机。

这是一个基于MFC框架的界面程序,需要了解的实际上只有三组文件(或者说三路文件)。一是MvCameraControl.h和MvErrorDefine.h和PixelType.h和CameraParams.h这几个文件就是前面的SDK的include里的头文件;二是MvCamera.h和MvCamera.cpp这是海康对SDK里的API和变量进行的二次封装,方便用户使用;三是BasicDemoDlg.h和BasicDemo.cpp,这是这个界面应用程序的主体。其他的则是一些资源文件和系统文件。因此,只要了解了海康二次开发的内容和界面程序的内容,就可以照猫画虎进行二次开发了。可以将这个demo划为3个层次

这里还需要借助海康给出的二次开发文档,这里面有相机工作的方式和流程,以及SDK里API的说明。

首先看MvCamera.h

/************************************************************************/
/* 以C++接口为基础,对常用函数进行二次封装,方便用户使用                */
/************************************************************************/class CMvCamera
{
public:CMvCamera();~CMvCamera();// ch:获取SDK版本号 | en:Get SDK Versionstatic int GetSDKVersion();// ch:枚举设备 | en:Enumerate Devicestatic int EnumDevices(unsigned int nTLayerType, MV_CC_DEVICE_INFO_LIST* pstDevList);// ch:判断设备是否可达 | en:Is the device accessiblestatic bool IsDeviceAccessible(MV_CC_DEVICE_INFO* pstDevInfo, unsigned int nAccessMode);// ch:打开设备 | en:Open Deviceint Open(MV_CC_DEVICE_INFO* pstDeviceInfo);// ch:关闭设备 | en:Close Deviceint Close();// ch:判断相机是否处于连接状态 | en:Is The Device Connectedbool IsDeviceConnected();/**********这里博主略了很多内容,细节大家可以看自己SDK里的文档****************/
/**********这里博主略了很多内容,细节大家可以看自己SDK里的文档****************/
/**********这里博主略了很多内容,细节大家可以看自己SDK里的文档****************/
/**********这里博主略了很多内容,细节大家可以看自己SDK里的文档****************/
/**********这里博主略了很多内容,细节大家可以看自己SDK里的文档****************/// ch:保存图片 | en:save imageint SaveImage(MV_SAVE_IMAGE_PARAM_EX* pstParam);// ch:保存图片为文件 | en:Save the image as a fileint SaveImageToFile(MV_SAVE_IMG_TO_FILE_PARAM* pstParam);
private:void*               m_hDevHandle;
};

可以看到,这个类里只有一个句柄和一系列和相机控制相关的函数。那么可以推测,相机(一个或许多个)可以通过实例化这个CMvCamera类的对象就可以对相机进行控制了。

再看BasicDemoDlg.h

class CBasicDemoDlg : public CDialog
{
// Construction
public:CBasicDemoDlg(CWnd* pParent = NULL);    // Standard constructor// Dialog Dataenum { IDD = IDD_BasicDemo_DIALOG };protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support// Implementation
protected:HICON m_hIcon;// Generated message map functionsvirtual BOOL OnInitDialog();afx_msg void OnSysCommand(UINT nID, LPARAM lParam);afx_msg void OnPaint();afx_msg HCURSOR OnQueryDragIcon();DECLARE_MESSAGE_MAP()/*ch:控件对应变量 | en:Control corresponding variable*/
private:BOOL                    m_bSoftWareTriggerCheck;double                  m_dExposureEdit;double                  m_dGainEdit;double                  m_dFrameRateEdit;   CComboBox               m_ctrlDeviceCombo;                // ch:枚举到的设备 | en:Enumerated deviceint                     m_nDeviceCombo;private:/*ch:最开始时的窗口初始化 | en:Window initialization*/void DisplayWindowInitial();void EnableControls(BOOL bIsCameraReady);void ShowErrorMsg(CString csMessage, int nErrorNum);int SetTriggerMode();                // ch:设置触发模式 | en:Set Trigger Modeint GetTriggerMode();int GetExposureTime();               // ch:设置曝光时间 | en:Set Exposure Timeint SetExposureTime(); int GetGain();                       // ch:设置增益 | en:Set Gainint SetGain();int GetFrameRate();                  // ch:设置帧率 | en:Set Frame Rateint SetFrameRate();int GetTriggerSource();              // ch:设置触发源 | en:Set Trigger Sourceint SetTriggerSource();int CloseDevice();                   // ch:关闭设备 | en:Close Deviceint SaveImage(MV_SAVE_IAMGE_TYPE enSaveImageType);                     // ch:保存图片 | en:Save Image// ch:去除自定义的像素格式 | en:Remove custom pixel formatsbool RemoveCustomPixelFormats(enum MvGvspPixelType enPixelFormat);private:BOOL                    m_bOpenDevice;                        // ch:是否打开设备 | en:Whether to open deviceBOOL                    m_bStartGrabbing;                     // ch:是否开始抓图 | en:Whether to start grabbingint                     m_nTriggerMode;                       // ch:触发模式 | en:Trigger Modeint                     m_nTriggerSource;                     // ch:触发源 | en:Trigger SourceCMvCamera*              m_pcMyCamera;               // ch:CMyCamera封装了常用接口 | en:CMyCamera packed commonly used interfaceHWND                    m_hwndDisplay;                        // ch:显示句柄 | en:Display HandleMV_CC_DEVICE_INFO_LIST  m_stDevList;         CRITICAL_SECTION        m_hSaveImageMux;unsigned char*          m_pSaveImageBuf;unsigned int            m_nSaveImageBufSize;MV_FRAME_OUT_INFO_EX    m_stImageInfo;void*                   m_hGrabThread;              // ch:取流线程句柄 | en:Grab thread handleBOOL                    m_bThreadState;public:/*ch:初始化 | en:Initialization*/afx_msg void OnBnClickedEnumButton();               // ch:查找设备 | en:Find Devicesafx_msg void OnBnClickedOpenButton();               // ch:打开设备 | en:Open Devicesafx_msg void OnBnClickedCloseButton();              // ch:关闭设备 | en:Close Devices/*ch:图像采集 | en:Image Acquisition*/afx_msg void OnBnClickedContinusModeRadio();        // ch:连续模式 | en:Continus Modeafx_msg void OnBnClickedTriggerModeRadio();         // ch:触发模式 | en:Trigger Modeafx_msg void OnBnClickedStartGrabbingButton();      // ch:开始采集 | en:Start Grabbingafx_msg void OnBnClickedStopGrabbingButton();       // ch:结束采集 | en:Stop Grabbingafx_msg void OnBnClickedSoftwareTriggerCheck();     // ch:软触发 | en:Software Triggerafx_msg void OnBnClickedSoftwareOnceButton();       // ch:软触发一次 | en:Software Trigger Execute Once/*ch:图像保存 | en:Image Save*/afx_msg void OnBnClickedSaveBmpButton();            // ch:保存bmp | en:Save bmpafx_msg void OnBnClickedSaveJpgButton();            // ch:保存jpg | en:Save jpgafx_msg void OnBnClickedSaveTiffButton();afx_msg void OnBnClickedSavePngButton();/*ch:参数设置获取 | en:Parameters Get and Set*/afx_msg void OnBnClickedGetParameterButton();       // ch:获取参数 | en:Get Parameterafx_msg void OnBnClickedSetParameterButton();       // ch:设置参数 | en:Exit from upper right cornerafx_msg void OnClose();virtual BOOL PreTranslateMessage(MSG* pMsg);int GrabThreadProcess();};

        这个文件里需要掌握的其实也只有三块:1.public函数:典型的是OnBnClicked开头的一系列函数。这些函数与界面上的按钮相对应,可以在资源文件里,点击按钮看到。比如开始采集,对应着OnBnClickedStartGrabbingButton函数。这类函数就是用户发出指令的。用户需要发出怎样指令,看到怎样的效果,这里就需要编写对应的函数。

 2.private函数:比如SetParams等等。这些是相机和程序交互的函数。

3.private变量:包括相机对象和相机参数。比如  CMvCamera*              m_pcMyCamera; 这就是要实例化的相机对象。

进一步将程序跑起来,连上相机,结合开发文档。可以了解到整个程序的流程应如下

1.3 相机预览多线程

整个程序中比较复杂的结构是相机图像的预览。直观地:就是相机不断取流的时候,显示器不断地展示相机拍摄到的图片。首先,程序肯定有循环,不断地取得相机数据。第二,程序需要保持与用户交互,不断显示图片,还能允许用户发送控制指令。第二点就是界面程序的本身任务,界面程序在一个线程里保持与用户交互;因此,还需要一个线程去不断获取相机的图像数据。

进行详细的代码解读(沿着打开预览的按钮的函数一直看下去):

在BasicDemoDlg.h声明了线程对象:

  void*                   m_hGrabThread;              // ch:取流线程句柄 | en:Grab threadhandle

在BasicDemoDlg.h声明了取流函数:

  int GrabThreadProcess();

观察其定义,确实是循环在取流:

int CBasicDemoDlg::GrabThreadProcess()
{MV_FRAME_OUT stImageInfo = {0};MV_DISPLAY_FRAME_INFO stDisplayInfo = {0};int nRet = MV_OK;while(m_bThreadState){nRet = m_pcMyCamera->GetImageBuffer(&stImageInfo, 1000);if (nRet == MV_OK){/*********/}else{if (MV_TRIGGER_MODE_ON ==  m_nTriggerMode){Sleep(5);}}}return MV_OK;
}

还需要一个函数,决定线程的启动:

unsigned int __stdcall GrabThread(void* pUser)
{if (pUser){CBasicDemoDlg* pCam = (CBasicDemoDlg*)pUser;pCam->GrabThreadProcess();return 0;}return -1;
}

观察上面函数GrabThread是如何被调用的:

  m_hGrabThread = (void*)_beginthreadex( NULL , 0 , GrabThread , this, 0 , &nThreadID );

注册回调函数的形式启动多线程。线程执行GrabThread,函数调用的是this,而this在线程里被同类的另一对象指向。也就是说,通过子线程里界面对象指针指向主线程的界面对象,从而实现子线程和主线程共同控制相机,完成不同的任务 。

        还需注意合适的位置加锁:

2.基于Qt双相机控制

采用Qt开发界面程序更加简单方便,因此这里用Qt进行双目相机控制界面程序开发。

IDE · GitCode

C/C++实战——基于Qt框架和visual studio的海康相机SDK二次开发相关推荐

  1. Visual Studio 2017 C# 对 AutoCad2014 的二次开发设置

    Visual Studio 2017 C# 对 AutoCad2014 的二次开发设置 开发平台:vs2017,win10,CAD2014 建立类库,引用文件 建立类库 从AutoCAD安装目录下添加 ...

  2. 海康视频监控二次开发基于B/S架构

    前言 最近做了一个音视频监控模块,是基于海康的视频平台进行的,今天将一些基本的使用分享给大家. 环境准备 由于调用视频监控需要安装一个插件WebComponentsKit.exe,链接: https: ...

  3. 海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(一)

    最近在做一个项目,涉及到工业相机,需要对其进行二次开发.相机方面选择了海康威视,网上关于海康威视工业相机SDK的开发资料很少,官方文档里面虽然写的是支持C++开发的,但其实是C.自己也摸索了一段时间, ...

  4. 嵌入式项目实战——基于QT的视频监控系统设计(一)

    嵌入式项目实战--基于QT的视频监控系统设计(一) 这个五一因为疫情,只能待在家里,想了想不如将我之前做的一个小的嵌入式的练习项目分享出来,供入门嵌入式的同学们学习.基于QT的视频监控系统设计虽然是个 ...

  5. 嵌入式项目实战——基于QT的视频监控系统设计(二)

    嵌入式项目实战--基于QT的视频监控系统设计(二) 昨天我分享了关于QT的基本使用方法,掌握了这些基本的方法就可以设计一个简单的视频监控界面.下面我们开始分享完成这个嵌入式项目同样重要的知识点--UD ...

  6. 嵌入式项目实战——基于QT的视频监控系统设计(三)

    嵌入式项目实战--基于QT的视频监控系统设计(三) 进入到五一假期第三天,继续我们的项目.本来五一假期还是想好好休息一下的,因为最近学习的状态不太好,刷题都没有思路了,但是身边的同学太卷了,不过我还是 ...

  7. 基于Qt框架实现的 C/S架构的外卖平台软件系统

    资源下载地址:https://download.csdn.net/download/sheziqiong/85628215 基于Qt框架实现的 C_S架构的外卖平台软件系统 演示视频 C/S 架构的外 ...

  8. 嵌入式项目实战——基于QT的视频监控系统设计(四)

    嵌入式项目实战--基于QT的视频监控系统设计(四) 进入到五一假期的第四天,通过前三天的分享,相信你应该已经掌握了QT的基本使用.UDP网络编程.v4l2视频处理模块.多线程编程等基本的知识点.其实昨 ...

  9. 基于 Qt 框架的开源笔记软件 VNote

    关注.星标公众号,直达精彩内容 来源:OSC开源社区 作者:tamlok VNote是一个受Vim启发开发的专门为Markdown而优化.设计的笔记软件. 授权协议:MIT 开发语言:C/C++ Ja ...

最新文章

  1. VS2015 win64下配置Opencv3.4.7
  2. 教你两种python selenium保存图片的方法
  3. Sql Server 2005如何设置连接加密
  4. c语言编程基础课件,第7章_C语言图形编程基础课件
  5. linux服务器查配置信息失败,查看Linux服务器的配置信息
  6. Redis详解(三)——Redis持久化
  7. 联想第三季:PC+时代的航母启航?
  8. android桌面部件开发教程,Android桌面小部件AppWidget开发
  9. Scientific Reports|比较转录组分析揭示了杀菌剂氰烯菌酯对尖孢镰刀菌的抗性调控机制和杀菌活性
  10. AppFuse 安装
  11. MBR 与 GPT - 分区时要知道的事情
  12. 基于javaEE的超市库存管理系统
  13. linux程序间管道通信,linux进程间通信——管道 详解
  14. 宝塔BT面板无法启动修复方法
  15. 三分钟了解http和https
  16. 大疆19年校招0804笔试A卷
  17. 为什么Facebook需要养号?Facebook养号系统有什么作用?
  18. 过分依赖计算机的影响,技术的“两面性”过于依赖技术,会给生活带来什么影响?...
  19. php实例一实验报告心得,实验报告个人心得体会【两篇】
  20. java序列化,从底层到序列化所隐藏的问题以及解决方案

热门文章

  1. L2-028 秀恩爱分得快 (25分) C++
  2. 在macOS开发中使用Touch Bar
  3. SpringMVC工作原理及源码解析
  4. [python][easygui]使用enterbox()方法,简体字会显示成繁体字了
  5. 【每日知识】进制转换:二进制、八进制、十六进制
  6. dbutils mysql,DbUtils操作数据库
  7. 怜惜,才是最真挚的爱情
  8. 循序渐进丨在openEuler 20.03操作系统上安装部署MogDB 2.1.1数据库
  9. xcode快速输入表情符号
  10. android camera噪点,android位图上的噪点效果