OpenCV_海康威视SDK_VS2012配置及实时预览(非海康(其他)网络摄像头IPC)二次开发

OpenCV_海康威视SDK_VS(Visual Studio)2012配置及实时预览(非海康(其他)网络摄像头IPC)二次开发

Python 版本的实现在这篇博客 ❤ o( ̄▽ ̄)d
https://blog.csdn.net/zuliang001/article/details/80882524

下载准备

  1. OpenCV
    https://opencv.org/releases.html (找到如下版本下载,因为我发现新的一些版本不支持VS2012)
    OpenCV
  2. 海康威视SDK
    http://www.hikvision.com/cn/download_61.html
    下载“设备网络SDK_Win32 ”和“播放库SDK_Windows ”(均下载32位的,因为要使用VS的32位编译器,即便Windows系统是64位的。我只调通了32位编译器的工程,所以很遗憾只能给大家介绍32位的啦o(╥﹏╥)o)
    hikvisionDownload
  3. VS2012,为了减少篇幅略去,自行度娘。

配置前的小插曲(以此判断是否可以读到摄像头)

  1. 使用SDK中的SADP工具,可以识别摄像头,配置IP与电脑在同一网段。
  2. 使用SDK中的ClientDemo.exe访问摄像头(添加你的摄像头,可以看到画面啦,激动٩(๑>◡<๑)۶)

正式配置开发环境

1. OpenCV的配置

1.1 在用户变量里新建变量OpenCV,变量值:C:\SDK\opencv\build;
OpenCV配置1
1.2 在用户变量的Path中添加:C:\SDK\opencv\build\x86\vc11\bin;
OpenCV配置2
(另,在OpenCV配置中,vc11即对应VS2012,vc12对应的是VS2013。这里x86还是x64的选择跟你的电脑是32位还是64位无关,这里我使用vs2012编译环境为win32编译器,所以选择x86。)

1.3 在系统变量中的Path中也加上;
OpenCV配置3(另,要使用英文输入下的分号和前面已有的路径分开,添加完之后需要重启或注销计算机,环境变量才会生效。)

1.4 VS2012的工程项目属性配置
新建Win32控制台应用程序,工程名命名为MyFirstOpenCV,在其后的选项里选择空项目:
OpenCV配置4
OpenCV配置5
打开“属性管理器”,在属性管理器的Debug|Win32目录上右键单击选择“添加新项目属性表”,新建属性表,并命名为OpenCVDebug
OpenCV配置6
OpenCV配置7
OpenCV配置8双击打开属性表OpenCVDebug.props。选择通用属性->VC++目录,在包含目录里添加3个目录:
OpenCV配置9在VC++目录下,在库目录里添加1个目录:C:\SDK\opencv\build\x86\vc11\lib
OpenCV配置10选择通用属性->链接器->输入->附加依赖项,在附加依赖项里添加库文件:

opencv_ml2413d.lib

opencv_calib3d2413d.lib

opencv_contrib2413d.lib

opencv_core2413d.lib

opencv_features2d2413d.lib

opencv_flann2413d.lib

opencv_gpu2413d.lib

opencv_highgui2413d.lib

opencv_imgproc2413d.lib

opencv_legacy2413d.lib

opencv_objdetect2413d.lib

opencv_ts2413d.lib

opencv_video2413d.lib

opencv_nonfree2413d.lib

opencv_ocl2413d.lib

opencv_photo2413d.lib

opencv_stitching2413d.lib

opencv_superres2413d.lib

opencv_videostab2413d.lib

OpenCV配置11
OpenCV项目测试程序:
OpenCV配置12
OpenCV配置13
OpenCV配置14

#include<iostream>  
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  

