OpenCV 2.4:在 MFC 中显示 cv::Mat

jss*_*soe 2 c++ mfc opencv

我正在将现有代码库从 IplImage* 更新到较新的 cv::Mat。我想知道如何向 MFC 显示我的 cv::Mat 对象。我们当前使用的解决方案基于旧的 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 );
}
Run Code Online (Sandbox Code Playgroud)

我遇到了这个线程,但不幸的是,提供的答案不能满足我的需求,因为答案仍然要求您在显示之前将 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 );
}
Run Code Online (Sandbox Code Playgroud)

Kor*_*nel 5

假设我们有一张 OpenCV 图像cv::Mat cvImg,需要将其转换为CImage* mfcImg.
\n当然,MFC 图像应该显示在 MFC 窗口上,即CStatic winImg

\n\n

因此,为了在 MFC 窗口中显示 OpenCV 图像,应执行以下转换:

\n\n
cv::Mat -> CImage -> CStatic\n
Run Code Online (Sandbox Code Playgroud)\n\n

定义MFC窗口大小:

\n\n
RECT r;\nwinImg.GetClientRect(&r);\ncv::Size winSize(r.right, r.bottom);\n
Run Code Online (Sandbox Code Playgroud)\n\n

的大小cvImg并不总是与 MFC 窗口\xe2\x80\x99s 相同:

\n\n
cv::Mat cvImgTmp(winSize, CV_8UC3);\nif (cvImg.size() != winSize)\n{\n    cv::resize(cvImg, cvImgTmp, winSize);\n}\nelse \n{\n    cvImgTmp = cvImg.clone();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

旋转图像:

\n\n
cv::flip(cvImgTmp, cvImgTmp, 0);\n
Run Code Online (Sandbox Code Playgroud)\n\n

创建 MFC 映像:

\n\n
if (mfcImg)\n{\n    mfcImg->ReleaseDC();\n    delete mfcImg; mfcImg = nullptr;\n}\n\nmfcImg = new CImage();\nmfcImg->Create(winSize.width, winSize.height, 24);\n
Run Code Online (Sandbox Code Playgroud)\n\n

因为mfcImg你需要一个标题。通过使用创建它BITMAPINFO结构体创建它

\n\n
BITMAPINFO bitInfo;\nbitInfo.bmiHeader.biBitCount = 24;\nbitInfo.bmiHeader.biWidth = winSize.width;\nbitInfo.bmiHeader.biHeight = winSize.height;\nbitInfo.bmiHeader.biPlanes = 1;\nbitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\nbitInfo.bmiHeader.biCompression = BI_RGB;\nbitInfo.bmiHeader.biClrImportant = 0;\nbitInfo.bmiHeader.biClrUsed = 0;\nbitInfo.bmiHeader.biSizeImage = 0;\nbitInfo.bmiHeader.biXPelsPerMeter = 0;\nbitInfo.bmiHeader.biYPelsPerMeter = 0;\n
Run Code Online (Sandbox Code Playgroud)\n\n

添加标题和 OpenCV image\xe2\x80\x99s 数据到mfcImg

\n\n
StretchDIBits(mfcImg->GetDC(), 0, 0,\n    winSize.width, winSize.height, 0, 0,\n    winSize.width, winSize.height,\n    cvImgTmp.data, &bitInfo, DIB_RGB_COLORS, SRCCOPY\n);\n
Run Code Online (Sandbox Code Playgroud)\n\n

展示mfcImg在MFC窗口中

\n\n
mfcImg->BitBlt(::GetDC(winImg.m_hWnd), 0, 0);\n
Run Code Online (Sandbox Code Playgroud)\n\n

发布mfcImg如果您不使用它,

\n\n
if (mfcImg)\n{\n    mfcImg->ReleaseDC();\n    delete mfcImg; mfcImg = nullptr;\n}\n
Run Code Online (Sandbox Code Playgroud)\n