我正在将现有的代码库从IplImage *更新到更新的cv :: Mat。我想知道如何将我的cv :: Mat对象显示到MFC。我们使用的当前解决方案基于旧的CvvImage类:
void DrawPicToHDC(IplImage *img, UINT ID, bool bOnPaint)
{
CDC *pDC = GetDlgItem(ID)->GetDC();
HDC hDC= pDC->GetSafeHdc();
CRect rect;
GetDlgItem(ID)->GetClientRect(&rect);
CvvImage cimg;
cimg.CopyOf( img );
cimg.DrawToHDC( hDC, &rect );
ReleaseDC( pDC );
}
我遇到了this帖子,但不幸的是,提供的答案并不能满足我的需求,因为答案仍然需要您在显示之前将Mat转换为IplImage *。
有没有办法只使用cv :: Mat?非常感谢任何帮助。
更新 我在Kornel的答案的帮助下,使用cv :: Mat调整了上述功能。我现在不需要包含CvvImage类:
void DrawPicToHDC(cv::Mat cvImg, UINT ID, bool bOnPaint)
{
// Get the HDC handle information from the ID passed
CDC *pDC = GetDlgItem(ID)->GetDC();
HDC hDCDst = pDC->GetSafeHdc();
CRect rect;
GetDlgItem(ID)->GetClientRect(&rect);
cv::Size winSize(rect.right, rect.bottom);
// Resize the source to the size of the destination image if necessary
cv::Mat cvImgTmp(winSize, CV_8UC3);
if (cvImg.size() != winSize)
{
cv::resize(cvImg, cvImgTmp, winSize);
}
else
{
cvImgTmp = cvImg;
}
// Rotate the image
cv::flip(cvImgTmp,cvImgTmp,0);
// Initialize the BITMAPINFO structure
BITMAPINFO bitInfo;
bitInfo.bmiHeader.biBitCount = 24;
bitInfo.bmiHeader.biWidth = winSize.width;
bitInfo.bmiHeader.biHeight = winSize.height;
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;
// Add header and OPENCV image's data to the HDC
StretchDIBits(hDCDst, 0, 0,
winSize.width, winSize.height, 0, 0,
winSize.width, winSize.height,
cvImgTmp.data, &bitInfo, DIB_RGB_COLORS, SRCCOPY);
ReleaseDC( pDC );
}
答案 0 :(得分:3)
假设我们有一个OpenCV图像cv::Mat cvImg
,其中一个应转换为CImage* mfcImg
。
当然,MFC图像应显示在MFC窗口上,即CStatic winImg
因此,为了在MFC窗口中显示OpenCV图像,应执行以下转换:
cv::Mat -> CImage -> CStatic
定义MFC窗口大小:
RECT r;
winImg.GetClientRect(&r);
cv::Size winSize(r.right, r.bottom);
cvImg
的大小并不总是与MFC窗口的大小相同:
cv::Mat cvImgTmp(winSize, CV_8UC3);
if (cvImg.size() != winSize)
{
cv::resize(cvImg, cvImgTmp, winSize);
}
else
{
cvImgTmp = cvImg.clone();
}
旋转图像:
cv::flip(cvImgTmp, cvImgTmp, 0);
创建MFC图像:
if (mfcImg)
{
mfcImg->ReleaseDC();
delete mfcImg; mfcImg = nullptr;
}
mfcImg = new CImage();
mfcImg->Create(winSize.width, winSize.height, 24);
对于mfcImg
,您需要一个标题。使用BITMAPINFO
结构
BITMAPINFO bitInfo;
bitInfo.bmiHeader.biBitCount = 24;
bitInfo.bmiHeader.biWidth = winSize.width;
bitInfo.bmiHeader.biHeight = winSize.height;
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;
将标题和OpenCV图像的数据添加到mfcImg
StretchDIBits(mfcImg->GetDC(), 0, 0,
winSize.width, winSize.height, 0, 0,
winSize.width, winSize.height,
cvImgTmp.data, &bitInfo, DIB_RGB_COLORS, SRCCOPY
);
在MFC窗口中显示mfcImg
mfcImg->BitBlt(::GetDC(winImg.m_hWnd), 0, 0);
如果您不使用它,请发布mfcImg
:
if (mfcImg)
{
mfcImg->ReleaseDC();
delete mfcImg; mfcImg = nullptr;
}