捕获海康威视IPCamera图像,转成OpenCV能够处理的图像(二)
海康威視IPCamera圖像捕獲
捕獲海康威視IPCamera圖像。轉(zhuǎn)成OpenCV能夠處理的IplImage圖像(一)
捕獲海康威視IPCamera圖像。轉(zhuǎn)成OpenCV能夠處理的IplImage圖像(二)
所使用海康威視攝像頭型號(hào):DS-2CD4026FWD-(A)(P)
海康威視IPCamera圖像捕獲方法有兩種:
(1)利用SDK里面的NET_DVR_CaptureJPEGPicture_NEW進(jìn)行視頻抓圖
(2)捕獲實(shí)時(shí)流。將實(shí)時(shí)流解碼成YV12,然后轉(zhuǎn)換成RGB
在上一篇博文里,我介紹了第一種方法,可是由于NET_DVR_CaptureJPEGPicture_NEW該函數(shù)執(zhí)行須要較長(zhǎng)時(shí)間,無(wú)法實(shí)時(shí),所以必須繼續(xù)另外一種方法。
在這篇博文里,我將介紹另外一種方法,將捕獲到的海康威視IPCamera攝像頭圖像轉(zhuǎn)成OpenCV能處理的IplImage圖像。
在實(shí)現(xiàn)完捕獲海康威視IPCamera圖像,轉(zhuǎn)成OpenCV能夠處理的IplImage圖像(一)里面的方法后,發(fā)現(xiàn)不能實(shí)時(shí)。這個(gè)系統(tǒng)我是要做給給人看的,是須要實(shí)時(shí)演示的,這樣子肯定是不行的。
糾結(jié)了好久!然后查看海康威視《設(shè)備網(wǎng)絡(luò)SDK使用手冊(cè)_V4.2》,里面有一個(gè)預(yù)覽模塊演示樣例程序,可惜我一直執(zhí)行不了,報(bào)出的錯(cuò)誤是PROCGETCONSOLEWINDOW GetConsoleWindow中的GetConsoleWindow被重定義,后來(lái)一直調(diào)試沒(méi)調(diào)成功。
實(shí)在是沒(méi)轍了。打海康客服,只是海康的客服我實(shí)在無(wú)語(yǔ),北京的全然無(wú)法接通,直接打杭州的,打了四五遍最終有個(gè)人接電話了,對(duì)方不懂,然后說(shuō)讓個(gè)project師回電話。OK。最終回了。他告訴我http://www.hikvision.com/cn/download_more_401.html?這里是有例程的,有分功能演示樣例!突然間有了希望了,例程是VC6.0project,改了一些地方后。最終能執(zhí)行了。于是,將他的MFCproject相關(guān)的代碼摳出來(lái),重組。
于是實(shí)現(xiàn)了捕獲YV12格式的視頻流的功能,光有YV12還是不行的,須要將YV12轉(zhuǎn)成YUV4:4:4的。然后再將YUV色度空間轉(zhuǎn)換成RGB色度空間,這個(gè)過(guò)程是在信件的DecBFun回調(diào)函數(shù)(回調(diào)函數(shù)請(qǐng)看這里!)里面執(zhí)行的。
不多說(shuō)了,上代碼!
#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 rowptr=row*width;for (col=0; col<width; col++){//int colhalf=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); }//解碼回調(diào) 視頻為YUV數(shù)據(jù)(YV12),音頻為PCM數(shù)據(jù) 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(); #elseIplImage* 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 USECOLORcvReleaseImage(&pImgYCrCb);cvReleaseImage(&pImg); #elsecvReleaseImage(&pImg); #endif//此時(shí)是YV12格式的視頻數(shù)據(jù),保存在pBuf中,能夠fwrite(pBuf,nSize,1,Videofile);//fwrite(pBuf,nSize,1,fp);}/***************else if (lFrameType ==T_AUDIO16){//此時(shí)是音頻數(shù)據(jù),數(shù)據(jù)保存在pBuf中。能夠fwrite(pBuf,nSize,1,Audiofile);}else{}*******************/}///實(shí)時(shí)流回調(diào) void CALLBACK fRealDataCallBack(LONG lRealHandle,DWORD dwDataType,BYTE *pBuffer,DWORD dwBufSize,void *pUser) {DWORD dRet;switch (dwDataType){case NET_DVR_SYSHEAD: //系統(tǒng)頭if (!PlayM4_GetPort(&nPort)) //獲取播放庫(kù)未使用的通道號(hào){break;}if(dwBufSize > 0){if (!PlayM4_OpenStream(nPort,pBuffer,dwBufSize,1024*1024)){dRet=PlayM4_GetLastError(nPort);break;}//設(shè)置解碼回調(diào)函數(shù) 僅僅解碼不顯示if (!PlayM4_SetDecCallBack(nPort,DecCBFun)){dRet=PlayM4_GetLastError(nPort);break;}//設(shè)置解碼回調(diào)函數(shù) 解碼且顯示//if (!PlayM4_SetDecCallBackEx(nPort,DecCBFun,NULL,NULL))//{// dRet=PlayM4_GetLastError(nPort);// break;//}//打開(kāi)視頻解碼if (!PlayM4_Play(nPort,hWnd)){dRet=PlayM4_GetLastError(nPort);break;}//打開(kāi)音頻解碼, 須要碼流是復(fù)合流if (!PlayM4_PlaySound(nPort)){dRet=PlayM4_GetLastError(nPort);break;} }break;case NET_DVR_STREAMDATA: //碼流數(shù)據(jù)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: //預(yù)覽時(shí)重連printf("----------reconnect--------%d\n", time(NULL));break;default:break;} }void main() {//---------------------------------------// 初始化NET_DVR_Init();//設(shè)置連接時(shí)間與重連時(shí)間NET_DVR_SetConnectTime(2000, 1);NET_DVR_SetReconnect(10000, true);//---------------------------------------// 獲取控制臺(tái)窗體句柄//HMODULE hKernel32 = GetModuleHandle((LPCWSTR)"kernel32");//GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow");//---------------------------------------// 注冊(cè)設(shè)備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;}//---------------------------------------//設(shè)置異常消息回調(diào)函數(shù)NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL);//cvNamedWindow("IPCamera");//---------------------------------------//啟動(dòng)預(yù)覽并設(shè)置回調(diào)數(shù)據(jù)流 NET_DVR_CLIENTINFO ClientInfo;ClientInfo.lChannel = 1; //Channel number 設(shè)備通道號(hào)ClientInfo.hPlayWnd = NULL; //窗體為空,設(shè)備SDK不解碼僅僅取流ClientInfo.lLinkMode = 0; //Main StreamClientInfo.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);//---------------------------------------//關(guān)閉預(yù)覽if(!NET_DVR_StopRealPlay(lRealPlayHandle)){printf("NET_DVR_StopRealPlay error! Error number: %d\n",NET_DVR_GetLastError());return;}//注銷(xiāo)用戶(hù)NET_DVR_Logout(lUserID);NET_DVR_Cleanup();return; }
最終能夠?qū)崟r(shí)捕獲圖像了。并且轉(zhuǎn)換成了OpenCV能夠處理的圖像格式。
在這個(gè)過(guò)程中搜了非常多資料,可是沒(méi)有一個(gè)地方能具體說(shuō)明,只是最終還是把這個(gè)給攻克了。
?
附加說(shuō)明:假設(shè)最后要做圖像處理而不是像我這樣僅僅是將採(cǎi)集的圖像顯示出來(lái),那么以下的語(yǔ)句是不須要的。
?
?后記:盡管這個(gè)功能實(shí)現(xiàn)了,可是與我的圖像處理函數(shù)怎樣結(jié)合到一起?我想到的是用鏈隊(duì)列,雙線程。鏈隊(duì)列代碼請(qǐng)看這里。
?
寫(xiě)這兩篇博文的目的事實(shí)上也是想讓處于探索過(guò)程中的開(kāi)發(fā)者能少走些彎路,節(jié)省些時(shí)間,衷心希望本文能夠幫到你!
由于本人已經(jīng)畢業(yè)。項(xiàng)目也早就已經(jīng)結(jié)題了,手頭上不再具有可供調(diào)試的硬件設(shè)備。因此對(duì)于大家所碰到的問(wèn)題,我基本上也已經(jīng)無(wú)法回答了。非常抱歉!
假設(shè)大家在開(kāi)發(fā)海康威視攝像頭的過(guò)程中遇到了什么問(wèn)題能夠去跟海康客服去溝通,假設(shè)您所在地區(qū)的客服無(wú)法聯(lián)系上的話,請(qǐng)直接聯(lián)系杭州總部的客服。
最后,對(duì)之前非常長(zhǎng)一段時(shí)間對(duì)大家所提出的問(wèn)題一直置之不理再次表示道歉!
謝謝大家的支持!
**************************************************************************************
轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/wanghuiqi2008/article/details/31410509
**************************************************************************************
轉(zhuǎn)載于:https://www.cnblogs.com/mqxnongmin/p/10500008.html
總結(jié)
以上是生活随笔為你收集整理的捕获海康威视IPCamera图像,转成OpenCV能够处理的图像(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 技术出身如何创业
- 下一篇: java常用时间工具类