使用OpenCV 2.4加载MFC SDI视图或控件中的图像

时间:2021-03-31 20:33:08

In old version of opencv we had the class like CvvImage, that were easily used for MFC controls to display camera images or simple images from the OpenCV. But in 2.4 or 2.3 this support is finished by the OpenCV , i wonder if we have any other class in new version.

在旧版本的opencv中,我们有CvvImage类,它很容易用于MFC控件以显示来自opencv的相机图像或简单图像。但是在2.4或2.3中,这个支持是OpenCV完成的,我想知道在新版本中是否还有其他类。

My application is MFC SDI and inside view i am over riding the OnPaint function. In previous opencv i was using Paint function like

我的应用程序是MFC SDI,我正在运行OnPaint函数。在之前的opencv中,我使用了Paint函数

void CRightCameraView::OnPaint()
{
    CPaintDC dc(this); // device context for painting
    m_CVvimageObj.CopyOf(m_iplImageFrame); //copy IplImage frame

    if(m_bImageDisplay)
    {
    m_CVvimageObj.Show(dc.GetSafeHdc(),10,0,m_CVvimageObj.Width(),m_CVvimageObj.Height());
    }


}

Kindly guide me which is the most update version of class to do same thing and support such DC controls of MFC.

请指导我哪个是类最更新的版本做同样的事情,并支持这样的MFC的DC控件。

3 个解决方案

#1


1  

Since i could not find the answer i would like to help others what i did.

因为我找不到答案,我想帮助别人我所做的。

I have extracted cvvimage class manually and added in my project and then i did the following ..

我已经手工提取了cvvimage类并添加到我的项目中,然后我做了如下的事情。

in my views header file i declared

在我声明的视图头文件中

CvvImage m_CVvImageObj;
cv::Mat m_matImage;

inside my CPP file of view , i have called following in initialization function

在我的CPP视图中,我已经调用了初始化函数。

m_matImage = cv::imread(strA.GetBuffer(),CV_LOAD_IMAGE_COLOR);   // Read the file

if(! m_matImage.data )                              // Check for invalid input
{
    AfxMessageBox(L"Could not open or find the image");
}


 IplImage iplimg = m_matImage;
 m_CVvImageObj.CopyOf(&iplimg);
 UpdateData();
 Invalidate();

inside the overided function of OnPaint inside view i added

在OnPaint的覆盖函数内部,我添加了视图

if(m_CVvImageObj.GetImage())
{       
    //m_CurrentFrame.Show
        m_CVvImageObj.Show(dc.GetSafeHdc(),10,0,m_CVvImageObj.Width(),m_CVvImageObj.Height());
}

Cvvimage h file is the following

Cvvimage h文件如下所示

#pragma once

//#pragma once  
#ifndef CVVIMAGE_CLASS_DEF  
#define CVVIMAGE_CLASS_DEF  

#include <opencv2\highgui\highgui.hpp>    
class CvvImage  
{  
public:  
    CvvImage();  
    virtual ~CvvImage();  

    virtual bool Create( int width, int height, int bits_per_pixel, int image_origin = 0 );  
    virtual bool Load( const char* filename, int desired_color = 1 );  
    virtual bool LoadRect( const char* filename,  

    int desired_color, CvRect r );  

#if defined WIN32 || defined _WIN32  
    virtual bool LoadRect( const char* filename,int desired_color, RECT r )  
    {  
        return LoadRect( filename, desired_color,  
            cvRect( r.left, r.top, r.right - r.left, r.bottom - r.top ));  
    }  
#endif  

    virtual bool Save( const char* filename );  
    virtual void CopyOf( CvvImage& image, int desired_color = -1 );  
    virtual void CopyOf( IplImage* img, int desired_color = -1 );  
    IplImage* GetImage() { return m_img; };  
    virtual void Destroy(void);  
    int Width() { return !m_img ? 0 : !m_img->roi ? m_img->width : m_img->roi->width; };  
    int Height() { return !m_img ? 0 : !m_img->roi ? m_img->height : m_img->roi->height;};  
    int Bpp() { return m_img ? (m_img->depth & 255)*m_img->nChannels : 0; };  
    virtual void Fill( int color );  
    virtual void Show( const char* window );  

#if defined WIN32 || defined _WIN32  
    virtual void Show( HDC dc, int x, int y, int width, int height,  
        int from_x = 0, int from_y = 0 );  
    virtual void DrawToHDC( HDC hDCDst, RECT* pDstRect );  
    virtual void DrawToHDC( HDC hDCDst, CvRect pDstRect ); 
#endif  

protected:

