(注:第一种方法是我的原创 ^_^。 第二种方法是从网上学习的。)
第一种方法:利用 板卡的API: GetJpegImage 得到 Jpeg 格式的图像数据,然后用opencv里的一个函数进行解码,得到IplImage对象。(我很郁闷海康威视采集卡为什么不直接提供RGB图像数据,而是提供了一个Jpeg数据给用户。)
libjpeg库就是专门处理 jpeg 格式的图像数据的,包括解码缩jpeg 格式的图像等。
opencv的库依赖于libjpeg库。我看了libjpeg库的源代码,然后又看了opencv 里 cvLoadImage这部分的源代码,发现opencv已经封装好了一个图像解码器: cvImageDecoder.
而且opencv的API 还提供了一个解码 内存中的图像数据的函数:
CVAPI(IplImage*) cvDecodeImage( const CvMat* buf, int iscolor CV_DEFAULT(CV_LOAD_IMAGE_COLOR));
先生成CvMat*,然后直接调用 cvDecodeImage 即可,以下是部分源代码:
1 void testCardAPI() 2 { 3 HANDLE channelHandle ; 4 DWORD nport; 5 6 //initialize the card 7 8 SetDefaultVideoStandard(StandardPAL); //returns 0 if error 9 10 //返回通道个数 11 int nChannels = InitDSPs(); 12 13 if( nChannels > 0 ) 14 { 15 16 17 //try to open any Channel 18 for(int i =0 ; i < GetTotalChannels() ; i++) 19 { 20 channelHandle = ChannelOpen( i ); 21 if( (unsigned int)channelHandle != 0xFFFFFFFF ) 22 { 23 //此处有疑问,nport 不知道是什么 24 nport = i ; 25 break; 26 } 27 } 28 29 //system("pause"); 30 31 // 如果 open channel 成功 32 if( (unsigned int)channelHandle != 0xFFFFFFFF ) 33 { 34 //注册画图回调函数 35 //RegisterDrawFun(); 36 37 SetOverlayColorKey( RGB(10,10,10) ); 38 39 40 //设置视频预览模式: overlay 41 int supportOverlayFlag = SetPreviewOverlayMode( true ); 42 43 if( supportOverlayFlag != 0 ) 44 { 45 //不支持 overlay, 就报错 46 } 47 48 //CWnd wnd; 49 //wnd.m_hwnd; 50 51 // StartVideoPreview( channelHandle, wnd.GetSafeHwnd() , 52 UCHAR imageBuf[704 * 576 * 2]; 53 DWORD Size = 704 * 576* 2; 54 DWORD hSize=704 * 576* 2; 55 UCHAR *imageBuffer=new UCHAR[hSize]; 56 cvNamedWindow("image",0); 57 while(1) 58 { 59 GetJpegImage(channelHandle, imageBuf, &Size, 50); 60 61 CvMat mat = cvMat(704,576,CV_8UC1, imageBuf); 62 63 IplImage *pIplImage = cvDecodeImage( &mat, 1 ); 64 65 //memcpy(imageBuffer,imageBuf,Size); 66 //IplImage *pIplImage=cvCreateImage(cvSize(704,576),8,1); 67 if(pIplImage) 68 { 69 //memcpy(pIplImage->imageData,imageBuf,Size); 70 cvShowImage("image",pIplImage); 71 cvReleaseImage(&pIplImage); 72 } 73 if(cvWaitKey(100)==27) 74 break; 75 } 76 77 78 } 79 } 80 }
第一种方法运行起来有点慢,可能是解压图片数据要耗时间罢。
第二种方法:从yuv422得到灰度图像,然后生成IplImage对象。
采集卡输出的是 原始yuv422格式图像
以下程序仅可以 实现 灰度图像(只提取了Y分量)的输出。
如果想得到彩色图像,还需要把 yuv422格式图像 转成 RGB格式的
以下是一段 简单的 视频卡驱动 和 用openCV显示图像的代码
1 // TestSDK.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 6 #define _AFXDLL 7 #include <afxwin.h> 8 9 #include "cv.h" 10 #include "highgui.h" 11 12 13 #pragma comment (lib, "DS40xxSDK.lib") 14 15 16 #include "DataType.h" 17 #include "HikVisionSdk.h" 18 19 20 21 void testCardAPI(); 22 23 int _tmain(int argc, _TCHAR* argv[]) 24 { 25 testCardAPI(); 26 return 0; 27 } 28 29 void testCardAPI() 30 { 31 HANDLE channelHandle ; 32 DWORD nport; 33 34 //initialize the card 35 36 SetDefaultVideoStandard(StandardPAL); //returns 0 if error 37 38 //返回通道个数 39 int nChannels = InitDSPs(); 40 41 if( nChannels > 0 ) 42 { 43 44 45 //try to open any Channel 46 for(int i =0 ; i < GetTotalChannels() ; i++) 47 { 48 channelHandle = ChannelOpen( i ); 49 if( (unsigned int)channelHandle != 0xFFFFFFFF ) 50 { 51 //此处有疑问,nport 不知道是什么 52 nport = i ; 53 break; 54 } 55 } 56 57 //system("pause"); 58 59 // 如果 open channel 成功 60 if( (unsigned int)channelHandle != 0xFFFFFFFF ) 61 { 62 //注册画图回调函数 63 //RegisterDrawFun(); 64 65 SetOverlayColorKey( RGB(10,10,10) ); 66 67 68 //设置视频预览模式: overlay 69 int supportOverlayFlag = SetPreviewOverlayMode( true ); 70 71 if( supportOverlayFlag != 0 ) 72 { 73 //不支持 overlay, 就报错 74 } 75 76 //CWnd wnd; 77 //wnd.m_hwnd; 78 79 // StartVideoPreview( channelHandle, wnd.GetSafeHwnd() , 80 UCHAR imageBuf[704 * 576*2]; 81 DWORD Size = 704 * 576*2; 82 DWORD hSize=704 * 576; 83 UCHAR *imageBuffer=new UCHAR[hSize]; 84 cvNamedWindow("image",0); 85 while(1) 86 { 87 GetOriginalImage(channelHandle, imageBuf, &Size); 88 memcpy(imageBuffer,imageBuf,hSize); 89 IplImage *pIplImage=cvCreateImage(cvSize(704,576),IPL_DEPTH_8U,1); 90 if(pIplImage) 91 { 92 memcpy(pIplImage->imageData,imageBuffer,hSize); 93 cvShowImage("image",pIplImage); 94 cvReleaseImage(&pIplImage); 95 } 96 if(cvWaitKey(100)==27) 97 break; 98 } 99 100 101 } 102 } 103 }
关键之处在
1 UCHAR imageBuf[704 * 576*2]; 2 DWORD Size = 704 * 576*2; 3 DWORD hSize=704 * 576; 4 UCHAR *imageBuffer=new UCHAR[hSize]; 5 cvNamedWindow("image",0); 6 while(1) 7 { 8 GetOriginalImage(channelHandle, imageBuf, &Size); 9 memcpy(imageBuffer,imageBuf,hSize); 10 IplImage *pIplImage=cvCreateImage(cvSize(704,576),IPL_DEPTH_8U,1); 11 if(pIplImage) 12 { 13 memcpy(pIplImage->imageData,imageBuffer,hSize); 14 cvShowImage("image",pIplImage); 15 cvReleaseImage(&pIplImage); 16 } 17 if(cvWaitKey(100)==27) 18 break; 19 }