环境说明:Ubuntu16.04
海康威视SDK包:MVS-2.1.0_x86_64_20201228.tar.gz

如若在Windows环境下配合Visual Studio使用请移至
海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(一)
海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(二)

记录自己的学习过程,方便以后查阅,若有错误或遗漏,欢迎大佬指正补充。

这里写目录标题

  • 1.准备
    • 1.1 相关资料
    • 1.2 Debug常备
    • 1.3 针对错误码的解析
      • MV_E_HANDLE 0x80000000 错误或无效的句柄
      • MV_E_SUPPORT 0x80000001 不支持的功能
      • MV_E_BUFOVER 0x80000002 缓存已满
      • MV_E_CALLORDER 0x80000003 函数调用顺序有误
      • MV_E_PARAMETER 0x80000004 错误的参数
      • MV_E_RESOURCE 0x80000006 资源申请失败
      • MV_E_NODATA 0x80000007 无数据
      • MV_E_NOENOUGH_BUF 0x8000000A 传入的内存空间不足
      • MV_E_UNKNOW 0x800000FF 未知的错误
      • MV_E_GC_GENERIC 0x80000100 通用错误
      • MV_E_GC_RANGE 0x80000102 值超出范围
      • MV_E_GC_ACCESS 0x80000106 节点访问条件有误
      • MV_E_GC_TIMEOUT 0x80000107 超时
      • MV_E_ACCESS_DENIED 0x80000203 设备无访问权限
      • MV_E_NETER 0x80000206 网络相关错误
      • MV_E_IP_CONFLICT 0x80000221 设备IP冲突
      • MV_E_USB_READ 0x80000300 读USB出错
      • MV_E_USB_WRITE 0x80000301 写USB出错
      • MV_E_USB_DRIVER 0x80000305 驱动不匹配或者未装驱动
  • 2.通过海康相机SDK熟悉C接口取图流程和取图方式
    • 2.1 设备连接接口流程
    • 2.2 相机取图——主动取流
    • 2.3 设置相机的一些参数
  • 3.将相机抓取到的图像转为Mat格式,方便后续使用
  • 4.将Mat格式图像转为QImage格式,用于UI界面上控件的显示

1.准备

  首先是安装海康威视的MVS软件,VMware虚拟机中Ubuntu16.04系统下通过MVS运行海康威视工业相机。

1.1 相关资料

  • 工业相机SDK(C)开发指南
    这是最重要的资料,里面有(环境配置:SDK编程环境配置,包括网络配置、驱动安装等)、(编程导引:相机连接流程和取图方式介绍)、相机的常用节点等等。

  • 相机的常用节点查询
    这部分主要是用于SDK提供API接口中的参数设置,如设置曝光模式、曝光值、增益模式、增益值、外触发等等。

    根据我实际开发过程中常用的相机节点值如下:
  • CameraParams.h:包含编程需要的所有结构体、宏定义和枚举量
  • MvCameraControl.h:包含所有控制相机的API接口
  • 相关示例程序

1.2 Debug常备

  如果遇到问题,比如相机未正常打开、相机无法取图等等,及时打印每次调用SDK接口返回的输出值,对照错误码定义去排查问题(记得将输出值转化为十六进制)事半功倍。

  如果函数正常完成而没有检测到任何错误,则返回值为MV_OK,否则返回错误码 。

1.3 针对错误码的解析

  调试时如果遇到常见的错误码,如0x80000000——错误或无效的句柄,很自然的我们就会去排查是不是对于句柄的操作有误,好歹给了我们一些方向,但有些错误码如0x80000006——资源申请失败或者通用错误这些,仅凭类型信息描述根本无法提供方向去排查,这里列出我网上找到的和我实际遇到的及其解决方法供大家参考。
参考:https://zhuanlan.zhihu.com/p/437976222

MV_E_HANDLE 0x80000000 错误或无效的句柄

解析:-2147483648/0x80000000 无效句柄。
常见问题如下
用户没有申请句柄,直接调用接口,新手常犯的错误,要引导去学习我们接口使用流程。
用户创建了句柄,但是其他地方销毁了句柄,用户没有注意到,需要仔细排查代码。

MV_E_SUPPORT 0x80000001 不支持的功能

解析:-2147483647/0x80000001
SDK接口的bayer空域降噪、无损压缩、色彩矫正等ISP功能,需要配合CS-Pro系列相机支持。
格式转化时,不同格式的相互转化,超出了算法能力集,详情请仔细查阅SDK接口说明。

MV_E_BUFOVER 0x80000002 缓存已满

