首页 > 代码库 > 捕获海康威视IPCamera图像,转成OpenCV可以处理的图像(一)

捕获海康威视IPCamera图像,转成OpenCV可以处理的图像(一)

海康威视IPCamera图像捕获


捕获海康威视IPCamera图像,转成OpenCV可以处理的IplImage图像(一)

捕获海康威视IPCamera图像,转成OpenCV可以处理的IplImage图像(二)


所使用海康威视摄像头型号:DS-2CD4026FWD-(A)(P)


海康威视IPCamera图像捕获方法有两种:

(1)利用SDK里面的NET_DVR_CaptureJPEGPicture_NEW进行视频抓图

(2)捕获实时流,将实时流解码成YV12,然后转换成RGB


在这篇博文里,我先介绍第一种方法。

第一种方法,关键是调用NET_DVR_CaptureJPEGPicture_NEW这个函数。关于这个函数的参数,可以在SDK中找到,我这里截个图以作说明。


这个函数Ret是用于返回该图像大小的一个参数,但是该函数的这个参数大概是没有用引用或者指针的方式来传递参数,导致返回值一直是我初始化的0,因此为后面的操作带来了些许的不便——不得不使用一个较大的内存来保存图像一定能存储的下。

NET_DVR_CaptureJPEGPicture_NEW这个函数是将单帧数据捕获并保存成JPEG,存放在指定的内存空间中。也就是内存里的JPEG。为了获得OpenCV能处理的IplImage图像,必须在内存中进行解码。

OpenCV在内存中解码的函数只有一个:imdecode,下图是imdecode的说明


该函数要求buf必须是数组或者是byte类型的vector. 因此需要对char * 类型的JPEG压缩图像进行存储格式转换。


#include <cstdio>
#include <iostream>
#include <ctime>
#include <Windows.h>
#include "HCNetSDK.h"
#include "highgui.h"
#include "cv.h"


using namespace cv;
using namespace std;


//typedef HWND (WINAPI *PROCGETCONSOLEWINDOW)();
//PROCGETCONSOLEWINDOW GetConsoleWindow;

int main(int argc, char * argv[]) 
{	
	//---------------------------------------
	// 初始化
	NET_DVR_Init();
	//设置连接时间与重连时间
	NET_DVR_SetConnectTime(2000, 1);
	NET_DVR_SetReconnect(10000, true);
	
	//---------------------------------------
	//获取控制台窗口句柄
	//HMODULE hKernel32 = GetModuleHandle((LPCWSTR)"kernel32");
	//GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow");

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

	
	//---------------------------------------
	//cvNamedWindow("camera",CV_WINDOW_AUTOSIZE);
	IplImage* frame;
	//定义JPEG图像质量
	LPNET_DVR_JPEGPARA JpegPara = new NET_DVR_JPEGPARA;
	JpegPara->wPicQuality = 0;
	JpegPara->wPicSize = 9;
	
	char * Jpeg = new char[200*1024];
	DWORD len = 200*1024;
	LPDWORD Ret = 0;
			
	if(!NET_DVR_SetCapturePictureMode(BMP_MODE))
	{
		cout<<"Set Capture Picture Mode error!"<<endl;
		cout<<"The error code is "<<NET_DVR_GetLastError()<<endl;
	}

	//bool capture = NET_DVR_CaptureJPEGPicture(lUserID,1,JpegPara,"1111");
	vector<char>data(200*1024);
	while(1)
	{
	bool capture = NET_DVR_CaptureJPEGPicture_NEW(lUserID,1,JpegPara,Jpeg,len,Ret);
	if(!capture)
	{
		printf("Error: NET_DVR_CaptureJPEGPicture_NEW = %d", NET_DVR_GetLastError());
		return -1;	
	}	

	for(int i=0;i<200*1024;i++)
		data[i] = Jpeg[i];

	Mat img = imdecode(Mat(data),1);
	imshow("camera",img);
	waitKey(1);
	
	}

	//FILE * fp = fopen("3.jpg","wb");
	//fwrite(Jpeg,1,123*1024,fp);
	//fclose(fp);
	
	return 0;
}

运行这个代码当然OpenCV的配置不能少,HCNetSDK.h也必须包含进工程。

运行这个程序,可以捕获到图像,但是我计算了下时间,在调用 NET_DVR_CaptureJPEGPicture_NEW(lUserID,1,JpegPara,Jpeg,len,Ret);这一句话的时候,用时300ms,这个耗时太长,无法实时!但是如果对实时无要求,用这个也可以了,好理解!