海康SDK开发步骤
本文出处:https://www.cnblogs.com/xiawuhao2013/p/9295781.html
使用工业相机采集图像,首先需要对相机的相关参数进行设置。现在项目需要使用SDK进行二次开发。依照以下步骤进行:
1.枚举设备 -> 2.创建句柄 -> 3.打开设备 -> 4.开始抓图 -> 5.获取一帧并保存图像 -> 6.停止抓图 -> 7.关闭设备 -> 8.销毁句柄
第一次使用海康相机SDK,初步按照以下流程进行开发:
第一步: 了解C接口流程。
a.设备连接 b.图像采集显示
设备连接接口流程:
主动取流流程图
回调出流流程图
第二步:学习实例代码,查询C接口定义
1. 枚举设备
1 int MV_CC_EnumDevices(unsigned int nTLayerType, \
MV_CC_DEVICE_INFO_LIST *pstDevList);
参数:
nTLayerType [in] 传输层协议类型,按位表示,支持复选,可选协议类型如下:
pstDevList [out] 查找到的设备信息列表
返回值:
成功,返回MV_OK (0);失败,返回错误码。
1 #include "MvCameraControl.h" 2 3 void main() 4 { 5 unsigned int nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE; 6 7 MV_CC_DEVICE_INFO_LIST m_stDevList = {0}; 8 int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList); 9 if (MV_OK != nRet) 10 { 11 printf("error: EnumDevices fail [%x]\n", nRet); 12 } 13 }
2. 创建设备句柄
int MV_CC_CreateHandle(void **handle, const MV_CC_DEVIEC_INFO *pstDevInfo);
参数:
handle [out] 设备句柄,输出参数;
pstDevInfo [in] 设备信息版本、MAC地址、传输层类型以及其它设备信息;
返回值:
成功,返回MV_OK (0);失败,返回错误码。
1 #include "MvCameraControl.h" 2 3 void main() 4 { 5 int nRet = -1; 6 void* m_handle = NULL; 7 8 //枚举子网内指定的传输协议对应的所有设备 9 unsigned int nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE; 10 MV_CC_DEVICE_INFO_LIST m_stDevList = {0}; 11 int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList); 12 if (MV_OK != nRet) 13 { 14 printf("error: EnumDevices fail [%x]\n", nRet); 15 return; 16 } 17 18 int i = 0; 19 if (m_stDevList.nDeviceNum == 0) 20 { 21 printf("no camera found!\n"); 22 return; 23 } 24 25 //选择查找到的第一台在线设备,创建设备句柄 26 int nDeviceIndex = 0; 27 28 MV_CC_DEVICE_INFO m_stDevInfo = {0}; 29 memcpy(&m_stDevInfo, m_stDevList.pDeviceInfo[nDeviceIndex], sizeof(MV_CC_DEVICE_INFO)); 30 31 nRet = MV_CC_CreateHandle(&m_handle, &m_stDevInfo); 32 33 if (MV_OK != nRet) 34 { 35 printf("error: CreateHandle fail [%x]\n", nRet); 36 return; 37 } 38 39 //...其他处理 40 41 //销毁句柄,释放资源 42 nRet = MV_CC_DestroyHandle(m_handle); 43 if (MV_OK != nRet) 44 { 45 printf("error: DestroyHandle fail [%x]\n", nRet); 46 return; 47 } 48 }
3. 关闭设备
int MV_CC_CloseDevice(void *handle);
参数:
handle [in] 设备句柄,MV_CC_CreateHandle或MV_CC_CreateHandleWithoutLog的[out]参数。
4. 释放句柄
int MV_CC_DestroyHandle(void *handle);
5. 注册图像数据回调函数,支持获取chunk信息
int MV_CC_RegisterImageCallBackEx(void *handle, const char *pEventName, \
cbEvent cbEvent, void *pUser);
参数:
pEventName [in] 事件名;
fEventCallBack [in] 接收Event事件的回调函数
pUser [in] 用户自定义变量
回调函数
void(__stdcall *cbEvent)(MV_EVENT_OUT_INFO *pEventInfo, void *pUser);
回调函数参数:
pEventInfo [out] 外部输出Event Info;
pUser [out] 用户自定义变量;
注意:通过该接口设置事件回调,可以在回调函数里面获取采集、曝光等事件信息。
6. 开始采集图像
int MV_CC_StartGrabbing(void *handle);
7. 获取一帧图像数据
int MV_CC_GetOneFrame(void *handle, unsigned char *pData, \ unsigned int nDataSize, \
MV_FRAME_OUT_INFO *pFrameInfo
);
参数:
pData [in] 用于保存图像数据的缓存地址;
nDataSize [in] 缓存区大小;
pFrameInfo [out] 获取到的帧信息;
int MV_CC_GetOneFrameTimeout(void *handle, \ unsigned char *pData, \ unsigned int nDataSize, \ MV_FRAME_OUT_INFO_EX *pFrameInfo, \
int nMsec);
参数:
nMsec [in] 等待超时时间,单位为毫秒;
注意:该接口对于U3V、GIGE相机均可支持。
#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; } }
8. 获取相机节点值
int MV_CC_GetIntValue(void *handle, const char *strKey, MVCC_INTVALUE *pIntValue);
参数:
strKey [in] 节点名称;
pIntValue [out] 获取到的节点值;
可以用来获取需要的节点值。
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
day1.20180716
问题记录:
1. 测试相机采图时遇到问题:
首先,推测是图像数据格式错误
代码摘要:
1 //像素格式转换输入输出参数 2 MV_CC_PIXEL_CONVERT_PARAM stParam; 3 memset(&stParam, 0, sizeof(MV_CC_PIXEL_CONVERT_PARAM)); 4 5 //源数据 6 stParam.pSrcData = m_pFrameBuf; //原始图像数据 7 stParam.nSrcDataLen = stInfo.nFrameLen; //原始图像数据长度 8 stParam.enSrcPixelType = stInfo.enPixelType; //原始图像数据的像素格式 9 stParam.nWidth = stInfo.nWidth; //图像宽 10 stParam.nHeight = stInfo.nHeight; //图像高 11 12 //目标数据 13 stParam.enDstPixelType = PixelType_Gvsp_Mono8; //需要保存的像素格式类型,转换成MONO8格式 14 stParam.nDstBufferSize; //存储节点的大小 15 unsigned char* pImage = (unsigned char*)malloc(stParam.nDstBufferSize); 16 stParam.pDstBuffer; //输出数据缓冲区,存放转换之后的数据 17 18 nRet = MV_CC_ConvertPixelType(m_handle, &stParam); 19 if(MV_OK != nRet) 20 { 21 m_pImgBuf = (unsigned char *)malloc (stParam.nDstBufferSize); 22 memcpy(m_pImgBuf, stParam.pDstBuffer, stParam.nDstBufferSize); 23 break; 24 } 25 26 free(pImage); 27 28 29 显示: 30 gen_image1(&g_img, "byte", g_uiWidth, g_uiHeight, pimgPointer); 31 open_window (0, 0, (Hlong)g_uiWidth, (Hlong)g_uiHeight, (Hlong)g_uiID, "visible", "", &g_window); 32 disp_image(g_img, g_window);
检查图像格式,为单色8位图像,没有错误。
检查halcon接口的创建图像,发现错误定义图像的尺寸大小。
所以,应该在打开相机后查询相机的ROI参数。改正后,单帧图像采集功能正常。
笔记:
1. IP设置
强制设置相机网络参数,包括IP地址、子网掩码、默认网关。
int MV_GIGE_ForceIpEx(void *handle, unsigned int nIP, \
unsigned int nSubNetMask, \
unsigned int nDefaultGateWay);
强制设置之后需要重新创建设备句柄,仅支持GigEVision相机。
如果设备未DHCP的状态,调用该接口后设备将会重启~
int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList); ... nRet = MV_CC_CreateHandle(&m_handle, &m_stDevInfo); ... // 设置设备网络属性 unsigned int nIP = ... // 这里。需要知道怎么把IP地址表示为unsigned int ... nRet = MV_GIGE_ForceIpEx(m_handle, nIP, nSubNetMask, nDefaultGateWay); ... // 重新创建设备句柄 nRet = MV_CC_CreateHandle(&m_handle, &m_stDevInfo);
2. 设置配置IP的方式
int MV_GIGE_SetIpConfig(void *handle, unsigned int nType);
参数nType:IP配置方式,定义如下
3. 相机的log文档
int MV_CC_SetSDKLogPath(IN const char *pSDKLogPath);
设置好路径后,可以在指定路径下存放sdk日志。
1 ... 2 string strPath = "D:/Hik/SDK"; 3 nRet = MV_CC_SetSDKLogPath(strPath.c_str());
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
接下来,做连续采集。