1. 程式人生 > >海康網路攝像機視訊資料的獲取及使用opencv顯示

海康網路攝像機視訊資料的獲取及使用opencv顯示

最近要使用海康威視攝像機獲取資料做處理。主要是藉助Opencv這個工具,所以做了一下步驟。
我用的是基於Qt+opencv的來顯示海康資料的。本人海康的型號為:DS-2CD2820FD
1、海康sdk開發環境的配置(我只給出我的配置路徑,視具體情況而定)

LIBS += -LD:\Softwares\HaiKang\x64\lib\
-lHCNetSDK \
-lGdiPlus \
-lHCCore \
-lPlayCtrl


LIBS += -LD:\Softwares\HaiKang\x64\lib\HCNetSDKCom\
-lHCAlarm \
-lHCGeneralCfgMgr \
-lHCPreview

2、包含的標頭檔案

#include<stdio.h>
#include<iostream>
#include<time.h>
#include<Windows.h>
#include<HCNetSDK.h>
#include<plaympeg4.h>
#include<cstring>


using namespace std;

#include"./opencv2/opencv.hpp"
using namespace  cv;



typedef HWND (WINAPI *PROCGETCONSOLEWINDOW)();
PROCGETCONSOLEWINDOW GetConsoleWindowAPI;

3、具體的實現程式碼如下:


LONG nPort=-1; //全域性的播放庫port號
//資料型別轉換
void yv12toYUV(uchar *outYuv, uchar *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;
        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; } } } ////解碼回撥 視訊為YUV資料(YV12) void CALLBACK DecCBFun(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2) { long lFrameType = pFrameInfo->nType; if(lFrameType ==T_YV12) { Mat matYCrCb=Mat(pFrameInfo->nHeight, pFrameInfo->nWidth,CV_8UC3); Mat matImge=Mat(pFrameInfo->nHeight, pFrameInfo->nWidth,CV_8UC3); yv12toYUV(matYCrCb.data,(uchar*)pBuf,pFrameInfo->nWidth,pFrameInfo->nHeight,matYCrCb.step); cvtColor(matYCrCb,matImge,CV_YCrCb2RGB); imshow("matImge IPCamera",matImge); waitKey(1);//一定記得加不然會出錯 } } void CALLBACK g_RealDataCallBack_V30(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer,DWORD dwBufSize,void* dwUser) { HWND hWnd=GetConsoleWindowAPI(); 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); //--------------------------------------- //設定異常訊息回撥函式 NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL); //--------------------------------------- // 獲取控制檯視窗控制代碼 HMODULE hKernel32 = GetModuleHandle(L"kernel32"); GetConsoleWindowAPI = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow"); //--------------------------------------- // 註冊裝置 LONG lUserID; //登入引數,包括裝置地址、登入使用者、密碼等 NET_DVR_USER_LOGIN_INFO struLoginInfo = {0}; struLoginInfo.bUseAsynLogin = 0; //同步登入方式 strcpy(struLoginInfo.sDeviceAddress, "192.168.10.64"); //裝置IP地址 struLoginInfo.wPort = 8000; //裝置服務埠 strcpy(struLoginInfo.sUserName, "admin"); //裝置登入使用者名稱 strcpy(struLoginInfo.sPassword, "admin123"); //裝置登入密碼 //裝置資訊, 輸出引數 NET_DVR_DEVICEINFO_V40 struDeviceInfoV40 = {0}; lUserID = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40); if (lUserID < 0) { printf("Login failed, error code: %d\n", NET_DVR_GetLastError()); NET_DVR_Cleanup(); return; } //--------------------------------------- //啟動預覽並設定回撥資料流 LONG lRealPlayHandle; NET_DVR_PREVIEWINFO struPlayInfo = {0}; struPlayInfo.hPlayWnd = NULL; //需要SDK解碼時控制代碼設為有效值,僅取流不解碼時可設為空 struPlayInfo.lChannel = 1; //預覽通道號 struPlayInfo.dwStreamType = 0; //0-主碼流,1-子碼流,2-碼流3,3-碼流4,以此類推 struPlayInfo.dwLinkMode = 0; //0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP struPlayInfo.bBlocked = 1; //0- 非阻塞取流,1- 阻塞取流 lRealPlayHandle = NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, g_RealDataCallBack_V30, NULL); if (lRealPlayHandle < 0) { printf("NET_DVR_RealPlay_V40 error, %d\n", NET_DVR_GetLastError()); NET_DVR_Logout(lUserID); NET_DVR_Cleanup(); return; } Sleep(-1); //--------------------------------------- //關閉預覽 NET_DVR_StopRealPlay(lRealPlayHandle); //登出使用者 NET_DVR_Logout(lUserID); NET_DVR_Cleanup(); return; }