    IplImage* m_img;

};

typedef CvvImage CImage;

#endif

and CPP file for cvvimage class is following

cvvimage类的CPP文件如下

///////////////////////////////////////////////////////////////////////////////////////////////////
//CvvImage.cpp

#include "StdAfx.h"  
#include "CvvImage.h"
///////////////////////////////////////////////////////////////////////////////////////////////////

CV_INLINE RECT NormalizeRect( RECT r );
CV_INLINE RECT NormalizeRect( RECT r )
{
    int t;
    if( r.left > r.right )
    {
        t = r.left;
        r.left = r.right;
        r.right = t;
    }
    if( r.top > r.bottom )
    {
        t = r.top;
        r.top = r.bottom;
        r.bottom = t;
    }

    return r;
}
CV_INLINE CvRect RectToCvRect( RECT sr );
CV_INLINE CvRect RectToCvRect( RECT sr )
{
    sr = NormalizeRect( sr );
    return cvRect( sr.left, sr.top, sr.right - sr.left, sr.bottom - sr.top );
}
CV_INLINE RECT CvRectToRect( CvRect sr );
CV_INLINE RECT CvRectToRect( CvRect sr )
{
    RECT dr;
    dr.left = sr.x;
    dr.top = sr.y;
    dr.right = sr.x + sr.width;
    dr.bottom = sr.y + sr.height;

    return dr;
}
CV_INLINE IplROI RectToROI( RECT r );
CV_INLINE IplROI RectToROI( RECT r )
{
    IplROI roi;
    r = NormalizeRect( r );
    roi.xOffset = r.left;
    roi.yOffset = r.top;
    roi.width = r.right - r.left;
    roi.height = r.bottom - r.top;
    roi.coi = 0;

    return roi;
}
void FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin )
{
    assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));

    BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);

    memset( bmih, 0, sizeof(*bmih));
    bmih->biSize = sizeof(BITMAPINFOHEADER);
    bmih->biWidth = width;
    bmih->biHeight = origin ? abs(height) : -abs(height);
    bmih->biPlanes = 1;
    bmih->biBitCount = (unsigned short)bpp;
    bmih->biCompression = BI_RGB;
    if( bpp == 8 )
    {
        RGBQUAD* palette = bmi->bmiColors;
        int i;
        for( i = 0; i < 256; i++ )
        {
            palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
            palette[i].rgbReserved = 0;
        }
    }
}
CvvImage::CvvImage()
{
    m_img = 0;
}
void CvvImage::Destroy()
{
    cvReleaseImage( &m_img );
}
CvvImage::~CvvImage()
{
    Destroy();
}
bool CvvImage::Create( int w, int h, int bpp, int origin )
{
    const unsigned max_img_size = 10000;

    if( (bpp != 8 && bpp != 24 && bpp != 32) ||
        (unsigned)w >= max_img_size || (unsigned)h >= max_img_size ||
        (origin != IPL_ORIGIN_TL && origin != IPL_ORIGIN_BL))
    {
        assert(0); // most probably, it is a programming error
        return false;
    }
    if( !m_img || Bpp() != bpp || m_img->width != w || m_img->height != h )
    {
        if( m_img && m_img->nSize == sizeof(IplImage))
            Destroy();

        m_img = cvCreateImage( cvSize( w, h ), IPL_DEPTH_8U, bpp/8 );
    }
    if( m_img )
        m_img->origin = origin == 0 ? IPL_ORIGIN_TL : IPL_ORIGIN_BL;
    return m_img != 0;
}
void CvvImage::CopyOf( CvvImage& image, int desired_color )
{
    IplImage* img = image.GetImage();
    if( img )
    {
        CopyOf( img, desired_color );
    }
}
#define HG_IS_IMAGE(img) \
    ((img) != 0 && ((const IplImage*)(img))->nSize == sizeof(IplImage) && \
    ((IplImage*)img)->imageData != 0)
