使用大华相机SDK进行相机控制的一个例子,包括相机的打开、关闭、参数设置、图像抓取等功能。以下是对代码中关键函数和操作的详细解释:
类定义:aHuaCamera
这个类继承自Camera基类,并且添加了一些用于控制大华相机的特定成员和方法。关键成员变量包括:
• devHandle: 用于持有与相机设备的连接句柄。
• m_isOpen 和 m_isGrabbing: 分别用于指示相机是否已打开和是否正在抓取图像。
• m_data: 存储图像数据的对象。
• m_num: 用于表示队列中图像数据的数量。
构造函数与析构函数
• 构造函数(aHuaCamera):初始化相机,设备句柄和图像数据置为nullptr,状态变量初始化。
• 析构函数(~aHuaCamera):关闭相机,销毁设备句柄,清理图像数据。
相机操作
• openCamera():这个函数负责打开相机。首先枚举所有连接的设备,匹配设备序列号,并创建设备句柄。之后注册状态和数据回调函数,并设置缓存。
• closeCamera():关闭相机。停止图像抓取,并关闭设备句柄。
• startGrabbing() 和 stopGrabbing():开始和停止图像抓取。这两个函数根据相机的状态(是否已打开和是否正在抓取)进行操作。
参数设置
• setCameraParameters():设置相机的曝光时间、增益等参数。
回调函数
• ImageCallBack():这是一个静态函数,用于处理从相机接收到的图像数据。根据像素格式进行图像创建,并添加到图像数据缓存中。
• ExceptionCallBack():处理设备连接状态的变化,如断线通知。
实用函数
• setCameraQueneNumber():设置和获取图像数据队列的数量。
• sendErrorsMsgs(), sendInforMsgs(), sendWarningMsgs():用于发送错误、信息和警告消息。
• clearImageData():清理图像数据缓存。
#include "./inc/camera/ahuacamera/ahuacamera.h"
#include <QDateTime>
// 构造函数,初始化相机实例aHuaCamera::aHuaCamera(const int index, const QString &ip) : Camera(index, ip), m_isOpen(false), m_isGrabbing(false), m_num(0){ devHandle = nullptr; // 设备句柄初始化为空 m_data = nullptr; // 初始化图像数据指针为空}
// 析构函数,负责资源的释放和相机的关闭aHuaCamera::~aHuaCamera(){ closeCamera(); // 调用关闭相机函数 if (devHandle) IMV_DestroyHandle(devHandle); // 如果设备句柄存在,销毁设备句柄 clearImageData(); // 清除图像数据 if (m_data) delete m_data; // 删除图像数据对象 m_data = nullptr; // 将图像数据指针置为空}
// 设置图像数据队列的数量bool aHuaCamera::setCameraQueneNumber(const int num){ if (!m_data) m_data = new ImageData(); // 如果图像数据对象不存在,创建一个新的 m_data->setImageDataQueneNumber(num); // 设置图像数据队列数量 m_num = m_data->getImageDataQueneNumber(); // 获取设置后的队列数量 return true;}
// 打开相机的函数bool aHuaCamera::openCamera(OpenCameraWay){ int ret = IMV_OK; // 初始化返回值为OK m_isOpen = false; // 设置相机开启状态为false IMV_DeviceList deviceInfoList; ret = IMV_EnumDevices(&deviceInfoList, interfaceTypeAll); // 枚举所有设备
if (deviceInfoList.nDevNum < 1) // 如果没有找到任何设备 { setLastErrorMsg("C10: 当前设备上未连接任何设备,错误代码:%1").arg(ret, 0, 16)); getchar(); // 等待用户输入,暂停程序 return false; // 返回失败 }
unsigned int i = 0; // 在枚举的设备中查找序列号与给定IP地址匹配的相机 for (; i < deviceInfoList.nDevNum; ++i) { if (reinterpret_cast<char*>(deviceInfoList.pDevInfo[i].serialNumber) == getCameraIpAddress()) { break; // 如果找到匹配的序列号,跳出循环 } }
if (i >= deviceInfoList.nDevNum) // 如果没有找到匹配的相机 { setLastErrorMsg("C11: aHua相机#%1-未查找到SN: %2的相机").arg(getCameraIndex()).arg(getCameraIpAddress()); return false; // 返回失败 }
// 创建设备句柄 if (IMV_OK != (IMV_CreateHandle(&devHandle, modeByCameraKey, deviceInfoList.pDevInfo[i].cameraKey))) { setLastErrorMsg("C16: 相机# %1创建失败,错误码:%2").arg(getCameraIndex()).arg(ret)); return false; // 创建失败,返回false }
// 打开设备 if (IMV_OK != (ret = IMV_Open(devHandle))) { setLastErrorMsg("C16: 相机# %1打开失败,错误码:%2").arg(getCameraIndex()).arg(ret)); return false; // 打开失败,返回false }
// 注册设备连接状态事件回调函数 ret = IMV_SubscribeConnectArg(devHandle, ExceptionCallBack, devHandle); if (IMV_OK != ret) { setLastErrorMsg("C12: 相机#%1注册连接状态失败:%2").arg(getCameraIndex()).arg(ret)); return false; // 注册失败,返回false }
// 注册数据帧回调函数 ret = IMV_AttachGrabbing(devHandle, ImageCallBack, this); if (IMV_OK != ret) { setLastErrorMsg("C12: 相机#%1注册回调函数失败:%2").arg(getCameraIndex()).arg(ret)); return false; // 注册失败,返回false }
// 设置图像缓存节点 if(IMV_OK!=(ret=IMV_SetBufferCount(devHandle,getImageBufferNodeNum()))) { setLastErrorMsg("C17-1: 相机#%1设置图像缓存节点数量失败,错误码:%2").arg(getCameraIndex()).arg(ret)); return false; // 设置失败,返回false }
// 加载相机参数 if (IMV_OK != (ret = IMV_SetEnumFeatureValue(devHandle, "UserSetSelector", 1))) { setLastErrorMsg("C16: 相机# %1设置UserSet1失败,错误码:%2").arg(getCameraIndex()).arg(ret)); return false; // 设置失败,返回false }
// 成功设置所有参数后,设置打开状态为true并返回成功 return (m_isOpen = (IMV_OK == ret));}