在Ubuntu下使用opencv调用海康威视的网络摄像头

经过很多天的配置,终于能在工程中调用海康威视的网络摄像头了,为了后人能快速上手,我整理内容如下:


在本文中我的电脑是使用的Ubuntu16.04 64位,使用工具是QT5.7.1,opencv2.4.9.
一、根据电脑的型号下载海康威视的SDK包
网址:http://www.hikvision.com/cn/download_61.html
我的笔记本时linux64位的,所以下载的 ————设备网络SDK_Linux64
二、 用下面的方法之一配置SDK
如果HCNetSDKCom目录以及libhcnetsdk.so、libhpr.so、libHCCore文件和可执行文件在同一级目录下,则使用同级目录下的库文件;
如果不在同一级目录下,则需要将以上文件的目录加载到动态库搜索路径中,设置的方式有以下几种:
1.    将网络SDK各动态库路径加入到LD_LIBRARY_PATH环境变量
    1.在终端输入:export  LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/XXX:/XXX/HCNetSDKCom      只在当前终端起作用
    2. 修改~/.bashrc或~/.bash_profile,最后一行添加 export  LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/XXX:/XXX/HCNetSDKCom,保存之后,使用source  .bashrc执行该文件 ,当前用户生效
    3. 修改/etc/profile,添加内容如第2条,同样保存之后使用source执行该文件  所有用户生效
 

2.在/etc/ld.so.conf文件结尾添加网络sdk库的路径,如/XXX和/XXX/HCNetSDKCom/,保存之后,然后执行ldconfig。

三. 在Ubuntu16.04 的qt中新建一个工程
1.  在工程的 ×.pro文件中添加以下内容:

INCLUDEPATH += /usr/local/include \
/usr/local/include/opencv \
/usr/local/include/opencv2

LIBS += /usr/local/lib/libopencv_calib3d.so\
        /usr/local/lib/libopencv_ml.so.2.4.9\
        /usr/local/lib/libopencv_calib3d.so.2.4 \
        /usr/local/lib/libopencv_nonfree.so\
        /usr/local/lib/libopencv_calib3d.so.2.4.9  \
        /usr/local/lib/libopencv_nonfree.so.2.4\
        /usr/local/lib/libopencv_contrib.so    \
        /usr/local/lib/libopencv_nonfree.so.2.4.9\
        /usr/local/lib/libopencv_contrib.so.2.4    \
        /usr/local/lib/libopencv_objdetect.so\
        /usr/local/lib/libopencv_contrib.so.2.4.9 \
        /usr/local/lib/libopencv_objdetect.so.2.4\
        /usr/local/lib/libopencv_core.so\
        /usr/local/lib/libopencv_objdetect.so.2.4.9\
        /usr/local/lib/libopencv_core.so.2.4 \
        /usr/local/lib/libopencv_ocl.so\
        /usr/local/lib/libopencv_core.so.2.4.9 \
        /usr/local/lib/libopencv_ocl.so.2.4\
        /usr/local/lib/libopencv_features2d.so \
        /usr/local/lib/libopencv_ocl.so.2.4.9\
        /usr/local/lib/libopencv_features2d.so.2.4  \
        /usr/local/lib/libopencv_photo.so\
        /usr/local/lib/libopencv_features2d.so.2.4.9 \
        /usr/local/lib/libopencv_photo.so.2.4\
        /usr/local/lib/libopencv_flann.so  \
        /usr/local/lib/libopencv_photo.so.2.4.9\
        /usr/local/lib/libopencv_flann.so.2.4   \
        /usr/local/lib/libopencv_stitching.so\
        /usr/local/lib/libopencv_flann.so.2.4.9  \
        /usr/local/lib/libopencv_stitching.so.2.4\
        /usr/local/lib/libopencv_gpu.so     \
        /usr/local/lib/libopencv_stitching.so.2.4.9\
        /usr/local/lib/libopencv_gpu.so.2.4   \
        /usr/local/lib/libopencv_superres.so\
        /usr/local/lib/libopencv_gpu.so.2.4.9 \
        /usr/local/lib/libopencv_superres.so.2.4\
        /usr/local/lib/libopencv_highgui.so   \
        /usr/local/lib/libopencv_superres.so.2.4.9\
        /usr/local/lib/libopencv_highgui.so.2.4   \
        /usr/local/lib/libopencv_highgui.so.2.4.9 \
        /usr/local/lib/libopencv_video.so\
        /usr/local/lib/libopencv_imgproc.so  \
        /usr/local/lib/libopencv_video.so.2.4\
        /usr/local/lib/libopencv_imgproc.so.2.4 \
        /usr/local/lib/libopencv_video.so.2.4.9\
        /usr/local/lib/libopencv_imgproc.so.2.4.9\
        /usr/local/lib/libopencv_videostab.so\
        /usr/local/lib/libopencv_legacy.so \
        /usr/local/lib/libopencv_videostab.so.2.4\
        /usr/local/lib/libopencv_legacy.so.2.4  \
        /usr/local/lib/libopencv_videostab.so.2.4.9\
        /usr/local/lib/libopencv_legacy.so.2.4.9  \
        /usr/local/lib/libopencv_ml.so

