MFC中使用opencv获取海康摄像头视频

1.MFC-opencv配置:

新建一个空白项目,点击项目(菜单项)-属性-VC++目录,按照下图提示,添加目录:

可执行文件目录D:\Program Files\opencv\build\x86\vc10\bin 

包含目录D:\Program Files\opencv\build\include 

     D:\Program Files\opencv\build\include\opencv 

             D:\Program Files\opencv\build\include\opencv2 

库目录D:\Program Files\opencv\build\x86\vc10\lib  (本人64位机选64位错误,海康的也要选x86的lib,原因不懂,小白阶段)

配置连接器:项目(菜单项)->…属性->连接器->输入->附加依赖项(Debug版本,Release的**.lib),遇到无法解析的外部符号一般是忘了添加lib了。以下仅为opencv的lib,海康的lib自行脑补。

opencv_calib3d248d.lib
opencv_contrib248d.lib
opencv_core248d.lib
opencv_features2d248d.lib
opencv_flann248d.lib
opencv_gpu248d.lib
opencv_highgui248d.lib
opencv_imgproc248d.lib
opencv_legacy248d.lib
opencv_ml248d.lib
opencv_nonfree248d.lib
opencv_objdetect248d.lib
opencv_ocl248d.lib
opencv_photo248d.lib
opencv_stitching248d.lib
opencv_superres248d.lib
opencv_ts248d.lib
opencv_video248d.lib
opencv_videostab248d.lib
2. 捕获实时流,将实时流解码成YV12,然后转换成RGB(转自http://blog.csdn.net/wanghuiqi2008/article/details/31410509)

  1. #include <cstdio>  
  2. #include <cstring>  
  3. #include <iostream>  
  4. #include "Windows.h"  
  5. #include "HCNetSDK.h"  
  6. #include "PlayM4.h"  
  7. #include <opencv2\opencv.hpp>  
  8. #include "cv.h"  
  9. #include "highgui.h"  
  10. #include <time.h>  
  11. #define USECOLOR 1  
  12. using namespace std;  
  13. using namespace std;  
  14.   
  15. //--------------------------------------------  
  16. int iPicNum=0;//Set channel NO.  
  17. LONG nPort=-1;  
  18. HWND hWnd=NULL;  
  19.   
  20.   
  21. void yv12toYUV(char *outYuv, char *inYv12, int width, int height,int widthStep)  
  22. {  
  23.    int col,row;  
  24.    unsigned int Y,U,V;  
  25.    int tmp;  
  26.    int idx;  
  27.   
  28.   //printf("widthStep=%d.\n",widthStep);  
  29.   
  30.    for (row=0; row<height; row++)  
  31.    {  
  32.       idx=row * widthStep;  
  33.       int rowptr=row*width;  
  34.   
  35.       for (col=0; col<width; col++)  
  36.       {  
  37.          //int colhalf=col>>1;  
  38.          tmp = (row/2)*(width/2)+(col/2);  
  39. //         if((row==1)&&( col>=1400 &&col<=1600))  
  40. //         {   
  41. //          printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp);  
  42. //          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);  
  43. //         }   
  44.          Y=(unsigned int) inYv12[row*width+col];  
  45.          U=(unsigned int) inYv12[width*height+width*height/4+tmp];  
  46.          V=(unsigned int) inYv12[width*height+tmp];  
  47. //         if ((col==200))  
  48. //         {   
  49. //         printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp);  
  50. //         printf("width*height+width*height/4+tmp=%d.\n",width*height+width*height/4+tmp);  
  51. //         return ;  
  52. //         }  
  53.          if((idx+col*3+2)> (1200 * widthStep))  
  54.          {  
  55.           //printf("row * widthStep=%d,idx+col*3+2=%d.\n",1200 * widthStep,idx+col*3+2);  
  56.          }   
  57.          outYuv[idx+col*3]   = Y;  
  58.          outYuv[idx+col*3+1] = U;  
  59.          outYuv[idx+col*3+2] = V;  
  60.       }  
  61.    }  
  62.    //printf("col=%d,row=%d.\n",col,row);  
  63. }  
  64.   
  65.   
  66.   
  67. //解码回调 视频为YUV数据(YV12),音频为PCM数据  
  68. void CALLBACK DecCBFun(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2)  
  69. {  
  70.     long lFrameType = pFrameInfo->nType;   
  71.   
  72.     if(lFrameType ==T_YV12)  
  73.     {  
  74. #if USECOLOR  
  75.     //int start = clock();  
  76.     IplImage* pImgYCrCb = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);//得到图像的Y分量    
  77.     yv12toYUV(pImgYCrCb->imageData, pBuf, pFrameInfo->nWidth,pFrameInfo->nHeight,pImgYCrCb->widthStep);//得到全部RGB图像  
  78.     IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);    
  79.     cvCvtColor(pImgYCrCb,pImg,CV_YCrCb2RGB);    
  80.     //int end = clock();  
  81. #else  
  82.     IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 1);    
  83.     memcpy(pImg->imageData,pBuf,pFrameInfo->nWidth*pFrameInfo->nHeight);   
  84. #endif  
  85.     //printf("%d\n",end-start);  
  86.     cvShowImage("IPCamera",pImg);  
  87.     cvWaitKey(1);  
  88. #if USECOLOR  
  89.     cvReleaseImage(&pImgYCrCb);  
  90.     cvReleaseImage(&pImg);  
  91. #else  
  92.     cvReleaseImage(&pImg);  
  93. #endif  
  94.     //此时是YV12格式的视频数据,保存在pBuf中,可以fwrite(pBuf,nSize,1,Videofile);  
  95.     //fwrite(pBuf,nSize,1,fp);  
  96.     }  
  97.     /*************** 
  98.     else if (lFrameType ==T_AUDIO16) 
  99.     { 
  100.         //此时是音频数据,数据保存在pBuf中,可以fwrite(pBuf,nSize,1,Audiofile); 
  101.          
  102.     } 
  103.     else 
  104.     { 
  105.  
  106.     } 
  107.     *******************/  
  108.   
  109. }  
  110.   
  111.   
  112. ///实时流回调  
  113. void CALLBACK fRealDataCallBack(LONG lRealHandle,DWORD dwDataType,BYTE *pBuffer,DWORD dwBufSize,void *pUser)  
  114. {  
  115.     DWORD dRet;  
  116.     switch (dwDataType)  
  117.     {  
  118.     case NET_DVR_SYSHEAD:    //系统头  
  119.         if (!PlayM4_GetPort(&nPort)) //获取播放库未使用的通道号  
  120.         {  
  121.             break;  
  122.         }  
  123.         if(dwBufSize > 0)  
  124.         {  
  125.             if (!PlayM4_OpenStream(nPort,pBuffer,dwBufSize,1024*1024))  
  126.             {  
  127.                 dRet=PlayM4_GetLastError(nPort);  
  128.                 break;  
  129.             }  
  130.             //设置解码回调函数 只解码不显示  
  131.             if (!PlayM4_SetDecCallBack(nPort,DecCBFun))  
  132.             {  
  133.                 dRet=PlayM4_GetLastError(nPort);  
  134.                 break;  
  135.             }  
  136.           
  137.             //设置解码回调函数 解码且显示  
  138.             //if (!PlayM4_SetDecCallBackEx(nPort,DecCBFun,NULL,NULL))  
  139.             //{  
  140.             //  dRet=PlayM4_GetLastError(nPort);  
  141.             //  break;  
  142.             //}  
  143.   
  144.             //打开视频解码  
  145.             if (!PlayM4_Play(nPort,hWnd))  
  146.             {  
  147.                 dRet=PlayM4_GetLastError(nPort);  
  148.                 break;  
  149.             }  
  150.   
  151.             //打开音频解码, 需要码流是复合流  
  152.             if (!PlayM4_PlaySound(nPort))  
  153.             {  
  154.                 dRet=PlayM4_GetLastError(nPort);  
  155.                 break;  
  156.             }         
  157.         }  
  158.         break;  
  159.           
  160.     case NET_DVR_STREAMDATA:   //码流数据  
  161.         if (dwBufSize > 0 && nPort != -1)  
  162.         {  
  163.             BOOL inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);  
  164.             while (!inData)  
  165.             {  
  166.                 Sleep(10);  
  167.                 inData=PlayM4_InputData(nPort,pBuffer,dwBufSize);  
  168.                 OutputDebugString(L"PlayM4_InputData failed \n");     
  169.             }  
  170.         }  
  171.         break;    
  172.     }         
  173. }  
  174.   
  175. void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)  
  176. {  
  177.     char tempbuf[256] = {0};  
  178.     switch(dwType)   
  179.     {  
  180.     case EXCEPTION_RECONNECT:    //预览时重连  
  181.     printf("----------reconnect--------%d\n", time(NULL));  
  182.     break;  
  183.     default:  
  184.     break;  
  185.     }  
  186. }  
  187.   
  188. void main() {  
  189.   
  190.   //---------------------------------------  
  191.   // 初始化  
  192.   NET_DVR_Init();  
  193.   //设置连接时间与重连时间  
  194.   NET_DVR_SetConnectTime(2000, 1);  
  195.   NET_DVR_SetReconnect(10000, true);  
  196.     
  197.   //---------------------------------------  
  198.   // 获取控制台窗口句柄  
  199.   //HMODULE hKernel32 = GetModuleHandle((LPCWSTR)"kernel32");  
  200.   //GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow");  
  201.   
  202.   //---------------------------------------  
  203.   // 注册设备  
  204.   LONG lUserID;  
  205.   NET_DVR_DEVICEINFO_V30 struDeviceInfo;  
  206.   lUserID = NET_DVR_Login_V30("10.102.7.88", 8000, "admin""12345", &struDeviceInfo);  
  207.   if (lUserID < 0)  
  208.   {  
  209.        printf("Login error, %d\n", NET_DVR_GetLastError());  
  210.        NET_DVR_Cleanup();  
  211.        return;  
  212.   }  
  213.   
  214.   //---------------------------------------  
  215.   //设置异常消息回调函数  
  216.   NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL);  
  217.   
  218.   
  219.   //cvNamedWindow("IPCamera");  
  220.   //---------------------------------------  
  221.   //启动预览并设置回调数据流   
  222.   NET_DVR_CLIENTINFO ClientInfo;  
  223.   ClientInfo.lChannel = 1;        //Channel number 设备通道号  
  224.   ClientInfo.hPlayWnd = NULL;     //窗口为空,设备SDK不解码只取流  
  225.   ClientInfo.lLinkMode = 0;       //Main Stream  
  226.   ClientInfo.sMultiCastIP = NULL;  
  227.     
  228.   LONG lRealPlayHandle;  
  229.   lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID,&ClientInfo,fRealDataCallBack,NULL,TRUE);  
  230.   if (lRealPlayHandle<0)  
  231.   {  
  232.     printf("NET_DVR_RealPlay_V30 failed! Error number: %d\n",NET_DVR_GetLastError());  
  233.     return;  
  234.   }  
  235.   
  236.   //cvWaitKey(0);  
  237.   Sleep(-1);  
  238.   
  239.   //fclose(fp);  
  240.   //---------------------------------------  
  241.   //关闭预览  
  242.   if(!NET_DVR_StopRealPlay(lRealPlayHandle))  
  243.   {  
  244.     printf("NET_DVR_StopRealPlay error! Error number: %d\n",NET_DVR_GetLastError());  
  245.     return;  
  246.   }  
  247.   //注销用户  
  248.   NET_DVR_Logout(lUserID);  
  249.   NET_DVR_Cleanup();  
  250.   
  251.   return;  
  252. }  


