DirectShow OpenCV GDI+ 图形显示格式转换

 

DirectShow OpenCV GDI+ 图形显示格式转换

GDI+在显示图像方面要比GDI使用起来更方便

OpenCV图像处理方面无论深度和与VC的兼容性方面都是很好的,
DirectShow要视频采集方面目前应该说是最优秀的

但OpenCV的IplImage格式与GDI+所需要的BITMAPINFO稍有不同
同时OpenCV集成的视频捕捉部分采用的VFW,效率上远不如DirectShow

三者之间的图像转换工作我采用的如下方法,经测试效率还可以
测试架构为
1.DirectShow采集一帧图像到源内存buf,把此buf转为OpenCV的彩色IplImage格式
2.用OpenCV的方法转成灰度图得到一个新的灰度IplImage
3.把灰度IplImage转为GDI+所能识别的Bitmap,显示到指定DC中
以上所有过程没有对源内存buf的无效copy过程(当然转灰度图过程OpenCV是要建个Buf的,不可省的)

1.DirectShow采集一帧图像到源内存buf,在CB函数中..
STDMETHODIMP CSampleGrabberCB::BufferCB(double SampleTime, BYTE * pBuffer, long BufferSize )
{
//cvCreateImage opencv自带函数,建立一个空图
IplImage *pImg = cvCreateImage(cvSize(biWidth ,biHeight), 8, 3);//建立空图3*8=24位
pImg->imageData = (char*)pBuffer;//得到buf指针,图像创建完毕
::SendMessageW(m_hWnd, UM_DVBACK, 0, LPARAM(pImg));//把图发到主线程,转2
cvReleaseImage(&pImg);//释放图
return 0;
}

2.在主线程中消息响应函数中用OpenCV的方法转成灰度图得到一个新的灰度IplImage
LRESULT CMy05_ThreadSnapDlg::OnUMDVBACK(WPARAM wParam, LPARAM lParam)
{
IplImage *pImgSrc = (IplImage *)lParam;// 得到源图  
IplImage* pImgGray = cvCreateImage(cvGetSize(pImgSrc), 8, 1);// 建立新的空的灰度图 
cvCvtColor(pImgSrc, pImgGray, CV_BGR2GRAY);// 24位RGB彩图转灰度图,opencv自带函数,这里可以使用任何opencv函数进行图象处理
DrawImgToHwnd(m_hWnd, pImgGray); //自写函数,显示灰度图,即处理结果;转3
}

3.把灰度IplImage转为GDI+所能识别的Bitmap,显示到指定DC中
void CMy05_ThreadSnapDlg::DrawImgToHwnd(HWND hWnd, IplImage *pImg)
{
int nBitCount = (pImg->depth & 255) * pImg->nChannels;//图像色彩深度 opencv源码这样写的,也可以直接乘
int nWidth = pImg->width;
int nHeight = pImg->height;//这里特别注意,如果发现倒像,这里设为负值即可(-pImg->height)
BITMAPINFO *pBITMAPINFO = nBitCount == 24 ? m_pBITMAPINFO_24:m_pBITMAPINFO_08;
//24位图和8位图的BITMAPINFO是固定的,要提前创建好,一次即可
Bitmap* pBitmap = Bitmap::FromBITMAPINFO(pBITMAPINFO, pImg->imageData);//GDI+的图像格式
Graphics *gdiDC = Graphics::FromHWND(hWnd);//GDI+创建画板方法
gdiDC->DrawImage(pBitmap,0,0);//GDI+画图方法
delete pBitmap;
delete gdiDC;
}

你可能感兴趣的:(DirectShow OpenCV GDI+ 图形显示格式转换)