海康威視攝像頭+OpenCV+VS2017 圖像處理小結(二)
https://blog.csdn.net/o_ha_yo_yepeng/article/details/79825648
目錄
一、海康威視SDK下載以及VS工程配置:
1. 下載海康威視SDK:
2. 新建控制台工程:
3. 配置屬性表:
二、OpenCV下載以及屬性表的添加:
1. 源文件下載、安裝以及庫文件和頭文件的提取:
2.補充屬性表內容:
三、海康攝像頭碼流轉碼並同通過OpenCV顯示:
1.代碼:
2.Bug調試
3.程序運行效果:
四、小結:
一、海康威視SDK下載以及VS工程配置:
1. 下載海康威視SDK:
海康威視SDK下載地址(32位或者64位根據各自工程需求下載,博主此處下載的是64位)
2. 新建控制台工程:
將工程模式調至Release|X64
模式
在工程目錄下新建一個命名為3rd_x64的文件夾存放三方庫,再在此文件夾中新建一個名為HC_vision_SDK_x64庫文件夾,並新建include文件夾和lib文件夾(如下圖所示),其中的文件分別來自於我們下載的64位SDK中的頭文件(CH-HCNetSDK(Windows64)V5.3.1.22_build20170909\頭文件\)以及庫文件夾下文件(CH-HCNetSDK(Windows64)V5.3.1.22_build20170909\庫文件\)。
3. 配置屬性表:
(1)為了方便之后重新建立的工程使用這次項目的配置,需要新建一個屬性表,下次新建工程需要配置的時候只要導入此屬性表就好,到屬性管理器中的Release|64模式下右擊新建屬性表,命名為HC_x64_release.prosp,雙擊新建好的屬性表,添加include文件目錄與lib文件目錄。為了工程的通用性,此處配置為相對路徑。
具體配置如下
(2)頭文件
../3rd_x64/HC_vision_SDK_x64/include
(3)庫文件
../3rd_x64/HC_vision_SDK_x64/lib/HCCore.lib ../3rd_x64/HC_vision_SDK_x64/lib/HCNetSDK.lib ../3rd_x64/HC_vision_SDK_x64/lib/PlayCtrl.lib ../3rd_x64/HC_vision_SDK_x64/lib/GdiPlus.lib ../3rd_x64/HC_vision_SDK_x64/lib/HCNetSDKCom/HCAlarm.lib ../3rd_x64/HC_vision_SDK_x64/lib/HCNetSDKCom/HCGeneralCfgMgr.lib ../3rd_x64/HC_vision_SDK_x64/lib/HCNetSDKCom/HCPreview.lib
二、OpenCV下載以及屬性表的添加:
1. 源文件下載、安裝以及庫文件和頭文件的提取:
(1)下載。OpenCV 2.4.13下載地址(不一定是2.4.13,可以根據自己的VS版本選擇合適的版本)
(2)安裝以及相關文件夾說明。此處為了建立的項目能夠通用一些,會將opencv相應函數的實現代碼的頭文件和庫文件提取出來,而不是直接使用1.25 GB 的原opencv安裝文件。下載了安裝包后安裝至自定義的相應路徑(opencv其實本質是一個有很多源碼和相應的編譯文件的SDK包,說是安裝,其實就是把這個包解壓至相應路徑),博主是解壓至G盤,具體路徑是G:\Program\opencv目錄。
此處說明一下,解壓出來后可以看到opencv文件夾下有兩個文件夾,一個是源碼sources文件夾,它里面存放了opencv所有的源程序以及依賴庫的源程序),另一個是Opencv替我們編譯好的build文件夾,待會我們就要將此文件夾下的一些文件拷貝出來以便工程中使用opencv庫。
進入G:\Program\opencv\build\x64文件夾下可以看到vc14這個文件夾,vc14文件夾名的含義主要是指opencv編譯出的庫文件所對應的VC編譯器版本,它是根據各個不同版本的VisualStudio而編譯的文件,其中各個版本的VS對應的VC編譯器版本如下
博主是下載的VC14版本的Opencv 2.4.13(最好自己的Visual Studio版本要和Oencv此處的編譯版本一致,如果不一致可以到我剛剛給出的Opencv的下載地址的上一級目錄查看適配版本下載)。
(3)提取庫文件。進入G:\Program\opencv\build\x64\vc14文件夾下可以看到三個個文件夾:bin文件夾,lib文件夾和staticlib文件夾。其中bin文件夾和lib文件夾下的文件是動態鏈接opencv庫時需要的文件,而staticlib文件夾下的文件是靜態鏈接opencv庫時需要的文件(其中動態鏈接與靜態鏈接的相關概念可以參照如下鏈接:.h頭文件、 .lib庫文件、 .dll動態鏈接庫文件的關系),因為我們此處采用的是動態鏈接,所以只需要bin文件夾和lib文件夾拷貝出來即可。先在C:\Users\yp\Desktop\03_海康威視攝像頭\海康威視_demo\3rd_x64(此處使用的是博主的海康威視項目的路徑)下新建一個名為opencv-x64的庫,並在這個文件夾下新建一個lib文件夾,將剛剛bin文件夾和lib文件夾拷貝至此lib文件夾下。
(4)提取頭文件。將G:\Program\opencv\build下的include文件夾拷貝出來,再復制到剛剛新建的opencv-x64文件夾下。
至此,opencv的提取工作完畢,接下來配置opencv的屬性表。
2.補充屬性表內容:
和剛剛新建海康威視SDK的屬性表一樣,不過此處我們直接在剛剛新添加HC_x64_release.prosp屬性表中添加opencv的相關配置,並將屬性表改名為HC_OpenCV_x64_release.prosp。
(1)頭文件
————————————————
../3rd_x64/opencv-x64/include ../3rd_x64/opencv-x64/include/opencv ../3rd_x64/opencv-x64/include/opencv2
(2)庫文件
../3rd_x64/opencv-x64/lib/release/opencv_ml2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_objdetect2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_ts2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_video2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_nonfree2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_ocl2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_photo2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_stitching2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_superres2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_videostab2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_calib3d2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_contrib2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_core2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_features2d2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_flann2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_gpu2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_highgui2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_imgproc2413.lib ../3rd_x64/opencv-x64/lib/release/opencv_legacy2413.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
三、海康攝像頭碼流轉碼並同通過OpenCV顯示:
注:此處代碼參考博客 海康攝像頭實時讀取+opencv顯示 和博客 OpenCV+海康威視攝像頭的實時讀取 以及博客
捕獲海康威視IPCamera圖像,轉成OpenCV可以處理的圖像(二)
1.代碼:
(1)新建一個頭文件HK_camera.h:定義了一個相機類
#ifndef _HK_CAMERA_H_ #define _HK_CAMERA_H_ #include<HCNetSDK.h> #include<plaympeg4.h> #include<PlayM4.h> //此頭文件需要按照下面第二步調試Bug中的方法去添加 #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #include <opencv2\imgproc\imgproc.hpp> using namespace cv; using namespace std; class HK_camera { public: HK_camera(void); ~HK_camera(void); public: bool Init(); //初始化 bool Login(char* sDeviceAddress, char* sUserName, char* sPassword, WORD wPort); //登陸 //bool Login(const char* sDeviceAddress,const char* sUserName,const char* sPassword, WORD wPort); //登陸(VS2017版本) void show(); //顯示圖像 private: LONG lUserID; }; #endif;
(2)新建一個HK_camera.cpp
//#include "stdafx.h" //VS2017中需要添加此預編譯頭文件 #include"HK_camera.h" #include <iostream> //全局變量 LONG g_nPort; Mat g_BGRImage; //數據解碼回調函數, //功能:將YV_12格式的視頻數據流轉碼為可供opencv處理的BGR類型的圖片數據,並實時顯示。 void CALLBACK DecCBFun(long nPort, char* pBuf, long nSize, FRAME_INFO* pFrameInfo, long nUser, long nReserved2) { if (pFrameInfo->nType == T_YV12) { std::cout << "the frame infomation is T_YV12" << std::endl; if (g_BGRImage.empty()) { g_BGRImage.create(pFrameInfo->nHeight, pFrameInfo->nWidth, CV_8UC3); } Mat YUVImage(pFrameInfo->nHeight + pFrameInfo->nHeight / 2, pFrameInfo->nWidth, CV_8UC1, (unsigned char*)pBuf); cvtColor(YUVImage, g_BGRImage, COLOR_YUV2BGR_YV12); imshow("RGBImage1", g_BGRImage); waitKey(15); YUVImage.~Mat(); } } //實時視頻碼流數據獲取 回調函數 void CALLBACK g_RealDataCallBack_V30(LONG lPlayHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize, void* pUser) { if (dwDataType == NET_DVR_STREAMDATA)//碼流數據 { if (dwBufSize > 0 && g_nPort != -1) { if (!PlayM4_InputData(g_nPort, pBuffer, dwBufSize)) { std::cout << "fail input data" << std::endl; } else { std::cout << "success input data" << std::endl; } } } } //構造函數 HK_camera::HK_camera(void) { } //析構函數 HK_camera::~HK_camera(void) { } //初始化函數,用作初始化狀態檢測 bool HK_camera::Init() { if (NET_DVR_Init()) { return true; } else { return false; } } //登錄函數,用作攝像頭id以及密碼輸入登錄 bool HK_camera::Login(char* sDeviceAddress, char* sUserName, char* sPassword, WORD wPort) //bool HK_camera::Login(const char* sDeviceAddress,const char* sUserName,const char* sPassword, WORD wPort); //登陸(VS2017版本) { NET_DVR_USER_LOGIN_INFO pLoginInfo = { 0 }; NET_DVR_DEVICEINFO_V40 lpDeviceInfo = { 0 }; pLoginInfo.bUseAsynLogin = 0; //同步登錄方式 strcpy_s(pLoginInfo.sDeviceAddress, sDeviceAddress); strcpy_s(pLoginInfo.sUserName, sUserName); strcpy_s(pLoginInfo.sPassword, sPassword); pLoginInfo.wPort = wPort; lUserID = NET_DVR_Login_V40(&pLoginInfo, &lpDeviceInfo); if (lUserID < 0) { return false; } else { return true; } } //視頻流顯示函數 void HK_camera::show() { if (PlayM4_GetPort(&g_nPort)) //獲取播放庫通道號 { if (PlayM4_SetStreamOpenMode(g_nPort, STREAME_REALTIME)) //設置流模式 { if (PlayM4_OpenStream(g_nPort, NULL, 0, 1024 * 1024)) //打開流 { if (PlayM4_SetDecCallBackExMend(g_nPort, DecCBFun, NULL, 0, NULL)) { if (PlayM4_Play(g_nPort, NULL)) { std::cout << "success to set play mode" << std::endl; } else { std::cout << "fail to set play mode" << std::endl; } } else { std::cout << "fail to set dec callback " << std::endl; } } else { std::cout << "fail to open stream" << std::endl; } } else { std::cout << "fail to set stream open mode" << std::endl; } } else { std::cout << "fail to get port" << std::endl; } //啟動預覽並設置回調數據流 NET_DVR_PREVIEWINFO struPlayInfo = { 0 }; struPlayInfo.hPlayWnd = NULL; //窗口為空,設備SDK不解碼只取流 struPlayInfo.lChannel = 1; //Channel number 設備通道 struPlayInfo.dwStreamType = 0;// 碼流類型,0-主碼流,1-子碼流,2-碼流3,3-碼流4, 4-碼流5,5-碼流6,7-碼流7,8-碼流8,9-碼流9,10-碼流10 struPlayInfo.dwLinkMode = 0;// 0:TCP方式,1:UDP方式,2:多播方式,3 - RTP方式,4-RTP/RTSP,5-RSTP/HTTP struPlayInfo.bBlocked = 1; //0-非阻塞取流, 1-阻塞取流, 如果阻塞SDK內部connect失敗將會有5s的超時才能夠返回,不適合於輪詢取流操作. if (NET_DVR_RealPlay_V40(lUserID, &struPlayInfo, g_RealDataCallBack_V30, NULL)) { namedWindow("RGBImage2"); } }
(3)新建一個main.cpp
//#include "stdafx.h" //VS2017中需要添加此預編譯頭文件 #include"HK_camera.h" #include <iostream> #include <Windows.h> using namespace std; int main() { HK_camera camera; if (camera.Init()) { cout << "init success" << endl; if (camera.Login("192.168.1.64", "admin", "sjtu2322", 8000))//用戶名以及密碼,根據此系列博客一中的方法查看或設置 { cout << "login successfully" << endl; camera.show(); } else { cout << "login fail" << endl; } } else { cout << "init fail" << endl; } while (1) { } return 0; }
2.Bug調試
提示bug:E1696無法打開源文件 "PlayM4.h",解決辦法:到\CH-HCNetSDK(Windows64)V5.3.1.22_build20170909\Demo示例\2- MFC分功能示例\2- 實時流回調解碼獲取YUV\文件夾下找到PlayM4.h文件,添加到\海康威視_demo\3rd_x64\HC_vision_SDK_x64\include 文件夾下
因為我此處使用的是VS2017,會報錯 C2664 無法將參數 1 從“const char [13]”轉換為“char *”,參照博客 無法將參數1從“const char [6]”轉換為“char *”的解決方法中所說,將上述代碼中的報錯的幾處改動一下即可(在上述代碼中都有注釋)。主要是
(1)將HK_camera.h中函數bool Login(char* sDeviceAddress, char* sUserName, char* sPassword, WORD wPort);改為函數bool Login(const char* sDeviceAddress,const char* sUserName,const char* sPassword, WORD wPort); (2)將 HK_camera.cpp中函數bool HK_camera::Login(char* sDeviceAddress, char* sUserName, char* sPassword, WORD wPort) 改為函數bool HK_camera::Login(const char* sDeviceAddress,const char* sUserName,const char* sPassword, WORD wPort); ————————————————
並且因為VS版本問題,需要在所有.cpp文件的頭部添加預編譯頭#include "stdafx.h"
,這個已經在上面代碼中注明,如果是VS2015或其他版本,則無此問題。
四、小結:
本篇博客中我們介紹了用海康威視SDK和OpeCV庫將海康威視攝像頭封裝為一個攝像機類,並且在此基礎上在主函數中創建了這個類的實例並調用它的函數顯示圖像。接下來下一篇博客我們將在此基礎上封裝人臉檢測的算法,完成一個基於海康威視攝像頭的人臉檢測的小測試工程的創建。