نمایش تصویر Mat روی دیالوگ MFC

نمایش تصویر Mat روی دیالوگ MFC

برای نمایش تصاویر cv::Mat در OpenCV تنها تابعی که وجود دارد، imshow است که یک پنجره جدید می سازد و در آن نمایش می دهد. زمانیکه بخواهیم تصاویر را در یک پروژه MFC مثلا در یک دیالوگ یا یک برنامه SDI نمایش دهیم به مشکل می خوریم. برای حل مشکل دو راه وجود دارد، یکی اینکه  Mat را به CImage تبدیل کنیم و از تابع CImage::Draw برای نمایش تصویر استفاده کنیم و دیگری که سربار کمتری دارد (چون حافظه ای کپی نمی شود) استفاده از تابع APIی ویندوز با نام StretchDIBits است:

show OpenCV image on MFC dialog

Showing 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,  
		0, 0, im.cols, im.rows,  
		im.data, &bitInfo, DIB_RGB_COLORS, SRCCOPY );  
}

 

بدون دیدگاه

ارسال یک نظر

نظر
نام
ایمیل
وبسایت