void CvvImage::CopyOf( IplImage* img, int desired_color )
{
    if( HG_IS_IMAGE(img) )
    {
        int color = desired_color;
        CvSize size = cvGetSize( img ); 
        if( color < 0 )
            color = img->nChannels > 1;
        if( Create( size.width, size.height,
            (!color ? 1 : img->nChannels > 1 ? img->nChannels : 3)*8,
            img->origin ))
        {
            cvConvertImage( img, m_img, 0 );
        }
    }
}
bool CvvImage::Load( const char* filename, int desired_color )
{
    IplImage* img = cvLoadImage( filename, desired_color );
    if( !img )
        return false;

    CopyOf( img, desired_color );
    cvReleaseImage( &img );

    return true;
}
bool CvvImage::LoadRect( const char* filename,
                        int desired_color, CvRect r )
{
    if( r.width < 0 || r.height < 0 ) return false;


    IplImage* img = cvLoadImage( filename, desired_color );
    if( !img )
        return false;
    if( r.width == 0 || r.height == 0 )
    {
        r.width = img->width;
        r.height = img->height;
        r.x = r.y = 0;
    }
    if( r.x > img->width || r.y > img->height ||
        r.x + r.width < 0 || r.y + r.height < 0 )
    {
        cvReleaseImage( &img );
        return false;
    }

    if( r.x < 0 )
    {
        r.width += r.x;
        r.x = 0;
    }
    if( r.y < 0 )
    {
        r.height += r.y;
        r.y = 0;
    }
    if( r.x + r.width > img->width )
        r.width = img->width - r.x;

    if( r.y + r.height > img->height )
        r.height = img->height - r.y;
    cvSetImageROI( img, r );
    CopyOf( img, desired_color );
    cvReleaseImage( &img );
    return true;
}
bool CvvImage::Save( const char* filename )
{
    if( !m_img )
        return false;
    cvSaveImage( filename, m_img );
    return true;
}
void CvvImage::Show( const char* window )
{
    if( m_img )
        cvShowImage( window, m_img );
}
void CvvImage::Show( HDC dc, int x, int y, int w, int h, int from_x, int from_y )
{
    if( m_img && m_img->depth == IPL_DEPTH_8U )
    {
        uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];
        BITMAPINFO* bmi = (BITMAPINFO*)buffer;
        int bmp_w = m_img->width, bmp_h = m_img->height;
        FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin );
        from_x = MIN( MAX( from_x, 0 ), bmp_w - 1 );
        from_y = MIN( MAX( from_y, 0 ), bmp_h - 1 );
        int sw = MAX( MIN( bmp_w - from_x, w ), 0 );
        int sh = MAX( MIN( bmp_h - from_y, h ), 0 );
        SetDIBitsToDevice(
            dc, x, y, sw, sh, from_x, from_y, from_y, sh,
            m_img->imageData + from_y*m_img->widthStep,
            bmi, DIB_RGB_COLORS );
    }
}
void CvvImage::DrawToHDC( HDC hDCDst, RECT* pDstRect ) 
{
    if( pDstRect && m_img && m_img->depth == IPL_DEPTH_8U && m_img->imageData )
    {
        uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];
        BITMAPINFO* bmi = (BITMAPINFO*)buffer;
        int bmp_w = m_img->width, bmp_h = m_img->height;
        CvRect roi = cvGetImageROI( m_img );
        CvRect dst = RectToCvRect( *pDstRect );
        if( roi.width == dst.width && roi.height == dst.height )
        {
            Show( hDCDst, dst.x, dst.y, dst.width, dst.height, roi.x, roi.y );
            return;
        }
        if( roi.width > dst.width )
        {
            SetStretchBltMode(
                hDCDst, // handle to device context
                HALFTONE );
        }
        else
        {
            SetStretchBltMode(
                hDCDst, // handle to device context
                COLORONCOLOR );
        }
        FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin );
        ::StretchDIBits(hDCDst,dst.x, dst.y, dst.width, dst.height,roi.x, roi.y, roi.width, roi.height,\
            m_img->imageData, bmi, DIB_RGB_COLORS, SRCCOPY );
    }
}
void CvvImage::DrawToHDC( HDC hDCDst, CvRect pDstRect )
{
    RECT rDest=CvRectToRect(pDstRect);
    DrawToHDC(hDCDst,&rDest);
}
void CvvImage::Fill( int color )
{
    cvSet( m_img, cvScalar(color&255,(color>>8)&255,(color>>16)&255,(color>>24)&255) );
}

