做视觉的朋友肯定会接触到各种相机(各种品牌),不管是工业相机、监控相机还是普通的USB Camera,都有一套常用的处理技巧,今天我们来看看IPCamera结合OpenCV图像处理的一般套路。IPCamera最常见的就是网络监控摄像头,而国内海康威视已经占了大部分份额,而且现在的监控摄像头还添加了各种智能功能,更方便用户使用。今天就以海康的网络摄像头来说明(具体型号没查到,客户给的,做了一层铁壳封装)。

    第一步:购买摄像头。不管是自行购买还是客户指定,一定要确保支持二次开发,有途径能够获取相机的SDK,这样才能对相机进行下一步操作。

    第二步:使用SDK中的demo操作相机。这一步骤主要的目的是确保SDK没问题,免得后续浪费时间,当然如果是海康对应的IPCamera一般官网可以下载到SDK,应该没问题。相机与SDK验证分以下几个步骤:

    ① 保证接通电源,链接网络,设置IP和摄像头同一网段;

    一般IP地址为:192.168.1.64,我们将电脑IP地址设置成192.168.1.x,(x可以是除64以外的数字,比如2),然后打开浏览器,然后输入192.168.1.64

海康IPCamera结合OpenCV图像处理的一般步骤_回调函数

    ② 浏览器登录验证,输入账户密码,看是否能够预览相机画面;

海康IPCamera结合OpenCV图像处理的一般步骤_回调函数_02

海康IPCamera结合OpenCV图像处理的一般步骤_回调函数_03

    ③ 使用SDK中的demo打开相机。以C++为例,这一步一般注意编译环境问题,还有demo默认字符集是Unicode还是多字节,一般都是多字节字符集。运行时要将需要的HK dll 拷贝到exe同目录,如果还有其他问题需要看下SDK说明中的注意事项或操作手册。

海康IPCamera结合OpenCV图像处理的一般步骤_回调函数_04

    第三步:从简易demo中提取我们想要的功能并单独复现。个人建议自己新建一个MFC或Qt界面来复现demo中需要的功能,一是方便我们了解相机的一些操作函数使用,另一方面demo中一般多了一些我们不需要的功能且UI并不美观,当然,如果你很着急,可以直接在上面改。复现时的一般步骤:

    ① 注册相机。需要设置IP,端口,用户名,密码,注意变量的类型,然后找到注册函数,验证是否能成功注册,注册失败一般都会提示或者有对应的错误代码。这里在调用注册函数NET_DVR_Login_V30/V40之前,需要先调用NET_DVR_Init()函数来初始化SDK,否则其他函数都调用不了,这个需要看手册(手册中也有简单的示例代码和说明),最后和它配对使用的释放SDK资源的函数在销毁窗口时使用。

NET_DVR_Cleanup(); //NET_DVR_Init和NET_DVR_Cleanup需要配对使用

海康IPCamera结合OpenCV图像处理的一般步骤_vim_05

海康IPCamera结合OpenCV图像处理的一般步骤_vim_06

海康IPCamera结合OpenCV图像处理的一般步骤_ip地址_07

NET_DVR_RealPlay_V30/V40函数,如果不设置回调函数,就直接给定Picture Control对应的窗口句柄,那么预览图像会显示在界面中 ,但是你无法操作图像。一般我们都需要指定回调函数,在回调函数中将图像数据解码后push到队列中,供图像处理时使用,此时hPlayWnd=NULL。

NET_DVR_CLIENTINFO ClientInfo;
//ClientInfo.hPlayWnd = GetDlgItem(IDC_PIC)->m_hWnd;
ClientInfo.hPlayWnd = NULL;
ClientInfo.lChannel = iChanIndex + 1;
ClientInfo.lLinkMode = 0;
ClientInfo.sMultiCastIP = NULL;
TRACE("Channel number:%d\n", ClientInfo.lChannel);
m_lPlayHandle = NET_DVR_RealPlay_V30(m_struDeviceInfo.lLoginID, &ClientInfo, fRealDataCallBack, NULL, TRUE);
if (-1 == m_lPlayHandle)
{
DWORD err = NET_DVR_GetLastError();
CString m_csErr;
m_csErr.Format("播放出错,错误代码%d", err);
MessageBox(m_csErr);
}

转到回调函数,可以设置是否边解码边显示预览,这里不预览(我们要显示处理后的预览图),这里的图像类型是T_YV12,使用一个解码回调函数来处理,vFrames队列中已是转换后的Mat类型图像。

//设置解码回调函数 只解码不显示
if (!PlayM4_SetDecCallBack(nPort, DecCBFun))
{
dRet = PlayM4_GetLastError(nPort);
break;
}
void CALLBACK DecCBFun(long nPort, char * pBuf, long nSize, FRAME_INFO * pFrameInfo, long nReserved1, long nReserved2)
{
long lFrameType = pFrameInfo->nType;

if (lFrameType == T_YV12)
{
/*if (HK_Frame.empty())
{
HK_Frame.create(pFrameInfo->nHeight, pFrameInfo->nWidth, CV_8UC3);
}*/
Mat YUVImage(pFrameInfo->nHeight + pFrameInfo->nHeight / 2, pFrameInfo->nWidth, CV_8UC1, (unsigned char*)pBuf);
Mat img;
cvtColor(YUVImage, img, COLOR_YUV2BGR_YV12);
vFrames.push(img.clone());
}
}

    ③ 从Mat队列中取图像处理。这时候就可以使用线程或Timer在队列中逐个取图进行分析处理,每处理完一帧后pop释放当前帧;

HK_Frame = vFrames.front();
//其他处理操作
vFrames.pop();

    第四步:关闭预览,释放SDK资源;关闭预览,注销,释放SDK.

StopPlay();
NET_DVR_Logout_V30(m_struDeviceInfo.lLoginID);
NET_DVR_Cleanup(); //NET_DVR_Init和NET_DVR_Cleanup需要配对使用

    效果如下:

海康IPCamera结合OpenCV图像处理的一般步骤_ip地址_08

    完整代码将发布在中,欢迎关注。