如何将海康高清摄像机转成opencv可以处理的格式?

环境:Red Hat Enterprise linux As5
SDK版本: CH-HCNetSDK(Linux)4.0.2.7
OpenCv:2.2.0
将控制台演示代码的 GetStream.cpp 覆盖为以下,就能转换成 IplImage 内存数据,IplImage *img 是YUV格式,IplImage *imgBgr 是BGR格式:

/*
* Copyright(C) 2010,Hikvision Digital Technology Co., Ltd 
* 
* File   name:GetStream.cpp
* Discription:
* Version    :1.0
* Author     :panyd
* Create Date:2010_3_25
* Modification History:
*/

#ifdef _WIN32
#include <windows.h>
#elif defined(__linux__)
#include   <unistd.h> 
#endif

#include "HCNetSDK.h"
#include "public.h"
#include <stdio.h>
#include <time.h>
#include "playsdkpu.h"
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>

int lPort;

void yv12toYUV(char *outYuv, char *inYv12, int width, int height,int widthStep)
{
   int col,row;
   unsigned int Y,U,V;
   int tmp;
   int idx;
//   unsigned int red,blue,green;
  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);
}



void CALLBACK g_DecCBFun(int nPort,char * pBuf,int nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2)
{
  
  printf("call g_DecCBFun suceess.\n");
  printf("nPort=%d,nSize=%d,pFrameInfo.nWidth=%ld,pFrameInfo.nHeight=%ld,\
  pFrameInfo.nStamp=%ld,pFrameInfo.nType=%ld,pFrameInfo.nFrameRate=%ld.\n", 
    nPort,nSize,pFrameInfo->nWidth,pFrameInfo->nHeight,
    pFrameInfo->nStamp,pFrameInfo->nType,pFrameInfo->nFrameRate);
  
  switch (pFrameInfo->nType)
  {
    case T_AUDIO16: //音频数据
      printf("pFrameInfo.nType is T_AUDIO16.\n");
      break;
    case T_RGB32: //系统头
      printf("pFrameInfo.nType is T_RGB32.\n");
      break;    
    case T_UYVY: //系统头
      printf("pFrameInfo.nType is T_UYVY.\n");
      break;    
    case T_YV12: //系统头      
      printf("pFrameInfo.nType is T_YV12.\n");
      break;      
    default :
      printf("Error pFrameInfo.nType.\n");
      break;
      
  }
  
  IplImage *img = cvCreateImage(cvSize(1600, 1200), IPL_DEPTH_8U, 3); 
printf("img->imageSize=%d.\n",img->imageSize);
printf("cvCreateImage sucess.\n");
    CvScalar scal; 
    scal = cvGet2D(img,1199,1599);//获取像素点
    
    double valY = scal.val[0];
    double valU = scal.val[1];
    double valV = scal.val[2];
printf("valY=%e, valU=%e,valV=%e.\n",valY,valU,valV);

  yv12toYUV(img->imageData, pBuf, 1600, 1200,img->widthStep);
printf("yv12toYUV sucess.\n");
    scal = cvGet2D(img,1199,1599);//获取像素点
    
    valY = scal.val[0];
    valU = scal.val[1];
    valV = scal.val[2];
printf("valY=%e, valU=%e,valV=%e.\n",valY,valU,valV);

  IplImage *imgBgr = cvCreateImage(cvSize(1600, 1200), IPL_DEPTH_8U, 3);
printf("imgBgr->imageSize=%d.\n",imgBgr->imageSize);   
  cvCvtColor(img, imgBgr, CV_YCrCb2BGR);
    scal = cvGet2D(imgBgr,1199,1599);//获取像素点
    
    valY = scal.val[0];
    valU = scal.val[1];
    valV = scal.val[2];
printf("B=%e, G=%e,R=%e.\n",valY,valU,valV);
  
printf("cvCvtColor sucess.\n");  
  cvSaveImage("cap.bmp",imgBgr);
//  cvSaveImage("./cap.jpg",imgBgr,0);
/*printf("cvSaveImage sucess.\n");   
*/
}

