海康威視攝像頭+OpenCV+VS2017 圖像處理小結(二 海康威視攝像頭+OpenCV+VS2017 圖像處理小結(二)

海康威視攝像頭+OpenCV+VS2017 圖像處理小結(二)


系列博客———————-海康威視攝像頭+OpenCV+VS2017 圖像處理小結(一)

第二篇
先介紹海康威視SDK的配置;
接着介紹並提取OpenCV庫的頭文件以及庫文件供工程使用,期間還演示瞭如何配置屬性表;
最後將海康威視的SDK進行封裝,封裝成HK_camera類,並在主函數中生成並調用這個類的實例。


目錄


一、海康威視SDK下載以及VS工程配置:

1. 下載海康威視SDK:

海康威視SDK下載地址(32位或者64位根據各自工程需求下載,博主此處下載的是64位)

海康威視SDK下載

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編譯器版本如下

Visual Studio版本 vc版本
Visual Studio 2008 vc9
Visual Studio 2010 vc10
Visual Studio 2012 vc11
Visual Studio 2013 vc12
Visual Studio 2015 vc14
Visual Studio 2017 vc15

,博主是下載的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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

(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");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147

(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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

2.Bug調試

  1. 提示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 文件夾下
    這裏寫圖片描述

  2. 因爲我此處使用的是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或其他版本,則無此問題。

3.程序運行效果:

這裏寫圖片描述

四、小結:

本篇博客中我們介紹了用海康威視SDK和OpeCV庫將海康威視攝像頭封裝爲一個攝像機類,並且在此基礎上在主函數中創建了這個類的實例並調用它的函數顯示圖像。接下來下一篇博客我們將在此基礎上封裝人臉檢測的算法,完成一個基於海康威視攝像頭的人臉檢測的小測試工程的創建。


【1】海康威視攝像頭+OpenCV+VS2017 圖像處理小結(一)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章