海康威视多摄像头视频实时采集——OpenCV显示
海康威視多攝像頭視頻實(shí)時(shí)采集——OpenCV顯示
最近由于工程上要做多攝像頭多目標(biāo)跟蹤,用到的攝像頭是海康威視的DS-2CD3320D攝像頭。
一、攝像頭的配置
本人購(gòu)買的攝像頭的型號(hào)是DS-2CD3320D,采用以太網(wǎng)接口。為了實(shí)現(xiàn)多路采集視頻,另外購(gòu)置了4路以太網(wǎng)卡(淘寶購(gòu)買)。
將攝像頭插入以太網(wǎng)口后,那么我們就可以通過(guò)官方提供的“設(shè)備網(wǎng)絡(luò)搜索軟件“——SADP工具,這個(gè)軟件可以在海康威視的官方網(wǎng)站下載最新版本。本篇文章的很大程度上參照了lonelyrains的教程,在此基礎(chǔ)上進(jìn)行改進(jìn),同時(shí)在此表示感謝。下面主要補(bǔ)充一些lonelyrains沒(méi)有提到的內(nèi)容。
1、攝像頭激活
攝像頭的激活需要用到官方的SADP工具,我第一次參照l(shuí)onelyrains的教程去其他網(wǎng)站下載SADP工具并不是最新版本,因此沒(méi)有激活功能。lonelyrains教程中的版本也確實(shí)沒(méi)有激活功能,可能是海康后續(xù)提供的。?
?
攝像頭第一次使用的時(shí)候,激活狀態(tài)會(huì)顯示未激活,這個(gè)時(shí)候在需要設(shè)置一個(gè)新密碼以激活設(shè)備。這點(diǎn)主要是出于隱私和安全性考慮。詳細(xì)的內(nèi)容說(shuō)明書(shū)會(huì)提到,這里就不贅述了。
2、攝像頭配置
前面步驟完成后就是配置攝像頭的IP地址,我的本機(jī)網(wǎng)卡的IP地址配置保持不變。采集卡的IP設(shè)置見(jiàn)下圖:?
?
IP地址和SADP配置的IP地址是一個(gè)子網(wǎng)即可。192.168.110.xxx?
二、視頻采集
如果上述的步驟成功完成,那么下面就可以通過(guò)官方的DEMO采集攝像頭的視頻了。官方的SDK下載地址。官方的DEMO就在解壓后的”庫(kù)文件“文件夾中。采集效果見(jiàn)下圖:?
二、程序編寫(xiě)
廢話不多說(shuō),直接上程序。
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; }運(yùn)行效果
總結(jié)
以上是生活随笔為你收集整理的海康威视多摄像头视频实时采集——OpenCV显示的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 房价是不是泡沫?
- 下一篇: 使用valgrind检测内存问题