DirectShow OpenCV GDI+ 图形显示格式转换
GDI+在显示图像方面要比GDI使用起来更方便
OpenCV图像处理方面无论深度和与VC的兼容性方面都是很好的,
DirectShow要视频采集方面目前应该说是最优秀的但OpenCV的IplImage格式与GDI+所需要的BITMAPINFO稍有不同
同时OpenCV集成的视频捕捉部分采用的VFW,效率上远不如DirectShow三者之间的图像转换工作我采用的如下方法,经测试效率还可以
测试架构为1.DirectShow采集一帧图像到源内存buf,把此buf转为OpenCV的彩色IplImage格式2.用OpenCV的方法转成灰度图得到一个新的灰度IplImage3.把灰度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));//把图发到主线程,转2cvReleaseImage(&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;}