enjoy.

享受。

#2


1  

1.first load a picture get pic name and path.

1。首先载入图片获得图片名称和路径。

void CvlistDlg::OnBnClickedRead()
{
    CString     FilePathName;
    CString     FileName;
    CFileDialog openVideo(true);
    openVideo.m_ofn.lpstrTitle = _T("Open");
    if (IDOK == openVideo.DoModal()){
        FileName = openVideo.GetFileName();
        FilePathName = openVideo.GetPathName();
        _currentFile._fileName = FileName;
        _currentFile._filePath = FilePathName;
    }
 }

2.add follow code in your button callback function.

2。在按钮回调函数中添加follow代码。

void CvlistDlg::OnBnClickedOk(){
    cv::Mat img = cv::imread(str);
    CDC *pDC = GetDlgItem(IDC_Pic)->GetDC();
    HDC hDC = pDC->GetSafeHdc();
    CRect rect;
    GetDlgItem(IDC_Pic)->GetClientRect(&rect);
    int rw = rect.right - rect.left;     //the width of your picture control
    int rh = rect.bottom - rect.top;
    if (!img.data){
        MessageBox(_T("read picture fail!"));
        return;
    }
    cv::resize(img, img, cv::Size(rw, rh));     
    IplImage iplimg = img;
    m_CVvImageObj.CopyOf(&iplimg);
    UpdateData();
    if (m_CVvImageObj.GetImage()){
        m_CVvImageObj.Show(pDC->GetSafeHdc(), 0, 0, rw, rh);
    }
}

I hope those can give you some help.

我希望他们能给你一些帮助。

#3


0  

You don't need of IplImage. Basically you can draw a cv::Mat to a DC of a MFC control, using StretchDIBits. It accepts pointer to memory block where the bitmap is stored... in this case cv::Mat.data

你不需要IplImage。基本上,您可以使用担架将cv: Mat绘制到MFC控件的DC。它接受一个指向内存块的指针,在这个块中存储位图。在这种情况下简历::Mat.data

But remember that (this make me crazing before)

但是记住这一点(这让我很疯狂)

  • GDI requires DWORD alignment while cv::Mat don't use any rows padding
  • GDI需要DWORD对齐,而cv::Mat不使用任何行填充。
  • In addition your Mat could be a ROI this means that at the end each rows there isn't next row but the image that continues
  • 此外,您的Mat可能具有ROI,这意味着在每一行的末尾都没有下一行,只有继续运行的映像

You can have DWORD alignment in OpenCV using images where cols % 4 == 0 so you can add a border to your image

您可以在OpenCV中使用cols % 4 = 0的图像进行DWORD对齐,以便向映像添加边框

  border = 4 - (img.cols % 4);
  if ( (border<4 && border > 0) || img.isContinuous() == false)
  {
    cv::copyMakeBorder(img, tmpImg, 0, 0, 0, border, cv::BORDER_CONSTANT, 0);
  }
  else
    tmpImg = img

Using copyMakeBorder you will solve both requirements

使用copyMakeBorder将解决这两个需求

Another issues is grey images because MFC requires a flat palette to display it. You can convert your Mat with cvtColor or create the palette:

另一个问题是灰色图像,因为MFC需要一个平面调色板来显示它。您可以转换您的席与cvtColor或创建调色板:

   uchar buffer[sizeof(BITMAPINFO) + 1024];
   BITMAPINFO* bmi = (BITMAPINFO*)buffer;
   BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);
   bmih->biBitCount = 8*img.elemenSize()
   bmih->biWidth = tmpImg.cols;
   bmih->biHeight = -tmpImg.rows;// DIB are bottom ->top
   bmih->...

  //The palette is required for grey image
  if (bmih->biBitCount == 8)
  {
    RGBQUAD* palette = bmi->bmiColors;
    for (int i = 0; i < 256; i++)
    {
      palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
      palette[i].rgbReserved = 0;
    }
  }

finally draw to HDC

最后画HDC