INCLUDEPATH += /home/ding/opencv_projects/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/incCn


LIBS += /home/ding/opencv_projects/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/lib/libhcnetsdk.so\
        /home/ding/opencv_projects/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/lib/libHCCore.so\
        /home/ding/opencv_projects/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/lib/libhpr.so\
        /home/ding/opencv_projects/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/lib/libPlayCtrl.so\
        /home/ding/opencv_projects/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/lib/libSuperRender.so\
        /home/ding/opencv_projects/CH_HCNetSDK_V5.2.7.4_build20170606_Linux64/lib/libAudioRender.so
2. 在main.cpp函数中添加以下内容:

#include "opencv2/opencv.hpp"

#include <QDir>
#include <fstream>
#include <unistd.h>
//#include "auto_entercs.h"

#include "HCNetSDK.h"
#include "PlayM4.h"
#include "LinuxPlayM4.h"

#define HPR_ERROR       -1
#define HPR_OK               0
#define USECOLOR          0

static cv::Mat dst;
HWND h = NULL;
LONG nPort=-1;
LONG lUserID;

pthread_mutex_t mutex;
std::list<cv::Mat> g_frameList;


FILE *g_pFile = NULL;

void CALLBACK PsDataCallBack(LONG lRealHandle, DWORD dwDataType,BYTE *pPacketBuffer,DWORD nPacketSize, void* pUser)
{

   if (dwDataType  == NET_DVR_SYSHEAD)
   {
       //写入头数据
       g_pFile = fopen("/home/lds/source/ps.dat", "wb");

       if (g_pFile == NULL)
       {
           printf("CreateFileHead fail\n");
           return;
       }

       //写入头数据
       fwrite(pPacketBuffer, sizeof(unsigned char), nPacketSize, g_pFile);
       printf("write head len=%d\n", nPacketSize);
   }
   else
   {
       if(g_pFile != NULL)
       {
           fwrite(pPacketBuffer, sizeof(unsigned char), nPacketSize, g_pFile);
           printf("write data len=%d\n", nPacketSize);
       }
   }

}

//void CALLBACK DecCBFun(LONG nPort, char *pBuf, LONG nSize, FRAME_INFO *pFrameInfo, LONG nReserved1, LONG nReserved2)
void CALLBACK DecCBFun(LONG nPort, char *pBuf, LONG nSize, FRAME_INFO *pFrameInfo, void* nReserved1, LONG nReserved2)
{
   long lFrameType = pFrameInfo->nType;

     if (lFrameType == T_YV12)
     {
      //cv::Mat dst(pFrameInfo->nHeight, pFrameInfo->nWidth,
      //            CV_8UC3);  // 8UC3表示8bit uchar无符号类型,3通道值
           dst.create(pFrameInfo->nHeight, pFrameInfo->nWidth,
                 CV_8UC3);

           cv::Mat src(pFrameInfo->nHeight + pFrameInfo->nHeight / 2, pFrameInfo->nWidth, CV_8UC1, (uchar *)pBuf);
           cv::cvtColor(src, dst, CV_YUV2BGR_YV12);
           pthread_mutex_lock(&mutex);
           g_frameList.push_back(dst);
           pthread_mutex_unlock(&mutex);
     }
    usleep(1000);

   //cv::Mat src(pFrameInfo->nHeight + pFrameInfo->nHeight / 2, pFrameInfo->nWidth, CV_8UC1, (uchar *)pBuf);
   //cv::cvtColor(src, dst, CV_YUV2BGR_YV12);
   //cv::imshow("bgr", dst);
   //pthread_mutex_lock(&mutex);
   //g_frameList.push_back(dst);
   //pthread_mutex_unlock(&mutex);
   //vw << dst;
   //cv::waitKey(10);

}