解析:-2147483646/0x80000002
常见于gige驱动启动时报错,低版本SDK在某些网卡上面易发,驱动启动失败后,走socket协议发送接收相机数据,效率低,CPU负载大 推荐使用SDK3.5版本解决此问题。

MV_E_CALLORDER 0x80000003 函数调用顺序有误

解析:-2147483645/0x80000003
sdk接口调用,有一定流程顺序,例如getimagebuffer在startgrabing之前调用,就违反了接口流程,就会报错顺序调用错误 还比如,没有调用startgrabing接口,就去调用频繁调用stopgrabing接口,也会报此错误。

MV_E_PARAMETER 0x80000004 错误的参数

解析:-2147483644/0x80000004
常见问题: 常见于格式转化、图像保存等需要补充数据结构的接口调用,部分参数传入错误,或者没有传入,这个时候,要去仔细检查参数的传入是否正确。

MV_E_RESOURCE 0x80000006 资源申请失败

解析:-2147483654/0x80000004
这个问题我在另一台设备上部署相机服务端时,枚举相机第一步就报了这个错误,最后是安装了MVS后才得以解决,推测是缺了什么依赖库,但ldd的时候并未显示缺失的库。

2022-9-14记录:今天又遇到了这个问题,原来是缺了libMVGigEVisionSDK.so.3.1.3.0libMVGigEVisionSDK.so这两个库。猜测海康这里是dlopen的这两个库,巨坑!!!通过ldd根本看不出什么错误。

MV_E_NODATA 0x80000007 无数据

解析:-2147483641/0x80000007无数据
相机帧率低,用户调用主动取流接口getimagebuffer/getoneframetimout频率高于相机出图频率,且超时时间短,没有拿到图片,此时应该打印相机帧号,如帧号连续则为正常现象。
相机处于触发模式,没有触发信号给到相机,此时,应该排查用户是否给了软触发或者硬触发信号。
相机停流,此时,建议打开MVS,观察相机状态。
耐心寻找规律,看看是否跟packsize、scpd、取流超时时间不合理所致。

MV_E_NOENOUGH_BUF 0x8000000A 传入的内存空间不足

解析:-2147483638/0x8000000A
1.用户自行开辟的内存大小,小于当前相机图像所需要的图像大小,例如用mono8的图像大小,接收RGB的图像。
2.用户定义的内存大小,中途更换了分辨率更高的相机,导致所需内存较多
3.相机开启了chunk功能,用户开辟缓存大小,仅考虑了图像宽像素格式,没有考虑到chunk。
解决方法:
排查内存开辟大小,建议使用相机payloadsize大小
检查相机图像格式
关闭相机chunk等功能

MV_E_UNKNOW 0x800000FF 未知的错误

解析:-2147483137/0x800000FF GenICam未知错误
未知错误,形成原因较难分析,建议如下:
更新最新版本的sdk
开启sdk日志等级,通过日志分析形成原因

MV_E_GC_GENERIC 0x80000100 通用错误

解析:-2147483392/0x80000100
通用接口调用,关键词写错,例如曝光:ExposureTime,拼写错误就会报错。
第三方相机链接,例如迈德威视相机链接MVS,也会报通用错误,这是因为迈德威视不是标准的genicam协议的相机导致的。
接口类型用错,例如曝光时float型节点,我们使用了一个int型的节点接口进行读写,访问,那么也会报通用错误。

MV_E_GC_RANGE 0x80000102 值超出范围

解析:-2147483390/0x80000102
接口传入的参数值,超出相机接受范围,例如,曝光存在上下限,图像宽高存在步进,没有按照步进进行设置等等。

MV_E_GC_ACCESS 0x80000106 节点访问条件有误

解析:-2147483386/0x80000106
常见的问题类型有: 相机节点不存在或者无法访问,例如,自动曝光,在手动曝光情况下,自动曝光节点会被隐藏,或者其他相机存在这个参数,而使用的相机无此参数,例如线扫相机的行频参数等等,还比如说部分相机无此功能,例如event参数,部分相机固件暂不支持用户调用。

MV_E_GC_TIMEOUT 0x80000107 超时

解析:-2147483385/0x80000107
GVCP命名包回复超时,一般出现在网络环境不好的情况下,此时应该调用接口加大gvcp命令包等待时间(MV_GIGE_GetGvcpTimeout()),持续出现该报错,应该排查网络环境问题。

MV_E_ACCESS_DENIED 0x80000203 设备无访问权限