终于能够实时捕获图像了,而且转换成了OpenCV能够处理的图像格式。

在这个过程中搜了很多资料,但是没有一个地方能详细说明,不过最终还是把这个给解决了。

 

附加说明:如果最后要做图像处理而不是像我这样只是将采集的图像显示出来,那么下面的语句是不需要的。

  1. #if USECOLOR  
  2.     cvReleaseImage(&pImgYCrCb);  
  3.     cvReleaseImage(&pImg);  
  4. #else  
  5.     cvReleaseImage(&pImg);  
  6. #endif  

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
使用Qt和OpenCV调用海康摄像头时,可以按照以下步骤进行操作: 1. 首先,确保已经安装并配置好了OpenCV海康摄像头相关的SDK工具。 2. 在Qt项目,包含OpenCV所需的头文件和链接库。可以在.pro文件添加如下配置: ``` INCLUDEPATH += /path/to/opencv/include LIBS += -L/path/to/opencv/libs -lopencv_core -lopencv_highgui -lopencv_imgproc ``` 3. 在Qt的主窗口UI设计添加一个用于显示视频的控件,例如QLabel。 4. 在代码使用OpenCV的VideoCapture类来打开摄像头并读取视频帧。以下是一个简单的示例: ```cpp #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> void MainWindow::on_pushButton_start_clicked(){ cv::VideoCapture camera; camera.open(0); //摄像头设备号,0代表第一个摄像头 cv::Mat frame; if (camera.isOpened()) { while (true) { camera.read(frame); if (!frame.empty()) { // 将读取到的图像frame显示在QLabel控件上,可通过QImage进行转换 QImage image(frame.data, frame.cols, frame.rows, QImage::Format_RGB888); ui->label_video->setPixmap(QPixmap::fromImage(image)); ui->label_video->resize(ui->label_video->pixmap()->size()); } else { break; } cv::waitKey(33); // 控制视频帧率,此处为30fps } camera.release(); } } ``` 以上示例的on_pushButton_start_clicked()函数是一个槽函数,当点击主窗口的开始按钮时,会打开摄像头并开始读取视频帧,然后将图像显示在QLabel控件上,直到点击停止按钮。 5. 最后,根据需要添加其他操作,例如图像处理或对象检测等功能。 通过以上步骤,就可以使用Qt和OpenCV调用海康摄像头,并在Qt界面上显示实时视频。需要注意的是,不同版本的OpenCV海康摄像头SDK可能有所区别,需根据实际情况进行相应的调整。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值