imgH = img.rows;
imgW = img.cols; //use original cols  to avoid border

ClientDC hDC(WinCtrl);

//rr is relative to control
RECT rr; WinCtrl->GetClientRect(&rr);  

StretchDIBits(hDC,
  0, 0, rr.right, rr.bottom,
  0, 0, imgW, imgH,
  tmpImg.data, bmi, DIB_RGB_COLORS, SRCCOPY);

You can find detailed info and a class to manage image fitting here: http://www.pklab.net/?&id=390&lang=EN&t=How-to-display-an-OpenCV-image-or-video-in-your-own-MFC-interface

您可以在这里找到详细的信息和管理图像匹配的类:http://www.pklab.net/?

#1


1  

Since i could not find the answer i would like to help others what i did.

因为我找不到答案,我想帮助别人我所做的。

I have extracted cvvimage class manually and added in my project and then i did the following ..

我已经手工提取了cvvimage类并添加到我的项目中,然后我做了如下的事情。

in my views header file i declared

在我声明的视图头文件中

CvvImage m_CVvImageObj;
cv::Mat m_matImage;

inside my CPP file of view , i have called following in initialization function

在我的CPP视图中,我已经调用了初始化函数。

m_matImage = cv::imread(strA.GetBuffer(),CV_LOAD_IMAGE_COLOR);   // Read the file

if(! m_matImage.data )                              // Check for invalid input
{
    AfxMessageBox(L"Could not open or find the image");
}


 IplImage iplimg = m_matImage;
 m_CVvImageObj.CopyOf(&iplimg);
 UpdateData();
 Invalidate();

inside the overided function of OnPaint inside view i added

在OnPaint的覆盖函数内部,我添加了视图

if(m_CVvImageObj.GetImage())
{       
    //m_CurrentFrame.Show
        m_CVvImageObj.Show(dc.GetSafeHdc(),10,0,m_CVvImageObj.Width(),m_CVvImageObj.Height());
}

Cvvimage h file is the following

Cvvimage h文件如下所示

#pragma once

//#pragma once  
#ifndef CVVIMAGE_CLASS_DEF  
#define CVVIMAGE_CLASS_DEF  

#include <opencv2\highgui\highgui.hpp>    
class CvvImage  
{  
public:  
    CvvImage();  
    virtual ~CvvImage();  

    virtual bool Create( int width, int height, int bits_per_pixel, int image_origin = 0 );  
    virtual bool Load( const char* filename, int desired_color = 1 );  
    virtual bool LoadRect( const char* filename,  

    int desired_color, CvRect r );  

#if defined WIN32 || defined _WIN32  
    virtual bool LoadRect( const char* filename,int desired_color, RECT r )  
    {  
        return LoadRect( filename, desired_color,  
            cvRect( r.left, r.top, r.right - r.left, r.bottom - r.top ));  
    }  
#endif  

    virtual bool Save( const char* filename );  
    virtual void CopyOf( CvvImage& image, int desired_color = -1 );  
    virtual void CopyOf( IplImage* img, int desired_color = -1 );  
    IplImage* GetImage() { return m_img; };  
    virtual void Destroy(void);  
    int Width() { return !m_img ? 0 : !m_img->roi ? m_img->width : m_img->roi->width; };  
    int Height() { return !m_img ? 0 : !m_img->roi ? m_img->height : m_img->roi->height;};  
    int Bpp() { return m_img ? (m_img->depth & 255)*m_img->nChannels : 0; };  
    virtual void Fill( int color );  
    virtual void Show( const char* window );  

#if defined WIN32 || defined _WIN32  
    virtual void Show( HDC dc, int x, int y, int width, int height,  
        int from_x = 0, int from_y = 0 );  
    virtual void DrawToHDC( HDC hDCDst, RECT* pDstRect );  
    virtual void DrawToHDC( HDC hDCDst, CvRect pDstRect ); 
#endif  

protected:

    IplImage* m_img;

};

typedef CvvImage CImage;

#endif

and CPP file for cvvimage class is following

cvvimage类的CPP文件如下

///////////////////////////////////////////////////////////////////////////////////////////////////
//CvvImage.cpp

#include "StdAfx.h"  
#include "CvvImage.h"
///////////////////////////////////////////////////////////////////////////////////////////////////

