【问题标题】:Conversion from MFC CImage to Opencv IPlImage从 MFC CImage 到 Opencv IPlImage 的转换
【发布时间】:2012-05-31 07:05:03
【问题描述】:

我有一个使用 opencv 的相机应用程序,而我正在使用 MFC GUI。我需要将 CImage 转换为 IplImage 以供 Opencv 模块进行图像处理,并将其转换回 CImage 以便再次在窗口中显示。

我研究了这个主题,但没有足够的例子和解决方案。任何人有一些建议。谢谢

这是我的代码...

void CChildView::OnFileOpenimage(void)
{
    // TODO: Add your command handler code here
    CString strFilter;
    CSimpleArray<GUID> aguidFileTypes;
    HRESULT hResult;
hResult = imgOriginal.GetExporterFilterString(strFilter,aguidFileTypes);
if (FAILED(hResult)) {
    CString fmt;
    fmt.Format("GetExporterFilter failed:\n%x - %s", hResult, _com_error(hResult).ErrorMessage());
    ::AfxMessageBox(fmt);
    return;
}

CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
dlg.m_ofn.nFilterIndex = m_nFilterLoad;
hResult = (int)dlg.DoModal();
if(FAILED(hResult)) {
    return;
}

m_nFilterLoad = dlg.m_ofn.nFilterIndex;
imgOriginal.Destroy();
CString pathval =  dlg.GetPathName();
hResult = imgOriginal.Load(dlg.GetPathName());
if (FAILED(hResult)) {
    CString fmt;
    fmt.Format("Load image failed:\n%x - %s", hResult, _com_error(hResult).ErrorMessage());
    ::AfxMessageBox(fmt);
    return;
}
// IplImage *img from  imgOriginal; want to convert here for further processing.

m_nImageSize = SIZE_ORIGINAL;
Invalidate();
UpdateWindow();

}

【问题讨论】:

  • 你看过 CImage 类定义了吗?你看过 IplImage 结构定义了吗?你看到一些模式了吗?

标签: c++ user-interface opencv mfc


【解决方案1】:

我自己也有这个问题很长一段时间了。我发现这个代码here 我最终使用它工作得很好。而不是研究“CImage to IplImage”,您应该搜索“HBITMAP to IplImage”

IplImage* hBitmap2Ipl(HBITMAP hBmp, bool flip)
{
    BITMAP bmp;
    ::GetObject(hBmp,sizeof(BITMAP),&bmp);

    int    nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8;
    int    depth     = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;

    IplImage *img=cvCreateImageHeader(cvSize(bmp.bmWidth, bmp.bmHeight), depth, nChannels);

    img->imageData = (char*)malloc(bmp.bmHeight*bmp.bmWidth*nChannels*sizeof(char));
    memcpy(img->imageData,(char*)(bmp.bmBits),bmp.bmHeight*bmp.bmWidth*nChannels);
    return img;

}

用法:

ATL::CImage image;
//whatever code you use to generate the image goes here
IplImage *convertedImage=hBitmap2Ipl(image.Detach());
image.Destroy();

【讨论】:

    【解决方案2】:

    我找了半夜的复制粘贴内存泄漏,终于找到了!

    所以这是原始答案的更新代码sn-p。对我来说重要的是使用 cvCreateImage 而不是 cvCreateImageHeader 因为在调用 hBitmap2IplImage 之后我确实使用了 cvReleaseImage .在我的情况下,翻转也是必要的。干杯!

    IplImage* hBitmap2IplImage(HBITMAP hBmp, bool flip)
    {
        BITMAP bmp;
        ::GetObject(hBmp,sizeof(BITMAP),&bmp);
    
        int    nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8;
        int    depth     = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;
    
        IplImage *img=cvCreateImage(cvSize(bmp.bmWidth, bmp.bmHeight), depth, nChannels);
    
        size_t imgSize = bmp.bmHeight*bmp.bmWidth*nChannels;
        memcpy_s(img->imageData, imgSize, (char*)(bmp.bmBits), imgSize);
        if (flip)
            cvFlip(img, NULL, 0);
    
        return img;
    }
    

    用法:

    ATL::CImage image;
    HBITMAP hBitmap = image.Detach(); // some handle to your bitmap
    bool flip = true;
    IplImage* pSomeIplImage = hBitmap2IplImage(hBitmap, flip);
    image.Destroy();
    //
    // use "pSomeIplImage"
    //
    cvReleaseImage( &pSomeIplImage ); // don't forget
    

    【讨论】:

      【解决方案3】:

      如果位图图像在视图上,您​​可以使用设备上下文 (CDC dcBuffer) 来复制它。

      IplImage *pCapture = cvCreateImage(cvSize(U16_IMAGE_WIDTH/2,U16_IMAGE_HEIGHT/2),8, 3);
      
      ::GetDIBits(dcBuffer.GetSafeHdc(), bitmapBuffer, 0, U16_IMAGE_HEIGHT/2, pCapture->imageData, &bitmapInfo, DIB_RGB_COLORS);
      
      cvSaveImage("temp.bmp", pCapture);
      
      cvReleaseImage(&pCapture);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-25
        • 1970-01-01
        • 2011-06-12
        • 1970-01-01
        • 2010-09-28
        • 2013-04-02
        相关资源
        最近更新 更多