void CALLBACK g_RealDataCallBack_V30(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer, DWORD dwBufSize,void* dwUser)
{
   /*
   if (dwDataType == 1)
   {
       PlayM4_GetPort(&nPort);
       PlayM4_SetStreamOpenMode(nPort, STREAME_REALTIME);
       PlayM4_OpenStream(nPort, pBuffer, dwBufSize, 1024 * 1024);
       PlayM4_SetDecCallBackEx(nPort, DecCBFun, NULL, NULL);
       PlayM4_Play(nPort, h);
   }
   else
   {
       BOOL inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);
   }*/
   DWORD dRet;
   switch (dwDataType)
   {
     case NET_DVR_SYSHEAD:           //系统头
       if (!PlayM4_GetPort(&nPort))  //获取播放库未使用的通道号
       {
         break;
       }
       if (dwBufSize > 0) {
         if (!PlayM4_SetStreamOpenMode(nPort, STREAME_REALTIME)) {
           dRet = PlayM4_GetLastError(nPort);
           break;
         }
         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, h))
         {
           dRet = PlayM4_GetLastError(nPort);
           break;
         }

         //打开音频解码, 需要码流是复合流
         if (!PlayM4_PlaySound(nPort)) {
           dRet = PlayM4_GetLastError(nPort);
           break;
         }
       }
       break;
       //usleep(500);
     case NET_DVR_STREAMDATA:  //码流数据
       if (dwBufSize > 0 && nPort != -1) {
         BOOL inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);
         while (!inData) {
           sleep(100);
           inData = PlayM4_InputData(nPort, pBuffer, dwBufSize);
           std::cerr << "PlayM4_InputData failed \n" << std::endl;
         }
       }
       break;
   }
}

void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)
{
   char tempbuf[256] = {0};
   std::cout << "EXCEPTION_RECONNECT = " << EXCEPTION_RECONNECT << std::endl;
   switch(dwType)
   {
   case EXCEPTION_RECONNECT:	//预览时重连
       printf("pyd----------reconnect--------%d\n", time(NULL));
       break;
   default:
       break;
   }
}

void *RunIPCameraInfo(void *)
{
   char IP[]         = "192.168.**.***";   //海康威视网络摄像头的ip
   char UName[] = "****";                 //海康威视网络摄像头的用户名
   char PSW[]      = "*****";           //海康威视网络摄像头的密码
   NET_DVR_Init();
   NET_DVR_SetConnectTime(2000, 1);
   NET_DVR_SetReconnect(1000, true);
   NET_DVR_SetLogToFile(3, "./sdkLog");
   NET_DVR_DEVICEINFO_V30 struDeviceInfo = {0};
   NET_DVR_SetRecvTimeOut(5000);
   lUserID = NET_DVR_Login_V30(IP, 8000, UName, PSW, &struDeviceInfo);

   NET_DVR_SetExceptionCallBack_V30(0, NULL, g_ExceptionCallBack, NULL);

   long lRealPlayHandle;
   NET_DVR_CLIENTINFO ClientInfo = {0};

   ClientInfo.lChannel       = 1;
   ClientInfo.lLinkMode     = 0;
   ClientInfo.hPlayWnd     = 0;
   ClientInfo.sMultiCastIP = NULL;


   //lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, PsDataCallBack, NULL, 0);
   lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, g_RealDataCallBack_V30, NULL, 0);
   //NET_DVR_SaveRealData(lRealPlayHandle, "/home/lds/source/yuntai.mp4");
   if (lRealPlayHandle < 0)
   {
       printf("pyd1---NET_DVR_RealPlay_V30 error\n");
   }
   sleep(-1);

   NET_DVR_Cleanup();
}

int main(int argc, char *argv[])
{

   pthread_t getframe;

   pthread_mutex_init(&mutex, NULL);
   int ret;

   ret = pthread_create(&getframe, NULL, RunIPCameraInfo, NULL);


   if(ret!=0)
   {
       printf("Create pthread error!\n");
   }

   cv::Mat image;
   while(1)
   {
       pthread_mutex_lock(&mutex);
       if(g_frameList.size())
       {
           std::list<cv::Mat>::iterator it;
           it = g_frameList.end();
           it--;
           image = (*(it));
           if (!image.empty())
           {
               imshow("frame from camera",image);
               cv::waitKey(1);
           }
           g_frameList.pop_front();
       }
       g_frameList.clear(); // 丢掉旧的帧
       pthread_mutex_unlock(&mutex);
   }

   return 0;
}


阅读更多
换一批

没有更多推荐了,返回首页