【问题标题】:OpenCV 2.4 : Displaying a cv::Mat in MFCOpenCV 2.4:在 MFC 中显示 cv::Mat
【发布时间】:2015-03-11 21:18:59
【问题描述】:

我正在将现有代码库从 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 );
}

【问题讨论】:

    标签: c++ opencv mfc


    【解决方案1】:

    假设我们有一个 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;
    

    将header和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;
    }
    

    【讨论】:

    • 感谢您的详尽回答,分步说明正是我所需要的!当我获得更多声望点时也会投票
    猜你喜欢
    • 2018-03-24
    • 2012-11-11
    • 2012-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多