void CALLBACK g_RealDataCallBack_V30(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer,DWORD dwBufSize,void* dwUser)
{
    printf("pyd---(hik_v30)Get data,the size is %d.\n",  dwBufSize);
    unsigned char pBitmap[50000];
    unsigned int pBmpSize;
    PLAYRECT hwnd;
    hwnd.x=0;
    hwnd.y=0;
    hwnd.uWidth=0;
    hwnd.uHeight=0;
    
    switch (dwDataType)
     {
       case NET_DVR_SYSHEAD: //系统头
        if (!PlayM4_GetPort(&lPort))  //获取播放库未使用的通道号
          {
             printf("(hik_v30)Get PlayM4_GetPort Error.\n");
             break;
          }
          else
          {
            printf("(hik_v30)Get PlayM4_GetPort lPort=%d.\n",lPort);
          }  
          //m_iPort = lPort; //第一次回调的是系统头,将获取的播放库port号赋值给全局port,下次回调数据时即使用此port号播放
          if (dwBufSize > 0)
          {    
             if (!PlayM4_OpenStream(lPort, (char*)pBuffer, dwBufSize, 1024*1024)) //打开流接口
             {
                printf("(hik_v30)Get PlayM4_OpenStream Error.\n");
                break;
             }   
             else
             {
               printf("(hik_v30)Get PlayM4_OpenStream Success.\n");
             } 
             
          if(!PlayM4_SetDecCallBack(lPort,g_DecCBFun))
          {
                printf("(hik_v30)Get PlayM4_SetDecCallBack Error.\n");
                break;
          }
          else
          {
            printf("(hik_v30)Get PlayM4_SetDecCallBack Success.\n");
          }  
                                 
          if (!PlayM4_Play(lPort, hwnd)) //播放开始
             {
                printf("(hik_v30)Get PlayM4_Play Error.\n");
                break;
             }
             else
             {
               printf("(hik_v30)Get PlayM4_Play Success.\n");
             }  

          }
         
         break;
       case NET_DVR_STREAMDATA:   //码流数据        
        
//        if(PlayM4_GetBMP(lPort,pBitmap,1024*1024,&pBmpSize))
//        {
//          printf("(hik_v30)Get PlayM4_GetBMP Bmp Size = %d.\n",  pBmpSize);
//        }
//        else
//        {
//          printf("(hik_v30)Get PlayM4_GetBMP Error =%d.",PlayM4_GetLastErrorCode());
//       }  

          if (dwBufSize > 0 && lPort != -1)
          {
             if (!PlayM4_InputData(lPort, (char*)pBuffer, dwBufSize))
             {
                printf("(hik_v30)Get PlayM4_InputData Error.\n");
                break;
             }
             else
             {
               printf("(hik_v30)Get PlayM4_InputData success.\n");
             }
          }

          
        break;
    }
}

void CALLBACK g_HikDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE *pBuffer,DWORD dwBufSize,DWORD dwUser)
{
    printf("pyd---(hik)Get data,the size is %d.\n", dwBufSize);
}

void CALLBACK g_StdDataCallBack(int lRealHandle, unsigned int dwDataType, unsigned char *pBuffer, unsigned int dwBufSize, unsigned int dwUser)
{
    printf("pyd---(rtsp)Get data,the size is %d.\n", dwBufSize);
}



/*******************************************************************
      Function:   Demo_GetStream
   Description:   preview(no "_V30")
     Parameter:   (IN)   none  
        Return:   0--successful,-1--fail。   
**********************************************************************/
int Demo_GetStream()
{

    NET_DVR_Init();
    long lUserID;
    //login
    NET_DVR_DEVICEINFO struDeviceInfo;
    lUserID = NET_DVR_Login("172.2.87.106", 8000, "admin", "12345", &struDeviceInfo);
    if (lUserID < 0)
    {
        printf("pyd1---Login error, %d\n", NET_DVR_GetLastError());
        return HPR_ERROR;
    }

    //Set callback function of getting stream.
    long lRealPlayHandle;
    NET_DVR_CLIENTINFO ClientInfo = {0};
#if (defined(_WIN32) || defined(_WIN_WCE))
    ClientInfo.hPlayWnd     = NULL;
#elif defined(__linux__)
    ClientInfo.hPlayWnd.x = 0;
    ClientInfo.hPlayWnd.y = 0;
    ClientInfo.hPlayWnd.uHeight = 0;
    ClientInfo.hPlayWnd.uWidth = 0;
#endif

    ClientInfo.lChannel     = 1;  //channel NO
    //ClientInfo.lLinkMode  = 0x40000000; //Record when breaking network.
    ClientInfo.lLinkMode    = 0;
    ClientInfo.sMultiCastIP = NULL;

    lRealPlayHandle = NET_DVR_RealPlay(lUserID, &ClientInfo);
    if (lRealPlayHandle < 0)
    {
        printf("pyd1---NET_DVR_RealPlay_V30 error\n");
        NET_DVR_Logout(lUserID);
        NET_DVR_Cleanup();
        return HPR_ERROR;
    }
    
    //Set callback function of getting stream.
    int iRet;
    iRet = NET_DVR_SetRealDataCallBack(lRealPlayHandle, g_HikDataCallBack, 0);
    if (!iRet)
    {
        printf("pyd1---NET_DVR_RealPlay_V30 error\n");
        NET_DVR_StopRealPlay(lRealPlayHandle);
        NET_DVR_Logout(lUserID);
        NET_DVR_Cleanup();  
        return HPR_ERROR;
    }


#ifdef _WIN32
    Sleep(5000);  //millisecond
#elif  defined(__linux__)
    sleep(500);   //second
#endif

    //stop
    NET_DVR_StopRealPlay(lRealPlayHandle);
    NET_DVR_Logout(lUserID);
    NET_DVR_Cleanup();
    return HPR_OK;

}

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


