100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 海康威视工业相机SDK的开发使用笔记

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

时间:2021-06-09 10:20:09

相关推荐

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

环境说明:Ubuntu16.04

海康威视SDK包:MVS-2.1.0_x86_64_2028.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——资源申请失败或者通用错误这些,仅凭类型信息描述根本无法提供方向去排查,这里列出我网上找到的和我实际遇到的及其解决方法供大家参考。

参考:/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的时候并未显示缺失的库。

-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 Listtypedef 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 infotypedef struct _MV_CC_DEVICE_INFO_{unsigned shortnMajorVer; ///< [OUT] \~chinese 主要版本 \~english Major Versionunsigned shortnMinorVer; ///< [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 __cplusplusMV_CAMCTRL_API int __stdcall MV_CC_OpenDevice(IN void* handle, IN unsigned int nAccessMode, IN unsigned short nSwitchoverKey);#elseMV_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 charpFrameBuf数据格式分别为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格式,方便后续使用

/************************************************************************* @fnMV_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));}

参考博文:

/developer/article/1730933

/weixin_46421489/article/details/116381368

关于相机SDK开发

/developer/article/1730940

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。