解析:-2147483133/0x80000203常见问题有:
相机被其他软件打开占用,关闭其他软件,检查设备管理器中,可能存在的残留进程。
代码debug下,心跳时间问题,等待60s后,可以重新打开(此问题参考心跳问题解决方法,可缩短打开时间)。
其余问题,例如一上电就打不开相机,需要重新插拔网线、USB线,就是其他问题,需要具体问题,具体分析。

MV_E_NETER 0x80000206 网络相关错误

解析:-2147483130/0x80000206
此类报错非常常见,主要分以下集中:
相机掉线,能够在日志中发现大量的206报错,此时需要去区分掉线原因,结合相机上电时间、心跳时间、相机权限,日志等信息,综合判断。
网线异常,导致相机掉线,也需要具体问题分析。

MV_E_IP_CONFLICT 0x80000221 设备IP冲突

解析:-2147483103/0x80000221
常见于IP设置时,当前ip已经被其他设备使用,需要更换ip重新设置。

MV_E_USB_READ 0x80000300 读USB出错

解析:-2147482880/0x80000300
USB读取相机信息失败,此类问题较为复制,与USB接口稳定性、线缆长度、电磁环境相关,往往不好分析,可以尝试插拔一下,或者更换USB接口尝试。

MV_E_USB_WRITE 0x80000301 写USB出错

解析:-2147482879/0x80000301
同0x80000300一样,不好分析,可以尝试插拔一下,或者更换USB接口尝试。

MV_E_USB_DRIVER 0x80000305 驱动不匹配或者未装驱动

解析: -2147482875/0x80000305
同0x80000300一样,问题复杂,除了更换USB接口外,还可以尝试更换sdk版本。

2.通过海康相机SDK熟悉C接口取图流程和取图方式

个人总结:句柄(void *handle)是相机开发中重要的一环,SDK中的接口中,大部分都是针对句柄的操作,如果有多个相机,要将每个相机和其对应的句柄关联好,防止后期使用的过程中未及时释放句柄、造成混乱等。

2.1 设备连接接口流程

  对设备进行操作,实现图像采集、参数配置等功能,需要先连接设备(打开设备),具体流程如下图所示:

  1.调用 MV_CC_EnumDevices() 枚举子网内指定传输协议对应的所有设备。可以通过 pstDevList 在结构 MV_CC_DEVICE_INFO_LIST 中找到设备的信息。

#include "MvCameraControl.h"void main()
{unsigned int nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE;MV_CC_DEVICE_INFO_LIST m_stDevList = {0};int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList);if (MV_OK != nRet){printf("error: EnumDevices fail [%x]\n", nRet);}
}

  关于搜索到的所有相机设备信息在 MV_CC_DEVICE_INFO_LIST结构体中,