CV_INLINE RECT NormalizeRect( RECT r );
CV_INLINE RECT NormalizeRect( RECT r )
{
    int t;
    if( r.left > r.right )
    {
        t = r.left;
        r.left = r.right;
        r.right = t;
    }
    if( r.top > r.bottom )
    {
        t = r.top;
        r.top = r.bottom;
        r.bottom = t;
    }

    return r;
}
CV_INLINE CvRect RectToCvRect( RECT sr );
CV_INLINE CvRect RectToCvRect( RECT sr )
{
    sr = NormalizeRect( sr );
    return cvRect( sr.left, sr.top, sr.right - sr.left, sr.bottom - sr.top );
}
CV_INLINE RECT CvRectToRect( CvRect sr );
CV_INLINE RECT CvRectToRect( CvRect sr )
{
    RECT dr;
    dr.left = sr.x;
    dr.top = sr.y;
    dr.right = sr.x + sr.width;
    dr.bottom = sr.y + sr.height;

    return dr;
}
CV_INLINE IplROI RectToROI( RECT r );
CV_INLINE IplROI RectToROI( RECT r )
{
    IplROI roi;
    r = NormalizeRect( r );
    roi.xOffset = r.left;
    roi.yOffset = r.top;
    roi.width = r.right - r.left;
    roi.height = r.bottom - r.top;
    roi.coi = 0;

    return roi;
}
void FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin )
{
    assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));

    BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);

    memset( bmih, 0, sizeof(*bmih));
    bmih->biSize = sizeof(BITMAPINFOHEADER);
    bmih->biWidth = width;
    bmih->biHeight = origin ? abs(height) : -abs(height);
    bmih->biPlanes = 1;
    bmih->biBitCount = (unsigned short)bpp;
    bmih->biCompression = BI_RGB;
    if( bpp == 8 )
    {
        RGBQUAD* palette = bmi->bmiColors;
        int i;
        for( i = 0; i < 256; i++ )
        {
            palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
            palette[i].rgbReserved = 0;
        }
    }
}
CvvImage::CvvImage()
{
    m_img = 0;
}
void CvvImage::Destroy()
{
    cvReleaseImage( &m_img );
}
CvvImage::~CvvImage()
{
    Destroy();
}
bool CvvImage::Create( int w, int h, int bpp, int origin )
{
    const unsigned max_img_size = 10000;

    if( (bpp != 8 && bpp != 24 && bpp != 32) ||
        (unsigned)w >= max_img_size || (unsigned)h >= max_img_size ||
        (origin != IPL_ORIGIN_TL && origin != IPL_ORIGIN_BL))
    {
        assert(0); // most probably, it is a programming error
        return false;
    }
    if( !m_img || Bpp() != bpp || m_img->width != w || m_img->height != h )
    {
        if( m_img && m_img->nSize == sizeof(IplImage))
            Destroy();

        m_img = cvCreateImage( cvSize( w, h ), IPL_DEPTH_8U, bpp/8 );
    }
    if( m_img )
        m_img->origin = origin == 0 ? IPL_ORIGIN_TL : IPL_ORIGIN_BL;
    return m_img != 0;
}
void CvvImage::CopyOf( CvvImage& image, int desired_color )
{
    IplImage* img = image.GetImage();
    if( img )
    {
        CopyOf( img, desired_color );
    }
}
#define HG_IS_IMAGE(img) \
    ((img) != 0 && ((const IplImage*)(img))->nSize == sizeof(IplImage) && \
    ((IplImage*)img)->imageData != 0)
