海康威视多摄像头视频实时采集——OpenCV显示
2017-07-12 21:25
585 查看
海康威视多摄像头视频实时采集——OpenCV显示
最近由于工程上要做多摄像头多目标跟踪,用到的摄像头是海康威视的DS-2CD3320D摄像头。一、摄像头的配置
本人购买的摄像头的型号是DS-2CD3320D,采用以太网接口。为了实现多路采集视频,另外购置了4路以太网卡(淘宝购买)。将摄像头插入以太网口后,那么我们就可以通过官方提供的“设备网络搜索软件“——SADP工具,这个软件可以在海康威视的官方网站下载最新版本。本篇文章的很大程度上参照了lonelyrains的教程,在此基础上进行改进,同时在此表示感谢。下面主要补充一些lonelyrains没有提到的内容。
1、摄像头激活
摄像头的激活需要用到官方的SADP工具,我第一次参照lonelyrains的教程去其他网站下载SADP工具并不是最新版本,因此没有激活功能。lonelyrains教程中的版本也确实没有激活功能,可能是海康后续提供的。摄像头第一次使用的时候,激活状态会显示未激活,这个时候在需要设置一个新密码以激活设备。这点主要是出于隐私和安全性考虑。详细的内容说明书会提到,这里就不赘述了。
2、摄像头配置
前面步骤完成后就是配置摄像头的IP地址,我的本机网卡的IP地址配置保持不变。采集卡的IP设置见下图:IP地址和SADP配置的IP地址是一个子网即可。192.168.110.xxx
二、视频采集
如果上述的步骤成功完成,那么下面就可以通过官方的DEMO采集摄像头的视频了。官方的SDK下载地址。官方的DEMO就在解压后的”库文件“文件夹中。采集效果见下图:二、程序编写
废话不多说,直接上程序。HKCamDriver.cpp
/************************************************************************************** * FileName : HKCamDriver.cpp * Discrption : HCNetSDK Camera Driver. You can simply using t 4000 his class by the following way: HKCamDriver m_HKCamDriver; m_HKCamDriver.InitHKNetSDK(); m_HKCamDriver.InitCamera("xxx.xxx.xxx.xxx","usrname","psw"); This class support OpenCV. You can get IplImage form the CALLBACK function DecCBFun. But there remain have some problem need to be slove. 1. Software decode the video steam need too much CPU resource. 2. When we convert the yv12 to RGB, There need too much CPU resource. If we use OpenCV, we can not avoid to convert the yv12 to RGB. 3. CALLBACK function will be call every time, and we also get the image data at the same time. There we have some multi-thread problem to be solve. * Create : 2017-7-10 * Author : Li Zhan, UESTC(University of Electronic Science and Technology of China) ***************************************************************************************/ #include <windows.h> #include "HKCamDriver.h" HKCamDriver::HKCamDriver() { /* Create a mutex Lock when a object create */ } HKCamDriver::~HKCamDriver(){ ReleaseCamera(); } int HKCamDriver::ReleaseCamera(void) { if(!NET_DVR_StopRealPlay(lRealPlayHandle)){ printf("NET_DVR_StopRealPlay error! Error number: %d\n",NET_DVR_GetLastError()); return 0; } NET_DVR_Logout(lUserID); NET_DVR_Cleanup(); return 1; } void HKCamDriver::InitHKNetSDK(void) { /* SDK Init */ NET_DVR_Init(); /* Set the Connect Time and Reconnect time */ NET_DVR_SetConnectTime(200, 1); NET_DVR_SetReconnect(10000, true); for(int i = 0; i < MaxCameraNum; i++){ hMutex[i] = CreateMutex(NULL,FALSE,NULL); nPort[i] = -1; pImg[i] = NULL; } Scalefactor = 1.0f; } CamHandle HKCamDriver::InitCamera(char *sIP,char *UsrName,char *PsW,int Port) { NET_DVR_DEVICEINFO_V30 struDeviceInfo; lUserID = NET_DVR_Login_V30(sIP, Port,UsrName,PsW, &struDeviceInfo); if (lUserID < 0){ printf("Login error, %d\n", NET_DVR_GetLastError()); NET_DVR_Cleanup(); return -1; } NET_DVR_SetExceptionCallBack_V30(0, NULL,ExceptionCallBack, NULL); NET_DVR_CLIENTINFO ClientInfo; ClientInfo.lChannel = 1; /* Channel number Device channel number. */ ClientInfo.hPlayWnd = NULL; /* Window is NULL */ ClientInfo.lLinkMode = 0; /* Main Stream */ ClientInfo.sMultiCastIP = NULL; lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID,&ClientInfo,fRealDataCallBack,NULL,TRUE); if (lRealPlayHandle<0)return 0; return lRealPlayHandle; } void CALLBACK HKCamDriver::DecCBFun(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2) { long lFrameType = pFrameInfo->nType; char WindowName[15]; static IplImage* pImgYCrCb[MaxCameraNum]; sprintf_s(WindowName,"Windows:%d",nPort); if(lFrameType ==T_YV12) { WaitForSingleObject(hMutex[nPort],INFINITE); /* Single Camera decode 3.5% */ if(pImgYCrCb[nPort] == NULL){ pImgYCrCb[nPort] = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3); } if(pImg[nPort]==NULL){ pImg[nPort] = cvCreateImage(cvSize((int)(pFrameInfo->nWidth*Scalefactor),(int)(pFrameInfo->nHeight*Scalefactor)), 8, 3); } /* CPU: 0.1% */ yv12toYUV(pImgYCrCb[nPort]->imageData, pBuf, pFrameInfo->nWidth, pFrameInfo->nHeight,pImgYCrCb[nPort]->widthStep); cvResize(pImgYCrCb[nPort],pImg[nPort], CV_INTER_LINEAR); /* CPU 3.4% */ cvCvtColor(pImg[nPort],pImg[nPort],CV_YCrCb2RGB); /* 1080p Video Display Need 3.5% per Cmaera */ ReleaseMutex(hMutex[nPort]); } } void CALLBACK HKCamDriver::ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser) { char tempbuf[256] = {0}; switch(dwType) { case EXCEPTION_RECONNECT: /* Reconnet when Error Happen */ break; default: break; } } void HKCamDriver::yv12toYUV(char *outYuv, char *inYv12, int width, int height,int widthStep) { int col,row; unsigned int Y,U,V; int tmp; int idx; for (row=0; row<height; row++){ idx=row * widthStep; int rowptr=row*width; for (col=0; col<width; col++){ tmp = (row/2)*(width/2)+(col/2); Y=(unsigned int) inYv12[row*width+col]; U=(unsigned int) inYv12[width*height+width*height/4+tmp]; V=(unsigned int) inYv12[width*height+tmp]; outYuv[idx+col*3] = Y; outYuv[idx+col*3+1] = U; outYuv[idx+col*3+2] = V; } } } /* Realtime Steam Callback */ void CALLBACK HKCamDriver::fRealDataCallBack(LONG lRealHandle,DWORD dwDataType,BYTE *pBuffer,DWORD dwBufSize,void *pUser) { DWORD dRet; DWORD CameraIndex = 0; CameraIndex = lRealHandle; printf("lRealHandle = %ld\n",CameraIndex); switch (dwDataType) { /* System Head */ case NET_DVR_SYSHEAD: if (!PlayM4_GetPort(&nPort[CameraIndex]))break; if(dwBufSize > 0){ if (!PlayM4_OpenStream(nPort[CameraIndex],pBuffer,dwBufSize,1024*1024)){ dRet=PlayM4_GetLastError(nPort[CameraIndex]); break; } /* Setting the Decode function*/ if (!PlayM4_SetDecCallBack(nPort[CameraIndex],DecCBFun)){ dRet=PlayM4_GetLastError(nPort[CameraIndex]); break; } if (!PlayM4_Play(nPort[CameraIndex],NULL)){ dRet=PlayM4_GetLastError(nPort[CameraIndex]); break; } } break; /* Code steam data */ case NET_DVR_STREAMDATA: if (dwBufSize > 0 && nPort[CameraIndex] != -1) { BOOL inData=PlayM4_InputData(nPort[CameraIndex],pBuffer,dwBufSize); while (!inData){ Sleep(10); inData=PlayM4_InputData(nPort[CameraIndex],pBuffer,dwBufSize); } } break; } } int HKCamDriver::GetCamMat(Mat &Img,CamHandle handle,float factor) { /* Get the Port using handle */ int iPort = nPort[lRealPlayHandle]; /* Check the iPort is vaild */ if(iPort != -1){ WaitForSingleObject(hMutex[iPort],INFINITE); Mat(pImg[iPort]).copyTo(Img); ReleaseMutex(hMutex[iPort]); resize(Img,Img,cv::Size(),factor,factor); return 1; } /* If iPort is invaild, return empty */ return 0; } void HKCamDriver::SetScaleFactor(float factor) { Scalefactor = factor; }
HKCamDriver.h
#ifndef _HKCAMDRIVER_H_ #define _HKCAMDRIVER_H_ #include "opencv2\opencv.hpp" /* OpenCV header */ #include "plaympeg4.h" /* Software decoder header */ #include "HCNetSDK.h" /* HCNet Camera SDK header */ using namespace cv; /* Need the OpenCV support */ #define MaxCameraNum 20 /* Support the max number of camera is 20 */ typedef long CamHandle; /* Camera Handle is long int */ /* Multi-Thread Lock */ static HANDLE hMutex[MaxCameraNum]; static long nPort[MaxCameraNum]; static IplImage* pImg[MaxCameraNum]; static float Scalefactor; class HKCamDriver{ public: /* Constructed function */ HKCamDriver(); ~HKCamDriver(); /* Init the HKNetSDK, and the function only be using by once */ void InitHKNetSDK(void); /* Supply IP Address,UserName and Password,return the * camera hanlde */ CamHandle InitCamera(char *sIP,char *UsrName,char *PsW,int Port = 8000); int ReleaseCamera(void); /* Supply Camera handle, and function return the Mat */ int GetCamMat(Mat &Img,CamHandle handle = NULL,float factor = 1.0f); /* Supply camera handle, and function return IPlImage */ IplImage* GetCamImage(CamHandle handle,float factor = 1.0f); /* Exception Callback function */ static void CALLBACK ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser); /* Decode function, which convert yv12 to rgb */ static void CALLBACK DecCBFun(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2); /* Realtime decode function,which call mpeg4 to decode */ static void CALLBACK fRealDataCallBack(LONG lRealHandle,DWORD dwDataType,BYTE *pBuffer,DWORD dwBufSize,void *pUser); static void SetScaleFactor(float factor); private: /* Convert the video format yv12 to YUV format */ static void yv12toYUV(char *outYuv, char *inYv12, int width, int height,int widthStep); /* Realtime Play handle */ LONG lRealPlayHandle; /* Camera User ID */ LONG lUserID; }; #endif
main.cpp
clude <opencv\cv.h> #include <opencv\highgui.h> #include <opencv2\opencv.hpp> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/ml/ml.hpp> #include <windows.h> #include "HKCamDriver.h" #include <string> using namespace std; using namespace cv; HKCamDriver m_CamDriver[2]; int main() { m_CamDriver[0].InitHKNetSDK(); m_CamDriver[0].SetScaleFactor(0.5f); Sleep(500); m_CamDriver[0].InitCamera("192.168.110.65","admin","DS-2CD3320D"); Sleep(200); m_CamDriver[1].InitCamera("192.168.110.64","admin","DS-2CD3320D"); Mat video[2]; /* Wait */ Sleep(1000); while(1) { if(m_CamDriver[0].GetCamMat(video[0],NULL,1.0f)){ imshow("windows::im0",video[0]); if(m_CamDriver[1].GetCamMat(video[1],NULL,1.0f)){ imshow("windows::im1",video[1]); } waitKey(30); } return 0; }
运行效果
相关文章推荐
- 用OpenCV在MFC Dialog中Picture控件上显示摄像头采集实时视频
- opencv实现摄像头的实时图像采集与显示
- opencv获取摄像头视频并显示
- 在页面中嵌入Applet使用opencv调用摄像头,并显示实时摄像头内容
- OpenCV学习——摄像头采集视频
- 采集音频和摄像头视频并实时H264编码及AAC编码
- 采集音频和摄像头视频并实时H264编码及AAC编码
- windows opencv新手读取视频或摄像头,一闪而过,只显示第一帧
- OpenCV摄像头视频数据采集与RTSP和RTMP直播
- python 使用OpenCV保存视频失败的解决方案及摄像头显示灰色的解决办法
- 在MFC中通过opencv显示摄像头视频或者文件视频
- 在MFC中通过opencv显示摄像头视频或者文件视频
- Linux 下摄像头视频采集与显示
- 采集音频和摄像头视频并实时H264编码及AAC编码
- opencv摄像头视频采集(Windows系统)
- 采集音频和摄像头视频并实时H264编码及AAC编码
- OpenCV 获取摄像头,新建窗口显示摄像头视频
- opencv 从摄像头显示视频
- OpenCV+海康威视摄像头的实时读取
- 采集音频和摄像头视频并实时H264编码及AAC编码