/*******************************************************************
      Function:   Demo_GetStream_V30
   Description:   preview(_V30)
     Parameter:   (IN)   none  
        Return:   0--successful,-1--fail。   
**********************************************************************/
int Demo_GetStream_V30()
{
    NET_DVR_Init();

    //设置连接时间,与重连时间
    NET_DVR_SetConnectTime(2000, 1);
    NET_DVR_SetReconnect(10000, true);

    long lUserID;
    //login
    NET_DVR_DEVICEINFO_V30 struDeviceInfo;
    //lUserID = NET_DVR_Login_V30("172.2.87.106", 8000, "admin", "12345", &struDeviceInfo);
    //lUserID = NET_DVR_Login_V30("113.18.11.162", 8000, "admin", "12345", &struDeviceInfo);
    lUserID = NET_DVR_Login_V30("192.168.1.64", 8000, "admin", "12345", &struDeviceInfo);
    if (lUserID < 0)
    {
        printf("pyd1---Login error, %d\n", NET_DVR_GetLastError());
        return HPR_ERROR;
    }

    NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL);

    //Set callback function of getting stream.
    long lRealPlayHandle;
    NET_DVR_CLIENTINFO ClientInfo = {0};
#if (defined(_WIN32) || defined(_WIN_WCE))
    ClientInfo.hPlayWnd     = NULL;
#elif defined(__linux__)
    ClientInfo.hPlayWnd.x = 0;
    ClientInfo.hPlayWnd.y = 0;
    ClientInfo.hPlayWnd.uHeight = 0;
    ClientInfo.hPlayWnd.uWidth = 0;
#endif

    ClientInfo.lChannel     = 1;  //channel NO.
    //ClientInfo.lLinkMode    = 0x40000000; //Record when breaking network.
    ClientInfo.lLinkMode    = 0;
    ClientInfo.sMultiCastIP = NULL;

    lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, g_RealDataCallBack_V30, NULL, 0);
    //lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, NULL, NULL, 0);
    if (lRealPlayHandle < 0)
    {
        printf("pyd1---NET_DVR_RealPlay_V30 error\n");
        return HPR_ERROR;
    }
    //Set rtsp callback function of getting stream.
    //NET_DVR_SetStandardDataCallBack(lRealPlayHandle, g_StdDataCallBack, 0);

#ifdef _WIN32
    Sleep(3000);  //millisecond
#elif  defined(__linux__)
    sleep(100);    //second
#endif

    //stop
    NET_DVR_StopRealPlay(lRealPlayHandle);
    NET_DVR_Logout_V30(lUserID);
    NET_DVR_Cleanup();
   
    return HPR_OK;
}



     这段代码在保存成jpg图片时,会内存溢出。原因是opencv保存jpg文件时要使用libjpeg.so 库的jpeg_start_compress 等函数,
但libm4paly.so也有jpeg_start_compress等函数。程序会找到libm4paly.so中的函数,导致异常。
我的libjpeg.so 库 在/usr/lib下。通过-Wl,-rpath, 选项让程序先找libjpeg.so

g++ -g -lopencv_core -lopencv_highgui -ljpeg -lhcnetsdk -lm4play -o hctest *.cpp -L/usr/local/lib -Wl,-rpath,/usr/lib,-rpath,./


编译后运行,就不会运行异常了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,以下是一个完整的示例程序: ```csharp using System; using System.Runtime.InteropServices; namespace PlayM4_OpenStreamAdvanced_Demo { class Program { [DllImport("PlayCtrl.dll")] public static extern bool PlayM4_OpenStreamAdvanced(int port, int flags, IntPtr pFileHeadBuf, int nSize, IntPtr pUser); [DllImport("PlayCtrl.dll")] public static extern bool PlayM4_Play(int nPort, IntPtr hWnd); static void Main(string[] args) { // 读取 SDP 文件内容 string sdpFilePath = "test.sdp"; string sdpContent = System.IO.File.ReadAllText(sdpFilePath); // 将 SDP 内容换为 byte 数组 byte[] sdpBytes = System.Text.Encoding.UTF8.GetBytes(sdpContent); // 调用 PlayM4_OpenStreamAdvanced 函数播放 RTP 视频 int port = 0; // 端口号 int flags = 0; // 标志位 IntPtr pFileHeadBuf = Marshal.AllocHGlobal(sdpBytes.Length); // 分配内存 IntPtr pUser = IntPtr.Zero; // 用户数据 Marshal.Copy(sdpBytes, 0, pFileHeadBuf, sdpBytes.Length); // 将 byte 数组复制到内存中 bool ret = PlayM4_OpenStreamAdvanced(port, flags, pFileHeadBuf, sdpBytes.Length, pUser); // 调用函数 Marshal.FreeHGlobal(pFileHeadBuf); // 释放内存 if (ret) { Console.WriteLine("播放功!"); // 获取播放窗口句柄 IntPtr hWnd = Console.WindowHandle; // 调用 PlayM4_Play 函数开始播放 ret = PlayM4_Play(port, hWnd); if (ret) { Console.WriteLine("开始播放!"); } else { Console.WriteLine("播放失败!"); } } else { Console.WriteLine("播放失败!"); } Console.ReadKey(); } } } ``` 需要注意的是,在播放视频之前,需要先调用 PlayM4_OpenStreamAdvanced 函数打开流并解析 SDP 内容。另外,需要将 PlayCtrl.dll 文件复制到程序运行目录下,并且需要安装海康播放库。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值