海康威视多摄像头视频实时采集——OpenCV显示
海康威視多攝像頭視頻實時采集——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 this 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 CALLBACKfunction 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; }; #endifmain.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显示的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 房价是不是泡沫?
- 下一篇: 使用valgrind检测内存问题