在MFC中如何显示OpenCV的图像Mat

  • Post author:
  • Post category:其他


作者:海水和火焰

转自:

http://lh2078.blog.163.com/blog/static/5681137220131311492631/

在OpenCV1.1版本之前,包含了一个CvvImage类可以用于将IplImage显示在MFC界面上,但是在OpenCV2.0后,这个类没有了。所以有很多朋友问及如何在MFC界面上显示Mat,如果简单的使用

StretchDibBit的方法,会出现图像显示错行。这是由于Mat中的数据和传统的IplImage数据数据对齐方式不同。下面

给出解决方法:

void ShowImg(CDC *pDC, Mat &img, RECT* pRect)
{


if( pDC && pRect && !img.empty() )


{


uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];


BITMAPINFO* bmi = (BITMAPINFO*)buffer;


int bmp_w = img.cols, bmp_h = img.rows;



BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);


memset( bmih, 0, sizeof(*bmih));


bmih->biSize = sizeof(BITMAPINFOHEADER);


bmih->biWidth = bmp_w;


bmih->biHeight = -bmp_h;// : -abs(height);


bmih->biPlanes = 1;


bmih->biBitCount = IPL_DEPTH_8U*img.channels();


bmih->biCompression = BI_RGB;


if( IPL_DEPTH_8U*img.channels() == 8 )


{


RGBQUAD* palette = bmi->bmiColors;


int i;


for( i = 0; i < 256; i++ )


{


palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;


palette[i].rgbReserved = 0;


}


}


if(pRect->right – pRect->left +1 < bmp_w )


{


SetStretchBltMode(


pDC->m_hDC,           // handle to device context


HALFTONE );


}


else


{


SetStretchBltMode(


pDC->m_hDC,           // handle to device context


COLORONCOLOR );


}


if(img.cols % 4 != 0 && img.isContinuous())


{


IplImage *tempimg = cvCreateImage(img.size(), 8, img.channels());


img.copyTo(Mat(tempimg));


::StretchDIBits(


pDC->m_hDC,


pRect->left, pRect->top, pRect->right – pRect->left+1, pRect->bottom – pRect->top+1,


0, 0, bmp_w, bmp_h,


tempimg->imageData, bmi, DIB_RGB_COLORS, SRCCOPY );



cvReleaseImage(&tempimg);



}



else


{


::StretchDIBits(


pDC->m_hDC,


pRect->left, pRect->top, pRect->right – pRect->left+1, pRect->bottom – pRect->top+1,


0, 0, bmp_w, bmp_h,


img.data, bmi, DIB_RGB_COLORS, SRCCOPY );


}


}


return;
}


其中,CDC *pDC不用说了,熟悉MFC的码农都知道, Mat &img即OpenCV2.0后的图像了,如果仍然采用IplImage可以强制转换为Mat类型, RECT* pRect是在窗口中显示的位置。