opencv的Mat图像显示在MFC控件中
方法:
只需要给Mat图像建立一个位图信息头即可;
例:
头文件中(.h)成员:
cv::Mat m_image
BITMAPINFO *m_imgInfo;
源文件中(.cpp):
BOOL CPointMatchDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// TODO: 在此添加额外的初始化代码
m_image = cv::imread("E:\dog.jpeg", cv::IMREAD_UNCHANGED); //(1)
//根据图像通道数建立图像信息(这里假定图像像素为24与32位或者8位(有颜色表的类似))
if(m_image.channels() == 3 || m_image.channels() == 4)
{
m_imgInfo = (BITMAPINFO*) new BYTE[sizeof(BITMAPINFOHEADER)];
}
else //8位,有颜色表
{
m_imgInfo = (BITMAPINFO*) new BYTE[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)];
//颜色表赋值
for (int i(0); i < 256; ++i)
{
m_imgInfo ->bmiColors[i].rgbBlue = i;
m_imgInfo ->bmiColors[i].rgbGreen = i;
m_imgInfo ->bmiColors[i].rgbRed = i;
m_imgInfo ->bmiColors[i].rgbReserved = 0;
}
}
//头文件信息(注意由实际显示情况可得出图像原点显示在空间左下角)
m_imgInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
m_imgInfo->bmiHeader.biBitCount = 8 * m_image .channels();
m_imgInfo->bmiHeader.biHeight = -m_image .rows;
m_imgInfo->bmiHeader.biWidth = m_image .cols;
m_imgInfo->bmiHeader.biPlanes = 1;
m_imgInfo->bmiHeader.biCompression = BI_RGB;
m_imgInfo->bmiHeader.biSizeImage = m_image .channels() * m_image .cols * m_image .rows;
m_imgInfo->bmiHeader.biXPelsPerMeter = 0;
m_imgInfo->bmiHeader.biYPelsPerMeter = 0;
m_imgInfo->bmiHeader.biClrUsed = 0;
m_imgInfo->bmiHeader.biClrImportant = 0;
return TRUE;
}
void CPointMatchDlg::OnPaint()
{
CDC *pDC;
pDC = GetDlgItem(IDC_MATCH_PICTURE_CONTROL)->GetDC();
CRecr imgCtrlRect;
GetDlgItem(IDC_MATCH_PICTURE_CONTROL)->GetClientRect(&imgCtrlRect);
pDC->SetStretchBltMode(COLORONCOLOR);
::StretchDIBits(pDC->GetSafeHdc(),
0, 0,
imgCtrlRect.Width(), m_imgCtrlRect.Height(),
0, 0,
m_image.cols, m_image.rows,
m_image.data,
m_imgInfo,
DIB_RGB_COLORS,
SRCCOPY);
ReleaseDC(pDC);
}
注:onPaint中的绘图程序一定不要放到OnInitDialog中,否则会发现StretchDIBits返回值不为零(说明函数执行正常),但是图像无法显示——OnInitDialog中是对话框初始化程序,对话框还没有初始化完成。OnInitDialog(初始化完成)后系统会自动调用onPaint绘制窗口(则OnInitDialog中显示图片没有意义,会被擦除)。
注意:
这里绘制图片时,一定要保证Mat图片符合window图片要求(即每行字节数为4的倍数),如果不满足则要进行适当的转化,否则画出的图像会出现问题(图像不是标准图像,反而是斜的)。
如果图片行字节数不是4的倍数,可在语句(1)修改为如下语句:
cv::Mat tempImg = cv::imread("E:\dog.jpeg", cv::IMREAD_UNCHANGED);
m_image = cv::Mat::zeros(tempImg.rows, (tempImg.cols + 3) / 4 * 4, m_image.type()); //转化行字节数为4的倍数(这里直接转化行像素为4的倍数)
tempImage.copyTo(m_image(cv::Rect(0, 0, tempImg.cols, tempImg.rows)));