新版本的opencv取消了CvvImage,然而就不支持在MFC中显示了。这里介绍一种新的显示图像的方法。
环境:OpenCV4.1 +MCF 对话框 +Picture控件
方法一:直接将Mat显示在Picture窗体上
显示函数定义如下,
// MFC上Picture Control控件显示图像
// src 待显示的图像 (OpenCV库Mat对象结构)
// hwnd MFC显示图像的窗口句柄
void CXXXDlg::ShowImage(Mat& imgSrc, HWND hwnd) {
HDC hdc = ::GetDC(hwnd);
CRect rect;
//获取图片控件矩形框
GetDlgItem(IDC_STATIC_SHOWIMAGE)->GetClientRect(&rect);
//缩放Mat,以适应图片控件大小
cv::resize(imgSrc, imgSrc, cv::Size(rect.Width(), rect.Height()));
//cv::resize(imgSrc, imgSrc, cv::Size(300, 300));
// 转换格式 ,便于获取BITMAPINFO
switch (imgSrc.channels())
{
case 1:
cv::cvtColor(imgSrc, imgSrc, COLOR_GRAY2BGRA); // GRAY单通道
break;
case 3:
cv::cvtColor(imgSrc, imgSrc, COLOR_BGR2BGRA); // BGR三通道
break;
default:
break;
}
// 计算一个像素多少个字节
int pixelBytes = imgSrc.channels()*(imgSrc.depth() + 1);
// 制作bitmapinfo(数据头)
BITMAPINFO bitInfo;
bitInfo.bmiHeader.biBitCount = 8 * pixelBytes;
bitInfo.bmiHeader.biWidth = imgSrc.cols;
bitInfo.bmiHeader.biHeight = -imgSrc.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;
CDC *pDC = GetDlgItem(IDC_STATIC_SHOWIMAGE)->GetDC(); //获取图片控件DC
//绘图
::StretchDIBits(
pDC->GetSafeHdc(),
0, 0, rect.Width(), rect.Height(),
0, 0, imgSrc.cols, imgSrc.rows,
imgSrc.data,
&bitInfo,
DIB_RGB_COLORS,
SRCCOPY
);
ReleaseDC(pDC); //释放DC
}
函数调用方法:
HWND hwnd = GetDlgItem(IDC_STATIC_SHOWIMAGE)->GetSafeHwnd();
// 获取显示的图像
Mat img = imread("D:/images/11111.jpg");
// 调用显示函数
ShowImage(img, hwnd);
方法二:用Mat转CImage的方式,然后在Pictrue控件上绘制CImage
Mat转CImage
void CXXXDlg::MatToCImage(Mat &mat, CImage &cImage)
{
//create new CImage
int width = mat.cols;
int height = mat.rows;
int channels = mat.channels();
cImage.Destroy(); //clear
cImage.Create(width, height, 8 * channels); //默认图像像素单通道占用1个字节
//copy values
uchar* ps;
uchar* pimg = (uchar*)cImage.GetBits(); //A pointer to the bitmap buffer
int step = cImage.GetPitch();
for (int i = 0; i < height; ++i)
{
ps = (mat.ptr<uchar>(i));
for (int j = 0; j < width; ++j)
{
if (channels == 1) //gray
{
*(pimg + i * step + j) = ps[j];
}
else if (channels == 3) //color
{
for (int k = 0; k < 3; ++k)
{
*(pimg + i * step + j * 3 + k) = ps[j * 3 + k];
}
}
}
}
}
函数调用示例:
void CXXXDlg::ShowMethord4()
{
int cxl, cyl;
Mat rgbImageL1 = imread("D:/images/11111.jpg");//opencv图片
CImage rgbImageL2;
CRect rectl, pic_rectl;
int widthl, heightl;
//改变图片大小适应picture控件
GetDlgItem(IDC_STATIC_SHOWIMAGE)->GetClientRect(&pic_rectl);
widthl = pic_rectl.right;
heightl = pic_rectl.bottom;
resize(rgbImageL1, rgbImageL1, Size(widthl, heightl));
MatToCImage(rgbImageL1, rgbImageL2);//OpenCV中Mat对象转MFC的CImage类的函数
//获取图片的宽 高度
cxl = rgbImageL2.GetWidth();
cyl = rgbImageL2.GetHeight();
//获取Picture Control控件的大小
GetDlgItem(IDC_STATIC_SHOWIMAGE)->GetWindowRect(&rectl);
//将客户区选中到控件表示的矩形区域内
ScreenToClient(&rectl);
//窗口移动到控件表示的区域
GetDlgItem(IDC_STATIC_SHOWIMAGE)->MoveWindow(rectl.left, rectl.top, cxl, cyl, TRUE);
CWnd *pWnd = NULL;
pWnd = GetDlgItem(IDC_STATIC_SHOWIMAGE);//获取控件句柄
pWnd->GetClientRect(&rectl);//获取句柄指向控件区域的大小
CDC *pDc = NULL;
pDc = pWnd->GetDC();//获取picture的DC
rgbImageL2.Draw(pDc->m_hDC, rectl);//将图片绘制到picture表示的区域内
ReleaseDC(pDc);
}