برای نمایش تصاویر cv::Mat در OpenCV تنها تابعی که وجود دارد، imshow است که یک پنجره جدید می سازد و در آن نمایش می دهد. زمانیکه بخواهیم تصاویر را در یک پروژه MFC مثلا در یک دیالوگ یا یک برنامه SDI نمایش دهیم به مشکل می خوریم. برای حل مشکل دو راه وجود دارد، یکی اینکه Mat را به CImage تبدیل کنیم و از تابع CImage::Draw برای نمایش تصویر استفاده کنیم و دیگری که سربار کمتری دارد (چون حافظه ای کپی نمی شود) استفاده از تابع APIی ویندوز با نام StretchDIBits است:
آنچه در این مطلب خواهیم خواند :
ToggleShowing cv::Mat in MFC Dialog by Converting Mat to CImage
int Mat2CImage(Mat *mat, CImage &img){
if(!mat || mat->empty())
return -1;
int nBPP = mat->channels()*8;
img.Create(mat->cols, mat->rows, nBPP);
if(nBPP == 8)
{
static RGBQUAD pRGB[256];
for (int i = 0; i < 256; i++)
pRGB[i].rgbBlue = pRGB[i].rgbGreen = pRGB[i].rgbRed = i;
img.SetColorTable(0, 256, pRGB);
}
uchar* psrc = mat->data;
uchar* pdst = (uchar*) img.GetBits();
int imgPitch = img.GetPitch();
for(int y = 0; y < mat->rows; y++)
{
memcpy(pdst, psrc, mat->cols*mat->channels());
psrc += mat->step;
pdst += imgPitch;
}
return 0;
}
Showing cv::Mat in MFC Dialog Using StretchDIBits
void imdraw(cv::Mat &im, HDC dc, HWND wnd)
{
// Initialize the BITMAPINFO structure
BITMAPINFO bitInfo;
bitInfo.bmiHeader.biBitCount = 24;
bitInfo.bmiHeader.biWidth = im.cols;
bitInfo.bmiHeader.biHeight = -im.rows;
bitInfo.bmiHeader.biPlanes = 1;
bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitInfo.bmiHeader.biCompression = BI_RGB;
bitInfo.bmiHeader.biClrImportant = 0;
bitInfo.bmiHeader.biClrUsed = 0;
bitInfo.bmiHeader.biSizeImage = 0;
bitInfo.bmiHeader.biXPelsPerMeter = 0;
bitInfo.bmiHeader.biYPelsPerMeter = 0;
//FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin );
int from_x = 0;//MIN( MAX( from_x, 0 ), bmp_w - 1 );
int from_y = 0;//MIN( MAX( from_y, 0 ), bmp_h - 1 );
int W = 500;//MAX( MIN( bmp_w - from_x, w ), 0 );
int H = 400;//MAX( MIN( bmp_h - from_y, h ), 0 );
int x_dst = 0, y_dst = 0, w_dst = W, h_dst = H;
if (wnd)//To preserve aspect ratio
{
RECT rc;
GetClientRect(wnd, &rc);
x_dst = rc.left;
y_dst = rc.top;
w_dst = W = rc.right - rc.left + 1;
h_dst = H = rc.bottom - rc.top + 1;
double xScale = (double)W / (double)im.cols;
double yScale = (double)H / (double)im.rows;
if (yScale < xScale)//fit to height
{
x_dst += (int)((1.0 - yScale / xScale)*W / 2 + 0.5);
w_dst = (int)((yScale / xScale)*W + 0.5);
}
else {
y_dst += (int)((1.0 - xScale / yScale)*H / 2 + 0.5); //+0.5 for rounding
h_dst = (int)((xScale / yScale)*H + 0.5);
}
}
SetStretchBltMode(
dc, // handle to device context
HALFTONE );
::StretchDIBits(
dc,
x_dst, y_dst, w_dst, h_dst,
۰, ۰, im.cols, im.rows,
im.data, &bitInfo, DIB_RGB_COLORS, SRCCOPY );
}