using namespace cv;  


    int main()  
    {  
        // 读入一张图片(游戏原画)特别注意路径中用的是双斜杠\\  
        Mat img=imread("C:\\Users\\JulianYang\\Desktop\\picture.jpg");  
        // 创建一个名为 "游戏原画"窗口  
        cvNamedWindow("游戏原画");  
        // 在窗口中显示游戏原画  
        imshow("游戏原画",img);  
        // 等待6000 ms后窗口自动关闭  
        waitKey(6000);  
    }

2. 海康SDK的配置

添加新项目属性表,设置海康威视sdk的属性,添加头文件、库文件、附加依赖项:
hikvision1
hikvision2
hikvision3

PlayCtrl.lib
GdiPlus.lib
HCCore.lib
HCNetSDK.lib
HCAlarm.lib
HCGeneralCfgMgr.lib
HCPreview.lib

测试

#include <cstdio>  
#include <cstring>  
#include <iostream>  
#include "Windows.h"  
#include "HCNetSDK.h"  
#include "PlayM4.h"  
#include <opencv2\opencv.hpp>  
#include "cv.h"  
#include "highgui.h"  
#include <time.h>  
#define USECOLOR 1  
using namespace std;  
using namespace std;  

//--------------------------------------------  
int iPicNum=0;//Set channel NO.  
LONG nPort=-1;  
HWND hWnd=NULL; 


void yv12toYUV(char *outYuv, char *inYv12, int width, int height,int widthStep)  
{  
   int col,row;  
   unsigned int Y,U,V;  
   int tmp;  
   int idx;  

  //printf("widthStep=%d.\n",widthStep);  

   for (row=0; row<height; row++)  
   {  
      idx=row * widthStep;  
      int rowptr=row*width;  

      for (col=0; col<width; col++)  
      {  
         //int colhalf=col>>1;  
         tmp = (row/2)*(width/2)+(col/2);  
//         if((row==1)&&( col>=1400 &&col<=1600))  
//         {   
//          printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp);  
//          printf("row*width+col=%d,width*height+width*height/4+tmp=%d,width*height+tmp=%d.\n",row*width+col,width*height+width*height/4+tmp,width*height+tmp);  
//         }   
         Y=(unsigned int) inYv12[row*width+col];  
         U=(unsigned int) inYv12[width*height+width*height/4+tmp];  
         V=(unsigned int) inYv12[width*height+tmp];  
//         if ((col==200))  
//         {   
//         printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp);  
//         printf("width*height+width*height/4+tmp=%d.\n",width*height+width*height/4+tmp);  
//         return ;  
//         }  
         if((idx+col*3+2)> (1200 * widthStep))  
         {  
          //printf("row * widthStep=%d,idx+col*3+2=%d.\n",1200 * widthStep,idx+col*3+2);  
         }   
         outYuv[idx+col*3]   = Y;  
         outYuv[idx+col*3+1] = U;  
         outYuv[idx+col*3+2] = V;  
      }  
   }  
   //printf("col=%d,row=%d.\n",col,row);  
}  



//解码回调 视频为YUV数据(YV12),音频为PCM数据  
//void CALLBACK DecCBFun(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, void * nReserved1,void * nReserved2)  
void CALLBACK DecCBFun(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2)  
{  
    long lFrameType = pFrameInfo->nType;   

    if(lFrameType ==T_YV12)  
    {  
#if USECOLOR  
    //int start = clock();  
    IplImage* pImgYCrCb = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);//得到图像的Y分量    
    yv12toYUV(pImgYCrCb->imageData, pBuf, pFrameInfo->nWidth,pFrameInfo->nHeight,pImgYCrCb->widthStep);//得到全部RGB图像  
    IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);    
    cvCvtColor(pImgYCrCb,pImg,CV_YCrCb2RGB);    
    //int end = clock();  
#else  
    IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 1);    
    memcpy(pImg->imageData,pBuf,pFrameInfo->nWidth*pFrameInfo->nHeight);   
#endif  
    //printf("%d\n",end-start);  
    cvShowImage("IPCamera",pImg);  
    cvWaitKey(1);  
