qt+opencv开发海康威视网络摄像机采集处理程序

正在开发的项目用到海康威视网络摄像机,现在总结一下该摄像机使用过程中遇到的一些问题。

首先是海康威视网络摄像机的IP设置,使用官网上提供的“设备网络搜索”软件将摄像机的IP地址前三位设置成与主机相同,同时把“使用DHCP”勾掉不使用。


qt+opencv开发海康威视网络摄像机采集处理程序_第1张图片


二次开发的话,主要参考了官方文档和这个帖子http://blog.csdn.net/wanghuiqi2008/article/details/31410509,采用实时流解码方式获取码流数据转换成OpenCV中的图像数据,然后再利用Qt中的消息传递机制将图像传送出去进行处理。


因为相机实时流解码方式采用了回调函数,为了在回调函数中传送qt消息,定义了一个相机类的全局变量指针,在相机类初始化时将相机this指针传给该变量,然后在回调函数中通过该变量调用相机类中函数发送图像数据。

代码(参考上面提到的帖子):

[cpp]  view plain  copy
  1. #ifndef CAMERAHK_H  
  2. #define CAMERAHK_H  
  3.   
  4. #include   
  5. #include     
  6. #include "opencv/cv.h"    
  7. #include "opencv/highgui.h"    
  8.   
  9. class CameraHk : public QObject  
  10. {  
  11.     Q_OBJECT  
  12.   
  13. public:  
  14.     CameraHk(QObject *parent);  
  15.     ~CameraHk();  
  16.     void emitImage(IplImage*);  
  17. signals:  
  18.     void outframe(IplImage*);  
  19. private:  
  20.     void login();//注册  
  21.     void capture();//开始采集  
  22.     void config();//设置参数  
  23.     void stop_play();  
  24. private:  
  25.     long lUserID;   
  26.     long lRealPlayHandle;   
  27. };  
  28.   
  29. #endif // CAMERAHK_H  
  30.   
  31.   
  32. #include "camerahk.h"  
  33. #include     
  34. #include     
  35. #include     
  36. #include "Windows.h"    
  37. #include "HCNetSDK.h"    
  38. #include "plaympeg4.h"  
  39. #include "SelectCamera.h"  
  40. #include     
  41. #define USECOLOR 1    
  42. using namespace std;  
  43.   
  44.   
  45.   
  46. CameraHk* HWND_CAMERAHK=0;//用于回调函数中使用,不安全  
  47.   
  48. //--------------------------------------------    
  49. int iPicNum=0;//Set channel NO.    
  50. LONG nPort=-1;    
  51. HWND hWnd=NULL;   
  52. NET_DVR_DEVICEINFO_V30 struDeviceInfo;    
  53.   
  54. void yv12toYUV(char *outYuv, char *inYv12, int width, int height,int widthStep)    
  55. {    
  56.    int col,row;    
  57.    unsigned int Y,U,V;    
  58.    int tmp;    
  59.    int idx;    
  60.     
  61.   //printf("widthStep=%d.\n",widthStep);    
  62.     
  63.    for (row=0; row
  64.    {    
  65.       idx=row * widthStep;    
  66.       int rowptr=row*width;    
  67.     
  68.       for (col=0; col
  69.       {    
  70.   
  71.          tmp = (row/2)*(width/2)+(col/2);    
  72.    
  73.          Y=(unsigned int) inYv12[row*width+col];    
  74.          U=(unsigned int) inYv12[width*height+width*height/4+tmp];    
  75.          V=(unsigned int) inYv12[width*height+tmp];    
  76.    
  77.          if((idx+col*3+2)> (1200 * widthStep))    
  78.          {    
  79.           //printf("row * widthStep=%d,idx+col*3+2=%d.\n",1200 * widthStep,idx+col*3+2);    
  80.          }     
  81.          outYuv[idx+col*3]   = Y;    
  82.          outYuv[idx+col*3+1] = U;    
  83.          outYuv[idx+col*3+2] = V;    
  84.       }    
  85.    }    
  86.   
  87. }      
  88.     
  89. //解码回调 视频为YUV数据(YV12),音频为PCM数据    
  90. void CALLBACK DecCBFun(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2)    
  91. {    
  92.     long lFrameType = pFrameInfo->nType;     
  93.     
  94.     if(lFrameType ==T_YV12)    
  95.     {    
  96. #if USECOLOR    
  97.         //int start = clock();    
  98.         IplImage* pImgYCrCb = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);//得到图像的Y分量      
  99.         yv12toYUV(pImgYCrCb->imageData, pBuf, pFrameInfo->nWidth,pFrameInfo->nHeight,pImgYCrCb->widthStep);//得到全部RGB图像    
  100.         IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);      
  101.         cvCvtColor(pImgYCrCb,pImg,CV_YCrCb2RGB);      
  102.         //int end = clock();  
  103. #else    
  104.         IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 1);      
  105.         memcpy(pImg->imageData,pBuf,pFrameInfo->nWidth*pFrameInfo->nHeight);     
  106. #endif    
  107.         //printf("%d\n",end-start);    
  108.         //cvShowImage("IPCamera",pImg);    
  109.         //cvWaitKey(-1);   
  110.         HWND_CAMERAHK->emitImage(pImg);  
  111. #if USECOLOR    
  112.         cvReleaseImage(&pImgYCrCb);    
  113.         cvReleaseImage(&pImg);    
  114. #else    
  115.     cvReleaseImage(&pImg);    
  116. #endif    
  117.     }  
  118.    
  119. }    
  120.       
  121. ///实时流回调    
  122. void CALLBACK fRealDataCallBack(LONG lRealHandle,DWORD dwDataType,BYTE *pBuffer,DWORD dwBufSize,void *pUser)    
  123. {    
  124.     DWORD dRet;    
  125.     switch (dwDataType)    
  126.     {    
  127.     case NET_DVR_SYSHEAD:    //系统头    
  128.         if (!PlayM4_GetPort(&nPort)) //获取播放库未使用的通道号    
  129.         {    
  130.             break;    
  131.         }    
  132.         if(dwBufSize > 0)    
  133.         {    
  134.             if (!PlayM4_OpenStream(nPort,pBuffer,dwBufSize,1024*1024))    
  135.             {    
  136.                 dRet=PlayM4_GetLastError(nPort);    
  137.                 break;    
  138.             }    
  139.             //设置解码回调函数 只解码不显示    
  140.             if (!PlayM4_SetDecCallBack(nPort,DecCBFun))    
  141.             {    
  142.                 dRet=PlayM4_GetLastError(nPort);    
  143.                 break;    
  144.             }    
  145.   
  146.     
  147.             //打开视频解码    
  148.             if (!PlayM4_Play(nPort,hWnd))    
  149.             {    
  150.                 dRet=PlayM4_GetLastError(nPort);    
  151.                 break;    
  152.             }    
  153.      
  154.         }    
  155.         break;    
  156.             
  157.     case NET_DVR_STREAMDATA:   //码流数据    
  158.         if (dwBufSize > 0 && nPort != -1)    
  159.         {    
  160.             BOOL inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);    
  161.             while (!inData)    
  162.             {    
  163.                 Sleep(10);    
  164.                 inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);    
  165.                 OutputDebugString(L"PlayM4_InputData failed \n");       
  166.             }    
  167.         }    
  168.         break;      
  169.     }           
  170. }    
  171.     
  172. void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)    
  173. {    
  174.     char tempbuf[256] = {0};    
  175.     switch(dwType)     
  176.     {    
  177.     case EXCEPTION_RECONNECT:    //预览时重连    
  178.     printf("----------reconnect--------%d\n", time(NULL));    
  179.     break;    
  180.     default:    
  181.     break;    
  182.     }    
  183. }   
  184.   
  185. CameraHk::CameraHk(QObject *parent)  
  186.     : QObject(parent)  
  187. {  
  188.     HWND_CAMERAHK=this;  
  189.     login();  
  190.     config();  
  191.     capture();  
  192. }  
  193.   
  194. CameraHk::~CameraHk()  
  195. {  
  196.     stop_play();  
  197. }  
  198.   
  199. void CameraHk::emitImage(IplImage* img)  
  200. {  
  201.     emit outframe(img);  
  202. }  
  203.   
  204. void CameraHk::login()  
  205. {  
  206.     //---------------------------------------    
  207.     // 初始化    
  208.     NET_DVR_Init();    
  209.     //设置连接时间与重连时间    
  210.     NET_DVR_SetConnectTime(2000, 1);    
  211.     NET_DVR_SetReconnect(10000, true);    
  212.   
  213.     //---------------------------------------    
  214.     // 注册设备       
  215.     lUserID = NET_DVR_Login_V30(CAMERA_IP, 8000, "admin""12345", &struDeviceInfo);    
  216.     if (lUserID < 0)    
  217.     {    
  218.         printf("Login error, %d\n", NET_DVR_GetLastError());    
  219.         NET_DVR_Cleanup();    
  220.         return;    
  221.     }    
  222.   
  223.       
  224. }  
  225. void CameraHk::config()  
  226. {  
  227. #if 1  
  228.     //---------------------------------------  
  229.     //设置参数  
  230.     int iRet;     
  231.     //获取压缩参数能力集  
  232.     NET_DVR_COMPRESSIONCFG_ABILITY struCompreCfgAbl;  
  233.     iRet=NET_DVR_GetDeviceAbility(lUserID,COMPRESSIONCFG_ABILITY, (char*)&nPort,sizeof(nPort),\  
  234.         (char*)&struCompreCfgAbl,sizeof(NET_DVR_COMPRESSIONCFG_ABILITY));  
  235.     if(!iRet)  
  236.     {  
  237.         printf("NET_DVR_GetDeviceAbility COMPRESSIONCFG_ABILITY error.\n");  
  238.     }  
  239.     //获取压缩参数  
  240.     DWORD dwReturnLen;  
  241.     NET_DVR_COMPRESSIONCFG_V30 struParams = {0};  
  242.     iRet = NET_DVR_GetDVRConfig(lUserID, NET_DVR_GET_COMPRESSCFG_V30, struDeviceInfo.byStartChan, \  
  243.         &struParams, sizeof(NET_DVR_COMPRESSIONCFG_V30), &dwReturnLen);  
  244.     if (!iRet)  
  245.     {  
  246.         printf("NET_DVR_GetDVRConfig NET_DVR_GET_COMPRESSCFG_V30 error.\n");  
  247.         //NET_DVR_Logout(lUserID);  
  248.         //NET_DVR_Cleanup();  
  249.         return;  
  250.     }  
  251.   
  252.     //设置压缩参数  
  253.     struParams.struNormHighRecordPara.byResolution=RESOLUTION_CODE;  
  254.     iRet = NET_DVR_SetDVRConfig(lUserID, NET_DVR_SET_COMPRESSCFG_V30, struDeviceInfo.byStartChan, \  
  255.         &struParams, sizeof(NET_DVR_COMPRESSIONCFG_V30));  
  256.     if (!iRet)  
  257.     {  
  258.         printf("NET_DVR_GetDVRConfig NET_DVR_SET_COMPRESSCFG_V30 error.\n");  
  259.         //NET_DVR_Logout(lUserID);  
  260.         //NET_DVR_Cleanup();  
  261.         return;  
  262.     }  
  263. #endif  
  264. }  
  265.   
  266. void CameraHk::capture()  
  267. {  
  268.     //---------------------------------------    
  269.     //设置异常消息回调函数    
  270.     NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL);   
  271.     //cvNamedWindow("IPCamera");    
  272.     //---------------------------------------    
  273.     //启动预览并设置回调数据流     
  274.     NET_DVR_CLIENTINFO ClientInfo;    
  275.     ClientInfo.lChannel = 1;        //Channel number 设备通道号    
  276.     ClientInfo.hPlayWnd = NULL;     //窗口为空,设备SDK不解码只取流    
  277.     ClientInfo.lLinkMode = 0;       //Main Stream    
  278.     ClientInfo.sMultiCastIP = NULL;    
  279.     lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID,&ClientInfo,fRealDataCallBack,NULL,TRUE);    
  280.   
  281.     if (lRealPlayHandle<0)    
  282.     {    
  283.         printf("NET_DVR_RealPlay_V40 failed! Error number: %d\n",NET_DVR_GetLastError());    
  284.         return;    
  285.     }    
  286. }  
  287.   
  288. void CameraHk::stop_play()  
  289. {  
  290.     //---------------------------------------    
  291.     //关闭预览    
  292.     if(!NET_DVR_StopRealPlay(lRealPlayHandle))    
  293.     {    
  294.         printf("NET_DVR_StopRealPlay error! Error number: %d\n",NET_DVR_GetLastError());    
  295.         return;    
  296.     }    
  297.     //释放播放库资源  
  298.     PlayM4_Stop(nPort);  
  299.     PlayM4_CloseStream(nPort);  
  300.     PlayM4_FreePort(nPort);  
  301.   
  302.     //注销用户    
  303.     NET_DVR_Logout(lUserID);    
  304.     NET_DVR_Cleanup();    
  305. }  

你可能感兴趣的:(qt,opencv,摄像头驱动开发)