[海康监控]海康监控摄像头IPCamera图像捕获
所使用海康威视摄像头型号:DS-2CD4026FWD-(A)(P)
海康威视IPCamera图像捕获方法有两种:
(1)利用SDK里面的NET_DVR_CaptureJPEGPicture_NEW进行视频抓图
(2)捕获实时流,将实时流解码成YV12,然后转换成RGB
在上一篇博文里,我介绍了第一种方法,但是由于NET_DVR_CaptureJPEGPicture_NEW该函数执行需要较长时间,无法实时,所以必须继续第二种方法。
在这篇博文里,我将介绍第二种方法,将捕获到的海康威视IPCamera摄像头图像转成OpenCV能处理的IplImage图像。
在实现完捕获海康威视IPCamera图像,转成OpenCV可以处理的IplImage图像(一)里面的方法后,发现不能实时,这个系统我是要做给给人看的,是需要实时演示的,这样子肯定是不行的。纠结了好久!然后查看海康威视《设备网络SDK使用手册_V4.2》,里面有一个预览模块示例程序,可惜我一直运行不了,报出的错误是PROCGETCONSOLEWINDOW GetConsoleWindow中的GetConsoleWindow被重定义,后来一直调试没调成功。
实在是没辙了,打海康客服,不过海康的客服我实在无语,北京的完全无法接通,直接打杭州的,打了四五遍终于有个人接电话了,对方不懂,然后说让个工程师回电话。OK,终于回了。他告诉我http://www.hikvision.com/cn/download_more_401.html 这里是有例程的,有分功能示例!突然间有了希望了,例程是VC6.0工程,改了一些地方后,终于能运行了。于是,将他的MFC工程相关的代码抠出来,重组。于是实现了捕获YV12格式的视频流的功能,光有YV12还是不行的,需要将YV12转成YUV4:4:4的,然后再将YUV色度空间转换成RGB色度空间,这个过程是在信件的DecBFun回调函数(回调函数请看这里!)里面执行的。
不多说了,上代码!
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include "Windows.h"
- #include "HCNetSDK.h"
- #include "PlayM4.h"
- #include <opencv2\opencv.hpp>
- #include "cv.h"
- #include "highgui.h"
- #include <time.h>
- #define USECOLOR 1
- using namespace std;
- using namespace std;
- //--------------------------------------------
- int iPicNum=0;//Set channel NO.
- LONG nPort=-1;
- HWND hWnd=NULL;
- void yv12toYUV(char *outYuv, char *inYv12, int width, int height,int widthStep)
- {
- int col,row;
- unsigned int Y,U,V;
- int tmp;
- int idx;
- //printf("widthStep=%d.\n",widthStep);
- for (row=0; row<height; row++)
- {
- idx=row * widthStep;
- int rowrowptr=row*width;
- for (col=0; col<width; col++)
- {
- //int colcolhalf=col>>1;
- tmp = (row/2)*(width/2)+(col/2);
- // if((row==1)&&( col>=1400 &&col<=1600))
- // {
- // printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp);
- // printf("row*width+col=%d,width*height+width*height/4+tmp=%d,width*height+tmp=%d.\n",row*width+col,width*height+width*height/4+tmp,width*height+tmp);
- // }
- Y=(unsigned int) inYv12[row*width+col];
- U=(unsigned int) inYv12[width*height+width*height/4+tmp];
- V=(unsigned int) inYv12[width*height+tmp];
- // if ((col==200))
- // {
- // printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp);
- // printf("width*height+width*height/4+tmp=%d.\n",width*height+width*height/4+tmp);
- // return ;
- // }
- if((idx+col*3+2)> (1200 * widthStep))
- {
- //printf("row * widthStep=%d,idx+col*3+2=%d.\n",1200 * widthStep,idx+col*3+2);
- }
- outYuv[idx+col*3] = Y;
- outYuv[idx+col*3+1] = U;
- outYuv[idx+col*3+2] = V;
- }
- }
- //printf("col=%d,row=%d.\n",col,row);
- }
- //解码回调 视频为YUV数据(YV12),音频为PCM数据
- 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 USECOLOR
- //int start = clock();
- IplImage* pImgYCrCb = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);//得到图像的Y分量
- yv12toYUV(pImgYCrCb->imageData, pBuf, pFrameInfo->nWidth,pFrameInfo->nHeight,pImgYCrCb->widthStep);//得到全部RGB图像
- IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);
- cvCvtColor(pImgYCrCb,pImg,CV_YCrCb2RGB);
- //int end = clock();
- #else
- IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 1);
- memcpy(pImg->imageData,pBuf,pFrameInfo->nWidth*pFrameInfo->nHeight);
- #endif
- //printf("%d\n",end-start);
- cvShowImage("IPCamera",pImg);
- cvWaitKey(1);
- #if USECOLOR
- cvReleaseImage(&pImgYCrCb);
- cvReleaseImage(&pImg);
- #else
- cvReleaseImage(&pImg);
- #endif
- //此时是YV12格式的视频数据,保存在pBuf中,可以fwrite(pBuf,nSize,1,Videofile);
- //fwrite(pBuf,nSize,1,fp);
- }
- /***************
- else if (lFrameType ==T_AUDIO16)
- {
- //此时是音频数据,数据保存在pBuf中,可以fwrite(pBuf,nSize,1,Audiofile);
- }
- else
- {
- }
- *******************/
- }
- ///实时流回调
- void CALLBACK fRealDataCallBack(LONG lRealHandle,DWORD dwDataType,BYTE *pBuffer,DWORD dwBufSize,void *pUser)
- {
- DWORD dRet;
- switch (dwDataType)
- {
- case NET_DVR_SYSHEAD: //系统头
- if (!PlayM4_GetPort(&nPort)) //获取播放库未使用的通道号
- {
- break;
- }
- if(dwBufSize > 0)
- {
- if (!PlayM4_OpenStream(nPort,pBuffer,dwBufSize,1024*1024))
- {
- dRet=PlayM4_GetLastError(nPort);
- break;
- }
- //设置解码回调函数 只解码不显示
- if (!PlayM4_SetDecCallBack(nPort,DecCBFun))
- {
- dRet=PlayM4_GetLastError(nPort);
- break;
- }
- //设置解码回调函数 解码且显示
- //if (!PlayM4_SetDecCallBackEx(nPort,DecCBFun,NULL,NULL))
- //{
- // dRet=PlayM4_GetLastError(nPort);
- // break;
- //}
- //打开视频解码
- if (!PlayM4_Play(nPort,hWnd))
- {
- dRet=PlayM4_GetLastError(nPort);
- break;
- }
- //打开音频解码, 需要码流是复合流
- if (!PlayM4_PlaySound(nPort))
- {
- dRet=PlayM4_GetLastError(nPort);
- break;
- }
- }
- break;
- case NET_DVR_STREAMDATA: //码流数据
- if (dwBufSize > 0 && nPort != -1)
- {
- BOOL inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);
- while (!inData)
- {
- Sleep(10);
- inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);
- OutputDebugString(L"PlayM4_InputData failed \n");
- }
- }
- 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);
- //---------------------------------------
- // 获取控制台窗口句柄
- //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;
- }
- //---------------------------------------
- //设置异常消息回调函数
- NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL);
- //cvNamedWindow("IPCamera");
- //---------------------------------------
- //启动预览并设置回调数据流
- 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;
- }
http://blog.csdn.net/wanghuiqi2008/article/details/31410509
热门文章推荐
- [海康监控]海康摄像头如何改密码(海康监控改密码图文教程)
- [海康监控]如何正确的修改海康威视摄像机IP地址
- [海康监控]海康NVR硬盘录像机密码恢复的解决办法
- [海康监控]海康威视视频流回放以及rtsp取流的格式说明
- [大华监控]大华硬盘录像机密码重置教程
- [海康NVR]关于NVR与ONVIF协议的问题
- [大华NVR]大华硬盘录像机远程监控设置方法
- [监控]海康威视视频流回放以及rtsp取流