在笔记1中,学会了用opencv打开USB摄像头,但是有时候我们需要用到网络摄像头,我们该怎么去调用,并用opencv做图像处理呢?我们以海康威视网络摄像头举例:

    首先配置好环境:

    在官网下载SDK文件,点击打开链接,对照自己的开发平台,选择下载,我下载的是设备网络SDK-Win32。下载好之后,将其解压到本地中。

    VC++包含目录中添加头文件,我的地址是:E:\CH-HCNetSDK(Windows32)V5.3.1.20_build20170820\CH-HCNetSDK(Windows32)V5.3.1.20_build20170820\include。

    同样,VC++库目录中添加lib路径,我的地址是:E:\CH-HCNetSDK(Windows32)V5.3.1.20_build20170820\CH-HCNetSDK(Windows32)V5.3.1.20_build20170820\lib。

    链接器、输入、附加依赖项里,添加SDK中的lib:GdiPlus.lib、HCCore.lib、HCCore.lib、PlayCtrl.lib。

    做好上面的步骤,保存就行了。


    接下来就是编写代码:

#include <cstdlib>
#include <cstring>
#include <iostream>
#include "Windows.h"
#include "HCNetSDK.h"
#include "plaympeg4.h"
#include <opencv2\opencv.hpp>
#include <time.h>

using namespace std;
using namespace cv;

LONG nPort = -1;

volatile int gbHandling = 3;

//解码回调 视频为YUV数据(YV12),音频为PCM数据
void CALLBACK DecCBFun(long nPort, char * pBuf, long nSize, FRAME_INFO * pFrameInfo, long nReserved1, long nReserved2)
{
	if (gbHandling)
	{
		gbHandling--;
		return;
	}
	long lFrameType = pFrameInfo->nType;
	if (lFrameType == T_YV12)
	{
		Mat pImg(pFrameInfo->nHeight, pFrameInfo->nWidth, CV_8UC3);
		Mat src(pFrameInfo->nHeight + pFrameInfo->nHeight / 2, pFrameInfo->nWidth, CV_8UC1, pBuf);
		cvtColor(src, pImg, CV_YUV2BGR_YV12);
		
		imshow("opencamera", pImg);
		waitKey(1);
	}
	gbHandling = 3;
}


///实时流回调
void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void *pUser)
{
	switch (dwDataType)
	{
	case NET_DVR_SYSHEAD: //系统头

		if (!PlayM4_GetPort(&nPort))  //获取播放库未使用的通道号
		{
			break;
		}
		//m_iPort = lPort; //第一次回调的是系统头,将获取的播放库port号赋值给全局port,下次回调数据时即使用此port号播放
		if (dwBufSize > 0)
		{
			if (!PlayM4_SetStreamOpenMode(nPort, STREAME_REALTIME))  //设置实时流播放模式
			{
				break;
			}
			if (!PlayM4_OpenStream(nPort, pBuffer, dwBufSize, 10 * 1024 * 1024)) //打开流接口
			{
				break;
			}
			if (!PlayM4_Play(nPort, NULL)) //播放开始
			{
				break;
			}
			if (!PlayM4_SetDecCallBack(nPort, DecCBFun))
			{
				break;
			}
		}
		break;
	case NET_DVR_STREAMDATA:   //码流数据
		if (dwBufSize > 0 && nPort != -1)
		{
			if (!PlayM4_InputData(nPort, pBuffer, dwBufSize))
			{
				cout << "error" << PlayM4_GetLastError(nPort) << endl;
				break;
			}
		}
		break;
	default: //其他数据
		if (dwBufSize > 0 && nPort != -1)
		{
			if (!PlayM4_InputData(nPort, pBuffer, dwBufSize))
			{
				break;
			}
		}
		break;
	}
}


void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)
{
	char tempbuf[256] = { 0 };
	switch (dwType)
	{
	case EXCEPTION_RECONNECT:    //预览时重连
		printf("----------reconnect--------%d\n", time(NULL));
		break;
	default:
		break;
	}
}

void main()
{
	// 初始化
	NET_DVR_Init();
	//设置连接时间与重连时间
	NET_DVR_SetConnectTime(2000, 1);
	NET_DVR_SetReconnect(10000, true);

	// 注册设备
	LONG lUserID;
	NET_DVR_DEVICEINFO_V30 struDeviceInfo;
	lUserID = NET_DVR_Login_V30("10.170.6.185", 8000, "admin", "abc20170620", &struDeviceInfo);
	if (lUserID < 0)
	{
		printf("Login error, %d\n", NET_DVR_GetLastError());
		NET_DVR_Cleanup();
		return;
	}

	//设置异常消息回调函数
	NET_DVR_SetExceptionCallBack_V30(0, NULL, g_ExceptionCallBack, NULL);

	//启动预览并设置回调数据流 
	NET_DVR_CLIENTINFO ClientInfo;
	ClientInfo.lChannel = 1;        //Channel number 设备通道号
	ClientInfo.hPlayWnd = NULL;     //窗口为空,设备SDK不解码只取流
	ClientInfo.lLinkMode = 0;       //Main Stream
	ClientInfo.sMultiCastIP = NULL;
	LONG lRealPlayHandle;
	lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, fRealDataCallBack, NULL, TRUE);
	if (lRealPlayHandle<0)
	{
		printf("NET_DVR_RealPlay_V30 failed! Error number: %d\n", NET_DVR_GetLastError());
		return;
	}

	//cvWaitKey(0);
	Sleep(-1);

	//fclose(fp);
	//关闭预览
	if (!NET_DVR_StopRealPlay(lRealPlayHandle))
	{
		printf("NET_DVR_StopRealPlay error! Error number: %d\n", NET_DVR_GetLastError());
		return;
	}
	//注销用户
	NET_DVR_Logout(lUserID);
	NET_DVR_Cleanup();
	return;
}
    解码回调函数里我们用了cvtcolor函数将采集到的YUV格式转换为RGB,这样可以让opencv进行处理。接下来做图像处理时,一个比较好的思路是将一帧一帧的数据送到队列中,再开启一个线程从队列取出进行处理就可以了。

    程序运行:

    

    工程下载:点击打开链接(内附海康威视错误代码大全)

    参考博客:http://blog.csdn.net/wanghuiqi2008/article/details/31410509

                        http://blog.csdn.net/m0_37901643/article/details/72817862