void CvvImage::CopyOf( IplImage* img, int desired_color )
{
    if( HG_IS_IMAGE(img) )
    {
        int color = desired_color;
        CvSize size = cvGetSize( img ); 
        if( color < 0 )
            color = img->nChannels > 1;
        if( Create( size.width, size.height,
            (!color ? 1 : img->nChannels > 1 ? img->nChannels : 3)*8,
            img->origin ))
        {
            cvConvertImage( img, m_img, 0 );
        }
    }
}
bool CvvImage::Load( const char* filename, int desired_color )
{
    IplImage* img = cvLoadImage( filename, desired_color );
    if( !img )
        return false;

    CopyOf( img, desired_color );
    cvReleaseImage( &img );

    return true;
}
bool CvvImage::LoadRect( const char* filename,
                        int desired_color, CvRect r )
{
    if( r.width < 0 || r.height < 0 ) return false;


    IplImage* img = cvLoadImage( filename, desired_color );
    if( !img )
        return false;
    if( r.width == 0 || r.height == 0 )
    {
        r.width = img->width;
        r.height = img->height;
        r.x = r.y = 0;
    }
    if( r.x > img->width || r.y > img->height ||
        r.x + r.width < 0 || r.y + r.height < 0 )
    {
        cvReleaseImage( &img );
        return false;
    }

    if( r.x < 0 )
    {
        r.width += r.x;
        r.x = 0;
    }
    if( r.y < 0 )
    {
        r.height += r.y;
        r.y = 0;
    }
    if( r.x + r.width > img->width )
        r.width = img->width - r.x;

    if( r.y + r.height > img->height )
        r.height = img->height - r.y;
    cvSetImageROI( img, r );
    CopyOf( img, desired_color );
    cvReleaseImage( &img );
    return true;
}
bool CvvImage::Save( const char* filename )
{
    if( !m_img )
        return false;
    cvSaveImage( filename, m_img );
    return true;
}
void CvvImage::Show( const char* window )
{
    if( m_img )
        cvShowImage( window, m_img );
}
void CvvImage::Show( HDC dc, int x, int y, int w, int h, int from_x, int from_y )
{
    if( m_img && m_img->depth == IPL_DEPTH_8U )
    {
        uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];
        BITMAPINFO* bmi = (BITMAPINFO*)buffer;
        int bmp_w = m_img->width, bmp_h = m_img->height;
        FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin );
        from_x = MIN( MAX( from_x, 0 ), bmp_w - 1 );
        from_y = MIN( MAX( from_y, 0 ), bmp_h - 1 );
        int sw = MAX( MIN( bmp_w - from_x, w ), 0 );
        int sh = MAX( MIN( bmp_h - from_y, h ), 0 );
        SetDIBitsToDevice(
            dc, x, y, sw, sh, from_x, from_y, from_y, sh,
            m_img->imageData + from_y*m_img->widthStep,
            bmi, DIB_RGB_COLORS );
    }
}
void CvvImage::DrawToHDC( HDC hDCDst, RECT* pDstRect ) 
{
    if( pDstRect && m_img && m_img->depth == IPL_DEPTH_8U && m_img->imageData )
    {
        uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];
        BITMAPINFO* bmi = (BITMAPINFO*)buffer;
        int bmp_w = m_img->width, bmp_h = m_img->height;
        CvRect roi = cvGetImageROI( m_img );
        CvRect dst = RectToCvRect( *pDstRect );
        if( roi.width == dst.width && roi.height == dst.height )
        {
            Show( hDCDst, dst.x, dst.y, dst.width, dst.height, roi.x, roi.y );
            return;
        }
        if( roi.width > dst.width )
        {
            SetStretchBltMode(
                hDCDst, // handle to device context
                HALFTONE );
        }
        else
        {
            SetStretchBltMode(
                hDCDst, // handle to device context
                COLORONCOLOR );
        }
        FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin );
        ::StretchDIBits(hDCDst,dst.x, dst.y, dst.width, dst.height,roi.x, roi.y, roi.width, roi.height,\
            m_img->imageData, bmi, DIB_RGB_COLORS, SRCCOPY );
    }
}
void CvvImage::DrawToHDC( HDC hDCDst, CvRect pDstRect )
{
    RECT rDest=CvRectToRect(pDstRect);
    DrawToHDC(hDCDst,&rDest);
}
void CvvImage::Fill( int color )
{
    cvSet( m_img, cvScalar(color&255,(color>>8)&255,(color>>16)&255,(color>>24)&255) );
}

enjoy.

享受。

#2


1  

1.first load a picture get pic name and path.

1。首先载入图片获得图片名称和路径。

void CvlistDlg::OnBnClickedRead()
{
    CString     FilePathName;
    CString     FileName;
    CFileDialog openVideo(true);
    openVideo.m_ofn.lpstrTitle = _T("Open");
    if (IDOK == openVideo.DoModal()){
        FileName = openVideo.GetFileName();
        FilePathName = openVideo.GetPathName();
        _currentFile._fileName = FileName;
        _currentFile._filePath = FilePathName;
    }
 }