#if USECOLOR  
    cvReleaseImage(&pImgYCrCb);  
    cvReleaseImage(&pImg);  
#else  
    cvReleaseImage(&pImg);  
#endif  
    //此时是YV12格式的视频数据,保存在pBuf中,可以fwrite(pBuf,nSize,1,Videofile);  
    //fwrite(pBuf,nSize,1,fp);  
    }  
    /*************** 
    else if (lFrameType ==T_AUDIO16) 
    { 
        //此时是音频数据,数据保存在pBuf中,可以fwrite(pBuf,nSize,1,Audiofile); 

    } 
    else 
    { 

    } 
    *******************/  

}  


///实时流回调  
void CALLBACK fRealDataCallBack(LONG lRealHandle,DWORD dwDataType,BYTE *pBuffer,DWORD dwBufSize,void *pUser)  
{  
    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);  

  //---------------------------------------  
  // 获取控制台窗口句柄  
  //HMODULE hKernel32 = GetModuleHandle((LPCWSTR)"kernel32");  
  //GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow");  

  //---------------------------------------  
  // 注册设备(这里要修改IP、账号、密码等等哦~)  
  LONG lUserID;  
  NET_DVR_DEVICEINFO_V30 struDeviceInfo;  
  lUserID = NET_DVR_Login_V30("192.168.1.64", 8000, "admin", "admin12345", &struDeviceInfo);  
  if (lUserID < 0)  
  {  
       printf("Login error, %d\n", NET_DVR_GetLastError());  
       NET_DVR_Cleanup();  
       return;  
  }  

  //---------------------------------------  
  //设置异常消息回调函数  
  NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL);  


  //cvNamedWindow("IPCamera");  
  //---------------------------------------  
  //启动预览并设置回调数据流   
  NET_DVR_CLIENTINFO ClientInfo;  
  ClientInfo.lChannel = 1;        //Channel number 设备通道号  
  ClientInfo.hPlayWnd = NULL;     //窗口为空,设备SDK不解码只取流  
  ClientInfo.lLinkMode = 0;       //Main Stream  
  ClientInfo.sMultiCastIP = NULL;  

  LONG lRealPlayHandle;  
  lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID,&ClientInfo,fRealDataCallBack,NULL,TRUE);  
  if (lRealPlayHandle<0)  
  {  
    printf("NET_DVR_RealPlay_V30 failed! Error number: %d\n",NET_DVR_GetLastError());  
    return;  
  }  

  //cvWaitKey(0);  
  Sleep(-1);  

  //fclose(fp);  
  //---------------------------------------  
  //关闭预览  
  if(!NET_DVR_StopRealPlay(lRealPlayHandle))  
  {  
    printf("NET_DVR_StopRealPlay error! Error number: %d\n",NET_DVR_GetLastError());  
    return;  
  }  
  //注销用户  
  NET_DVR_Logout(lUserID);  
  NET_DVR_Cleanup();  

  return;  
} 

final

参考

  1. OpenCV2.4.13+VS2012开发环境配置 - CSDN博客 http://blog.csdn.net/dcrmg/article/details/51809614
  2. OpenCV+海康威视摄像头的实时读取 - CSDN博客 http://blog.csdn.net/lonelyrains/article/details/50350052
  3. MFC(vs2013)+opencv+海康SDK_显示视频教程 - CSDN博客 http://blog.csdn.net/naibozhuan3744/article/details/78561745

✿✿ヽ(°▽°)ノ✿完结撒花!

FAQs

  1. 错误:“由于找不到HCNetSDK.dll,无法继续执行代码。重新安装程序可能会解决此问题。”
    question1
    方案:将调用的dll文件全部复制到
    (32位系统的话)C:\Windows\System32
    (64位系统的话)C:\Windows\SysWOW64

猜你喜欢

转载自blog.csdn.net/zuliang001/article/details/78621456