/// \~chinese 设备信息列表    \~english Device Information List
typedef struct _MV_CC_DEVICE_INFO_LIST_
{unsigned int        nDeviceNum;                         ///< [OUT] \~chinese 在线设备数量       \~english Online Device NumberMV_CC_DEVICE_INFO*  pDeviceInfo[MV_MAX_DEVICE_NUM];     ///< [OUT] \~chinese 支持最多256个设备  \~english Support up to 256 devices}MV_CC_DEVICE_INFO_LIST;

  通过MV_CC_DEVICE_INFO结构体可以访问每个设备的详细信息,

/// \~chinese 设备信息    \~english Device info
typedef struct _MV_CC_DEVICE_INFO_
{unsigned short      nMajorVer;                  ///< [OUT] \~chinese 主要版本                                 \~english Major Versionunsigned short      nMinorVer;                  ///< [OUT] \~chinese 次要版本                                 \~english Minor Versionunsigned int        nMacAddrHigh;               ///< [OUT] \~chinese 高MAC地址                                \~english High MAC Addressunsigned int        nMacAddrLow;                ///< [OUT] \~chinese 低MAC地址                                \~english Low MAC Addressunsigned int        nTLayerType;                ///< [OUT] \~chinese 设备传输层协议类型,e.g. MV_GIGE_DEVICE  \~english Device Transport Layer Protocol Type, e.g. MV_GIGE_DEVICEunsigned int        nReserved[4];               ///<       \~chinese 预留                                     \~english Reservedunion{MV_GIGE_DEVICE_INFO stGigEInfo;             ///< [OUT] \~chinese GigE设备信息                             \~english GigE Device InfoMV_USB3_DEVICE_INFO stUsb3VInfo;            ///< [OUT] \~chinese USB设备信息                              \~english USB Device InfoMV_CamL_DEV_INFO    stCamLInfo;             ///< [OUT] \~chinese CameraLink设备信息                          \~english CameraLink Device Info// more ...}SpecialInfo;}MV_CC_DEVICE_INFO;

  这里以我使用的网口相机GigE设备为例,要获取到设备的详细内容:

// 我通过std::map<std::string, std::tuple<void*,MV_CC_DEVICE_INFO*>>m_dev_info_list_;来存储枚举到的所示设备。
// 第一个参数的设备的名称,这个可以自己定义,方便后面对哪一个相机进行操作;
// 第二个参数是句柄
// 第三个参数就是MV_CC_DEVICE_INFO设备信息的结构体
MV_CC_DEVICE_INFO* pstMVDevInfo = std::get<1>(m_dev_info_list_[dev_name]);if (pstMVDevInfo->nTLayerType == MV_GIGE_DEVICE) {std::string model =(char*)pstMVDevInfo->SpecialInfo.stGigEInfo.chModelName;std::string cam_ip = "Current IP Address: " ;int nIp1 =((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >>24);int nIp2 =((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >>16);int nIp3 =((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >>8);int nIp4 =(pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);}

  有些参数我也没搞懂是什么信息。。。

  2.在打开指定设备之前,调用 MV_CC_IsDeviceAccessible() 检查指定设备是否可访问。 (这一步在实际使用中并未用到)

  3.调用 MV_CC_CreateHandle() 以创建设备句柄。

#include "MvCameraControl.h"void main()
{int nRet = -1;void*  m_handle = NULL;//枚举子网内指定的传输协议对应的所有设备unsigned int nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE;MV_CC_DEVICE_INFO_LIST m_stDevList = {0};int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList);if (MV_OK != nRet){printf("error: EnumDevices fail [%x]\n", nRet);return;}int i = 0;if (m_stDevList.nDeviceNum == 0){printf("no camera found!\n");return;}//选择查找到的第一台在线设备,创建设备句柄int nDeviceIndex = 0;MV_CC_DEVICE_INFO m_stDevInfo = {0};memcpy(&m_stDevInfo, m_stDevList.pDeviceInfo[nDeviceIndex], sizeof(MV_CC_DEVICE_INFO));nRet = MV_CC_CreateHandle(&m_handle, &m_stDevInfo);if (MV_OK != nRet){printf("error: CreateHandle fail [%x]\n", nRet);return;}//...其他处理//销毁句柄,释放资源nRet = MV_CC_DestroyHandle(m_handle);if (MV_OK != nRet){printf("error: DestroyHandle fail [%x]\n", nRet);return;}
}

  4.调用 MV_CC_OpenDevice() 打开设备。

  去该API定义后发现,后面两个参数有默认值,所以实际使用中只需要输入第一个参数设备的句柄即可。

/********************************************************************//***  @~chinese*  @brief  打开设备*  @param  handle                      [IN]            设备句柄*  @param  nAccessMode                 [IN]            访问权限*  @param  nSwitchoverKey              [IN]            切换访问权限时的密钥*  @return 成功,返回MV_OK;错误,返回错误码 *  @remarks 根据设置的设备参数,找到对应的设备,连接设备。\n 调用接口时可不传入nAccessMode和nSwitchoverKey,此时默认设备访问模式为独占权限。目前设备暂不支持MV_ACCESS_ExclusiveWithSwitch、MV_ACCESS_ControlWithSwitch、MV_ACCESS_ControlSwitchEnable、MV_ACCESS_ControlSwitchEnableWithKey这四种抢占模式。\n 对于U3V设备,nAccessMode、nSwitchoverKey这两个参数无效。  */
#ifndef __cplusplus
MV_CAMCTRL_API int __stdcall MV_CC_OpenDevice(IN void* handle, IN unsigned int nAccessMode, IN unsigned short nSwitchoverKey);
#else
MV_CAMCTRL_API int __stdcall MV_CC_OpenDevice(IN void* handle, IN unsigned int nAccessMode = MV_ACCESS_Exclusive, IN unsigned short nSwitchoverKey = 0);
#endif
int nRet = MV_CC_OpenDevice(m_handle);

  5.调用 MV_CC_CloseDevice() 关闭设备。

  6.调用 MV_CC_DestroyHandle() 来销毁句柄并释放资源。

2.2 相机取图——主动取流

  SDK提供主动获取图像的接口,用户可以在开启取流后直接调用此接口获取图像,也可以使用异步方式(线程、定时器等)获取图像。示例代码详见 GrabImage.cpp 和 GrabImage_HighPerformance.cpp 。

  • 主动获取图像有两种方式(两种方式不能同时使用)
    方式一:调用 MV_CC_StartGrabbing() 开始采集,需要自己开启一个buffer,然后在应用层循环调用 MV_CC_GetOneFrameTimeout() 获取指定像素格式的帧数据,获取帧数据时上层应用程序需要根据帧率控制好调用该接口的频率。
    方式二:调用 MV_CC_StartGrabbing() 开始采集,然后在应用层调用 MV_CC_GetImageBuffer() 获取指定像素格式的帧数据,然后调用 MV_CC_FreeImageBuffer() 释放buffer,获取帧数据时上层应用程序需要根据帧率控制好调用该接口的频率。
  • 主动取图方式使用的场景
    主动取图方式需要先调用 MV_CC_StartGrabbing() 启动图像采集。上层应用程序需要根据帧率,控制好调用主动取图接口的频率。两种主动取图方式都支持设置超时时间,SDK内部等待直到有数据时返回,可以增加取流平稳性,适合用于对平稳性要求较高的场合。
  • 两种主动取图方式的区别
    a、 MV_CC_GetImageBuffer() 需要与 MV_CC_FreeImageBuffer() 配套使用,当处理完取到的数据后,需要用 MV_CC_FreeImageBuffer() 接口将pstFrame内的数据指针权限进行释放。
    b、 MV_CC_GetImageBuffer()MV_CC_GetOneFrameTimeout() 相比,有着更高的效率。且其取流缓存的分配是由sdk内部自动分配的,而 MV_CC_GetOneFrameTimeout() 接口是需要客户自行分配。

这里我使用方式一的取图流程。

  1.开始取流。

  2.停止取流。

  3.方式一的取图方式,采用超时机制获取一帧图片,SDK内部等待直到有数据时返回。

所获取的帧属于裸数据,数据保存在pData,并无图像格式(具体数据格式可以提前设定)。pFrameInfo表示输出帧的信息。

  可以通过函数MV_CC_Display(IN void* handle, IN void* hWnd)来实时显示采集到的图像。该函数需要在MV_CC_StartGrabbing之后调用,显示采集到的图像。如果相机当前采集图像是JPEG压缩的格式,则不支持调用该函数接口进行显示。

  可以通过函数MV_CC_SaveImage(IN&OUT MV_SAVE_IMAGE_PARAM* pSaveParam)将原始图像数据转换成图片格式并保存在指定内存里,再通过函数fwrite写入文件中。
  也可以通过函数MV_CC_SaveImageEx将原始图像数据转换成图片格式并保存在指定内存中,可支持设置JPEG编码质量。

  可通过函数memcpy(OUT void* dst, IN void const* src, IN size_t size) 把资源内存(src所指向的内存区域)拷贝到目标内存(dest所指向的内存区域),从而将unsigned char格式的图像数据转换为QImage格式的图像数据,这里要注意输入数据的格式,代码中输入的unsigned char pFrameBuf数据格式分别为Mono8的灰度图像和RGB8_Packed的彩色图像。

#include "MvCameraControl.h"void main()
{int nRet = -1;void* m_handle = NULL;//枚举子网内指定的传输协议对应的所有设备unsigned int nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE;MV_CC_DEVICE_INFO_LIST m_stDevList = {0};int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList);if (MV_OK != nRet){printf("error: EnumDevices fail [%x]\n", nRet);return;}int i = 0;if (m_stDevList.nDeviceNum == 0){printf("no camera found!\n");return;}//选择查找到的第一台在线设备,创建设备句柄int nDeviceIndex = 0;MV_CC_DEVICE_INFO m_stDevInfo = {0};memcpy(&m_stDevInfo, m_stDevList.pDeviceInfo[nDeviceIndex], sizeof(MV_CC_DEVICE_INFO));nRet = MV_CC_CreateHandle(&m_handle, &m_stDevInfo);if (MV_OK != nRet){printf("error: CreateHandle fail [%x]\n", nRet);return;}//连接设备nRet = MV_CC_OpenDevice(m_handle, nAccessMode, nSwitchoverKey);if (MV_OK != nRet){printf("error: OpenDevice fail [%x]\n", nRet);return;}//...其他处理 //开始采集图像nRet = MV_CC_StartGrabbing(m_handle);if (MV_OK != nRet){printf("error: StartGrabbing fail [%x]\n", nRet);return;}//获取一帧数据的大小MVCC_INTVALUE stIntvalue = {0};nRet = MV_CC_GetIntValue(m_handle, "PayloadSize", &stIntvalue);if (nRet != MV_OK){printf("Get PayloadSize failed! nRet [%x]\n", nRet);return;}int nBufSize = stIntvalue.nCurValue; //一帧数据大小unsigned int    nTestFrameSize = 0;unsigned char*  pFrameBuf = NULL;pFrameBuf = (unsigned char*)malloc(nBufSize);MV_FRAME_OUT_INFO_EX stInfo;memset(&stInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX));//上层应用程序需要根据帧率,控制好调用该接口的频率//此次代码仅供参考,实际应用建议另建线程进行图像帧采集和处理while(1){if (nTestFrameSize > 99) {break;}nRet = MV_CC_GetOneFrameTimeout(m_handle, pFrameBuf, nBufSize, &stInfo, 1000);if (MV_OK != nRet){Sleep(10);}else{//...图像数据处理nTestFrameSize++;}}//...其他处理//停止采集图像 nRet = MV_CC_StopGrabbing(m_handle);if (MV_OK != nRet){printf("error: StopGrabbing fail [%x]\n", nRet);return;}//关闭设备,释放资源nRet = MV_CC_CloseDevice(m_handle);if (MV_OK != nRet){printf("error: CloseDevice fail [%x]\n", nRet);return;}//销毁句柄,释放资源nRet = MV_CC_DestroyHandle(m_handle);if (MV_OK != nRet){printf("error: DestroyHandle fail [%x]\n", nRet);return;}
}

SDK还提供了回调出流的方法,这里我没研究,如果大佬采用的这种方式,也可以一起交流,方便我学习。

2.3 设置相机的一些参数

/********************************************************************//***  @~chinese*  @brief  设置Enum型属性值*  @param  handle                      [IN]            设备句柄*  @param  strKey                      [IN]            属性键值,如获取像素格式信息则为"PixelFormat"*  @param  nValue                      [IN]            想要设置的设备的属性值*  @return 成功,返回MV_OK,失败,返回错误码*  @remarks 连接设备之后调用该接口可以设置Enum类型的指定节点的值。strKey取值可以参考XML节点参数类型列表,表格里面数据类型为“IEnumeration”的节点值都可以通过该接口设置,strKey参数取值对应列表里面的“名称”一列。
************************************************************************/
MV_CAMCTRL_API int __stdcall MV_CC_SetEnumValue(IN void* handle,IN const char* strKey,IN unsigned int nValue);/********************************************************************//***  @~chinese*  @brief  设置float型属性值*  @param  handle                      [IN]            设备句柄*  @param  strKey                      [IN]            属性键值*  @param  fValue                      [IN]            想要设置的设备的属性值*  @return 成功,返回MV_OK,失败,返回错误码*  @remarks 连接设备之后调用该接口可以设置float类型的指定节点的值。strKey取值可以参考XML节点参数类型列表,表格里面数据类型为“IFloat”的节点值都可以通过该接口设置,strKey参数取值对应列表里面的“名称”一列。 ************************************************************************/
MV_CAMCTRL_API int __stdcall MV_CC_SetFloatValue(IN void* handle,IN const char* strKey,IN float fValue);

  关于输入参数参考相机中的节点。

int setCameraParametMode(const char* str_key, unsigned int val)
{// TriggerMode    0: Off  1: On// TriggerSource  0:Line0  1:Line1  7:Software// GainAuto       0: Off    1: Once   2: Continuousint temp_val = MV_CC_SetEnumValue(m_handle, str_key, val);if (temp_val != 0) {return -1;}else {return 0;}
}int setCameraParametValue(const char* str_type, float num_val)
{// ExposureTime// Gainint temp_value = MV_CC_SetFloatValue(m_handle, str_type, num_val);if (temp_value != 0) {return -1;}else {return 0;}
}

  使用:

camera_obj->setCameraParametMode("ExposureAuto", 0);
camera_obj->setCameraParametValue("ExposureTime", exposure_time);
camera_obj->setCameraParametMode("GainAuto", 0);
camera_obj->setCameraParametValue("Gain", gain);

3.将相机抓取到的图像转为Mat格式,方便后续使用

/*************************************************************************  @fn     MV_CAMCTRL_API int __stdcall MV_CC_GetIntValue(IN void* handle,IN const char* strKey,OUT MVCC_INTVALUE *pIntValue);*  @brief  获取Integer属性值(建议改用MV_CC_GetIntValueEx接口)*  @param  void* handle                [IN]        相机句柄*  @param  char* strKey                [IN]        属性键值,如获取宽度信息则为"Width"*  @param  MVCC_INTVALUE* pstValue     [IN][OUT]   返回给调用者有关相机属性结构体指针*  @return 成功,返回MV_OK,失败,返回错误码
************************************************************************/
MV_CAMCTRL_API int __stdcall MV_CC_GetIntValue(IN void* handle,IN const char* strKey,OUT MVCC_INTVALUE *pIntValue);
  • 相机采集到的图像格式是buffer,需要将其转化为Mat类型。
int HikCamera::CameraOneFrameImageToMat(void* dev_handle,const std::string& dev_name, cv::Mat& image)
{cv::Mat* getImage = new cv::Mat();unsigned int nRecvBufSize = 0;MVCC_INTVALUE stParam;memset(&stParam, 0, sizeof(MVCC_INTVALUE));int tempValue = MV_CC_GetIntValue(dev_handle, "PayloadSize", &stParam);if (tempValue != 0) {return -1;}nRecvBufSize = stParam.nCurValue;unsigned char* pDate;pDate = (unsigned char*)malloc(nRecvBufSize);MV_FRAME_OUT_INFO_EX stImageInfo = { 0 };tempValue = MV_CC_GetOneFrameTimeout(dev_handle, pDate, nRecvBufSize,&stImageInfo, 500);if (tempValue != 0) {return -1;}m_nBufSizeForSaveImage_ =stImageInfo.nWidth * stImageInfo.nHeight * 3 + 2048;unsigned char* m_pBufForSaveImage;m_pBufForSaveImage = (unsigned char*)malloc(m_nBufSizeForSaveImage_);bool isMono; //判断是否为黑白图像switch (stImageInfo.enPixelType) {case PixelType_Gvsp_Mono8:case PixelType_Gvsp_Mono10:case PixelType_Gvsp_Mono10_Packed:case PixelType_Gvsp_Mono12:case PixelType_Gvsp_Mono12_Packed:isMono = true;break;default:isMono = false;break;}if (isMono) {*getImage =cv::Mat(stImageInfo.nHeight, stImageInfo.nWidth, CV_8UC1, pDate);}else {// 转换图像格式为BGR8MV_CC_PIXEL_CONVERT_PARAM stConvertParam = { 0 };memset(&stConvertParam, 0, sizeof(MV_CC_PIXEL_CONVERT_PARAM));stConvertParam.nWidth = stImageInfo.nWidth;stConvertParam.nHeight = stImageInfo.nHeight;stConvertParam.pSrcData = pDate;stConvertParam.nSrcDataLen = stImageInfo.nFrameLen; // 输入数据大小stConvertParam.enSrcPixelType = stImageInfo.enPixelType; // 输入像素格式stConvertParam.enDstPixelType = PixelType_Gvsp_BGR8_Packed; // 输出像素格式stConvertParam.pDstBuffer = m_pBufForSaveImage; // 输出数据缓存stConvertParam.nDstBufferSize = m_nBufSizeForSaveImage_; // 输出缓存大小MV_CC_ConvertPixelType(dev_handle, &stConvertParam);*getImage = cv::Mat(stImageInfo.nHeight, stImageInfo.nWidth, CV_8UC3, m_pBufForSaveImage);}(*getImage).copyTo(image);(*getImage).release();free(pDate);free(m_pBufForSaveImage);return 0;
}

4.将Mat格式图像转为QImage格式,用于UI界面上控件的显示

  转化为Mat后,通过display_myImage_L再将Mat转化为QImage类型,进行在控件上显示。软触发的话,就是采集到当前帧图像,通过display_myImage_L显示,连续采集的话,通过多线程,将线程对象myThread_camera_L_show发送信号display给主线程,主线程调用display_myImage_L将相机采集到的图像进行显示。

void display_myImage_L(const cv::Mat* image_ptr)
{cv::Mat rgb;// cv::cvtColor(*imagePrt, rgb, CV_BGR2RGB);//判断是黑白、彩色图像QImage QmyImage_L;if (lbl_camera_L_image->channels() > 1) {cv::cvtColor(*image_ptr, rgb, CV_BGR2RGB);QmyImage_L = QImage((const unsigned char*)(rgb.data), rgb.cols,rgb.rows, QImage::Format_RGB888);}else {cv::cvtColor(*image_ptr, rgb, CV_GRAY2RGB);QmyImage_L = QImage((const unsigned char*)(rgb.data), rgb.cols,rgb.rows, QImage::Format_RGB888);}QmyImage_L = (QmyImage_L).scaled(ui.lbl_camera_L->size(), Qt::IgnoreAspectRatio,Qt::SmoothTransformation);ui.lbl_camera_L->setPixmap(QPixmap::fromImage(QmyImage_L));
}

参考博文:
https://cloud.tencent.com/developer/article/1730933
https://blog.csdn.net/weixin_46421489/article/details/116381368
关于相机SDK开发
https://cloud.tencent.com/developer/article/1730940

海康威视工业相机SDK的开发使用笔记相关推荐

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

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

  2. 海康威视工业相机SDK二次开发

    海康威视工业相机SDK二次开发 好气,第一次写文章,结果没不小心保存关掉,什么都没了. 本人是一名在读研究生,被导师分配了做项目中海康工业相机的二次开发.实现的需求是:实现八个相机同时打开视频,并且分 ...

  3. Linux环境中对海康威视工业相机SDK进行二次开发(QT+CMake+Opencv+海康SDK)

    关于在Windows环境中对海康威视工业相机SDK进行二次开发的话,可以参考这两篇博客. 海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(一) 海康威视工业相机SDK二 ...

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

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

  5. 【项目实践】海康威视工业相机SDK开发小白版入门教程(VS2015+OpenCV4.5.1)

    本文目录 前言 怎么查找资料? 数据手册 例程 项目开发 VS版本与OpenCV版本选择 VS配置OpenCV VS添加MVS安装目录下的头文件和库 VS项目开发 编程问题记录 相机数据如何转换为Op ...

  6. VS2015配置海康威视工业相机SDK二次开发

    1.概述: 工业相机SDK是用于控制相机的一个独立组件,支持获取实时图像数据.配置参数.对图像进行后续处理等功能.工业相机SDK兼容GigE Vision协议.USB3 Vision协议.Camera ...

  7. gige相机二次开发_海康威视工业相机SDK二次开发示例程序demo和PDF说明.zip

    1 海康威视相机demo和PDF说明\Samples\DirectShow\DirectShowDisplay\lib\x64\uuid.lib 4.73 MB 2018/12/29 10:59:06 ...

  8. 大恒相机开发(大恒SDK+opencv开发)笔记1

    大恒相机开发(大恒SDK+opencv开发 一.项目简介 在大三上学期做过人脸识别的开发,刚好下学期老师手中有相机的项目,然后项目就到了我手上,下面是我开发这个项目的一些经历,进程还在调试中.笔记会按 ...

  9. 海康威视工业相机SDK二次开发环境配置—Windows10+VS2017

    参考链接: https://blog.csdn.net/motikesi/article/details/108287951 一.SDK下载地址: https://www.hikrobotics.co ...

  10. python调用海康威视工业相机SDK实现图片采集

    海康工业相机 图像采集流程 环境设置 先安装MVS,下载地址 海康机器人官网. 条件:Python+海康官方的mvs文件下的development/samples下的python文件夹 注意:相机连接 ...

最新文章

  1. 通过事件同步两个窗体之间的数据
  2. 新手学JAVA(六)----处理随机性的数据
  3. QT造类器(操作简单)
  4. 蒙特卡洛模拟 matlab实例,蒙特卡洛模拟的简单例子
  5. android 不压缩保存图片格式,Android图片处理——压缩、剪裁、圆角、保存
  6. 【unity】解决3d max导出的fbx在unity贴图丢失的问题
  7. 求小于100的所有合数 python_python100例
  8. U盘复制东西时显示:磁盘被写保护,请去掉写保护或使用另一张磁盘的解决方法。
  9. 金融现金贷用户数据分析和用户画像(基于12万真实数据)
  10. ctc5(ctc5160)
  11. android 电视安装apk文件损坏,智能电视无法安装APK文件?原因都在这里!
  12. R语言之主成分分析和因子分析
  13. 计算机D盘无法读取,D盘目录或文件被损坏且无法读取的愿意以及解决办法
  14. 服务器异常消息微信通知
  15. 一份超详细的网站推广优化方案
  16. 基于SSH的羽毛球场地预定系统毕业设计-运动场地预定系统 源码 java-体育馆预定场地管理系统-场馆预约系统
  17. 数值计算方法第三章—线性方程组的数值解法知识点总结
  18. android addarc,Android绘图之Path总结
  19. 深入浅出MySQL JSON数据类型
  20. 真正意义上下一代 Windows Embedded:有关 Windows 10 Athens 的事

热门文章

  1. java 正则车牌_javascript匹配车牌号正则表达式
  2. html php即时通讯_PHP在线客服即时通讯源码
  3. Appium下载安装与配置
  4. 调用网易云api接口
  5. 软件开发需求分析内容
  6. 漏洞扫描工具AppScan下载网盘
  7. g4600黑苹果efi_授人以鱼不如授人以渔,黑苹果EFI相关问题分析方法以及解决思路...
  8. 推荐一个完全免费的高质量素材网站
  9. CorelDRAW X4 SP2 简体中文正式版精简增强版
  10. java-jsoup爬虫