2.add follow code in your button callback function.

2。在按钮回调函数中添加follow代码。

void CvlistDlg::OnBnClickedOk(){
    cv::Mat img = cv::imread(str);
    CDC *pDC = GetDlgItem(IDC_Pic)->GetDC();
    HDC hDC = pDC->GetSafeHdc();
    CRect rect;
    GetDlgItem(IDC_Pic)->GetClientRect(&rect);
    int rw = rect.right - rect.left;     //the width of your picture control
    int rh = rect.bottom - rect.top;
    if (!img.data){
        MessageBox(_T("read picture fail!"));
        return;
    }
    cv::resize(img, img, cv::Size(rw, rh));     
    IplImage iplimg = img;
    m_CVvImageObj.CopyOf(&iplimg);
    UpdateData();
    if (m_CVvImageObj.GetImage()){
        m_CVvImageObj.Show(pDC->GetSafeHdc(), 0, 0, rw, rh);
    }
}

I hope those can give you some help.

我希望他们能给你一些帮助。

#3


0  

You don't need of IplImage. Basically you can draw a cv::Mat to a DC of a MFC control, using StretchDIBits. It accepts pointer to memory block where the bitmap is stored... in this case cv::Mat.data

你不需要IplImage。基本上,您可以使用担架将cv: Mat绘制到MFC控件的DC。它接受一个指向内存块的指针,在这个块中存储位图。在这种情况下简历::Mat.data

But remember that (this make me crazing before)

但是记住这一点(这让我很疯狂)

  • GDI requires DWORD alignment while cv::Mat don't use any rows padding
  • GDI需要DWORD对齐,而cv::Mat不使用任何行填充。
  • In addition your Mat could be a ROI this means that at the end each rows there isn't next row but the image that continues
  • 此外,您的Mat可能具有ROI,这意味着在每一行的末尾都没有下一行,只有继续运行的映像

You can have DWORD alignment in OpenCV using images where cols % 4 == 0 so you can add a border to your image

您可以在OpenCV中使用cols % 4 = 0的图像进行DWORD对齐,以便向映像添加边框

  border = 4 - (img.cols % 4);
  if ( (border<4 && border > 0) || img.isContinuous() == false)
  {
    cv::copyMakeBorder(img, tmpImg, 0, 0, 0, border, cv::BORDER_CONSTANT, 0);
  }
  else
    tmpImg = img

Using copyMakeBorder you will solve both requirements

使用copyMakeBorder将解决这两个需求

Another issues is grey images because MFC requires a flat palette to display it. You can convert your Mat with cvtColor or create the palette:

另一个问题是灰色图像,因为MFC需要一个平面调色板来显示它。您可以转换您的席与cvtColor或创建调色板:

   uchar buffer[sizeof(BITMAPINFO) + 1024];
   BITMAPINFO* bmi = (BITMAPINFO*)buffer;
   BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);
   bmih->biBitCount = 8*img.elemenSize()
   bmih->biWidth = tmpImg.cols;
   bmih->biHeight = -tmpImg.rows;// DIB are bottom ->top
   bmih->...

  //The palette is required for grey image
  if (bmih->biBitCount == 8)
  {
    RGBQUAD* palette = bmi->bmiColors;
    for (int i = 0; i < 256; i++)
    {
      palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
      palette[i].rgbReserved = 0;
    }
  }

finally draw to HDC

最后画HDC

imgH = img.rows;
imgW = img.cols; //use original cols  to avoid border

ClientDC hDC(WinCtrl);

//rr is relative to control
RECT rr; WinCtrl->GetClientRect(&rr);  

StretchDIBits(hDC,
  0, 0, rr.right, rr.bottom,
  0, 0, imgW, imgH,
  tmpImg.data, bmi, DIB_RGB_COLORS, SRCCOPY);

You can find detailed info and a class to manage image fitting here: http://www.pklab.net/?&id=390&lang=EN&t=How-to-display-an-OpenCV-image-or-video-in-your-own-MFC-interface

您可以在这里找到详细的信息和管理图像匹配的类:http://www.pklab.net/?