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

来源:互联网 发布:知乎电力系统仿真书籍 编辑:程序博客网 时间:2024/06/01 09:28

环境: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,./


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