海康威视摄像头+OpenCV+VS 图像处理小结(二)

时间:2024-01-29 16:13:33

海康威视摄像头+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库将海康威视摄像头封装为一个摄像机类,并且在此基础上在主函数中创建了这个类的实例并调用它的函数显示图像。接下来下一篇博客我们将在此基础上封装人脸检测的算法,完成一个基于海康威视摄像头的人脸检测的小测试工程的创建。