转自:http://blog.csdn.net/tyt2222008/article/details/6257155
(注:第一种方法是我的原创 ^_^。 第二种方法是从网上学习的。)
第一种方法:利用 板卡的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 即可,以下是部分源代码:
void testCardAPI()
{
HANDLE channelHandle ;
DWORD nport;
//initialize the card
SetDefaultVideoStandard(StandardPAL); //returns 0 if error
//返回通道个数
int nChannels = InitDSPs();
if( nChannels > 0 )
{
//try to open any Channel
for(int i =0 ; i < GetTotalChannels() ; i++)
{
channelHandle = ChannelOpen( i );
if( (unsigned int)channelHandle != 0xFFFFFFFF )
{
//此处有疑问,nport 不知道是什么
nport = i ;
break;
}
}
//system("pause");
// 如果 open channel 成功
if( (unsigned int)channelHandle != 0xFFFFFFFF )
{
//注册画图回调函数
//RegisterDrawFun();
SetOverlayColorKey( RGB(10,10,10) );
//设置视频预览模式: overlay
int supportOverlayFlag = SetPreviewOverlayMode( true );
if( supportOverlayFlag != 0 )
{
//不支持 overlay, 就报错
}
//CWnd wnd;
//wnd.m_hwnd;
// StartVideoPreview( channelHandle, wnd.GetSafeHwnd() ,
UCHAR imageBuf[704 * 576 * 2];
DWORD Size = 704 * 576* 2;
DWORD hSize=704 * 576* 2;
UCHAR *imageBuffer=new UCHAR[hSize];
cvNamedWindow("image",0);
while(1)
{
GetJpegImage(channelHandle, imageBuf, &Size, 50);
CvMat mat = cvMat(704,576,CV_8UC1, imageBuf);
IplImage *pIplImage = cvDecodeImage( &mat, 1 );
//memcpy(imageBuffer,imageBuf,Size);
//IplImage *pIplImage=cvCreateImage(cvSize(704,576),8,1);
if(pIplImage)
{
//memcpy(pIplImage->imageData,imageBuf,Size);
cvShowImage("image",pIplImage);
cvReleaseImage(&pIplImage);
}
if(cvWaitKey(100)==27)
break;
}
}
}
}
第一种方法运行起来有点慢,可能是解压图片数据要耗时间罢。
第二种方法:从yuv422得到灰度图像,然后生成IplImage对象。
采集卡输出的是 原始yuv422格式图像
以下程序仅可以 实现 灰度图像(只提取了Y分量)的输出。
如果想得到彩色图像,还需要把 yuv422格式图像 转成 RGB格式的
以下是一段 简单的 视频卡驱动 和 用openCV显示图像的代码
// TestSDK.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#define _AFXDLL
#include <afxwin.h>
#include "cv.h"
#include "highgui.h"
#pragma comment (lib, "DS40xxSDK.lib")
#include "DataType.h"
#include "HikVisionSdk.h"
void testCardAPI();
int _tmain(int argc, _TCHAR* argv[])
{
testCardAPI();
return 0;
}
void testCardAPI()
{
HANDLE channelHandle ;
DWORD nport;
//initialize the card
SetDefaultVideoStandard(StandardPAL); //returns 0 if error
//返回通道个数
int nChannels = InitDSPs();
if( nChannels > 0 )
{
//try to open any Channel
for(int i =0 ; i < GetTotalChannels() ; i++)
{
channelHandle = ChannelOpen( i );
if( (unsigned int)channelHandle != 0xFFFFFFFF )
{
//此处有疑问,nport 不知道是什么
nport = i ;
break;
}
}
//system("pause");
// 如果 open channel 成功
if( (unsigned int)channelHandle != 0xFFFFFFFF )
{
//注册画图回调函数
//RegisterDrawFun();
SetOverlayColorKey( RGB(10,10,10) );
//设置视频预览模式: overlay
int supportOverlayFlag = SetPreviewOverlayMode( true );
if( supportOverlayFlag != 0 )
{
//不支持 overlay, 就报错
}
//CWnd wnd;
//wnd.m_hwnd;
// StartVideoPreview( channelHandle, wnd.GetSafeHwnd() ,
UCHAR imageBuf[704 * 576*2];
DWORD Size = 704 * 576*2;
DWORD hSize=704 * 576;
UCHAR *imageBuffer=new UCHAR[hSize];
cvNamedWindow("image",0);
while(1)
{
GetOriginalImage(channelHandle, imageBuf, &Size);
memcpy(imageBuffer,imageBuf,hSize);
IplImage *pIplImage=cvCreateImage(cvSize(704,576),IPL_DEPTH_8U,1);
if(pIplImage)
{
memcpy(pIplImage->imageData,imageBuffer,hSize);
cvShowImage("image",pIplImage);
cvReleaseImage(&pIplImage);
}
if(cvWaitKey(100)==27)
break;
}
}
}
}
关键之处在
UCHAR imageBuf[704 * 576*2];
DWORD Size = 704 * 576*2;
DWORD hSize=704 * 576;
UCHAR *imageBuffer=new UCHAR[hSize];
cvNamedWindow("image",0);
while(1)
{
GetOriginalImage(channelHandle, imageBuf, &Size);
memcpy(imageBuffer,imageBuf,hSize);
IplImage *pIplImage=cvCreateImage(cvSize(704,576),IPL_DEPTH_8U,1);
if(pIplImage)
{
memcpy(pIplImage->imageData,imageBuffer,hSize);
cvShowImage("image",pIplImage);
cvReleaseImage(&pIplImage);
}
if(cvWaitKey(100)==27)
break;
}