2012-10-15 31 views
0

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

我的应用程序是MFC SDI和内部视图我骑在OnPaint功能。在以前的OpenCV我使用画图功能一样

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()); 
    } 


} 

请指引我这是阶级的是最新版本的做同样的事情,并支持MFC这样的DC控制。

+0

什么当你运行你的代码时你得到了什么? –

+0

这个代码是有这个cvvimage选项的旧代码。我想知道我应该在新的opencv 2.4中使用什么。为同样的功能 – wolvorinePk

回答

1

因为我找不到答案,我想帮助别人我做了什么。

我已经手动cvvimage类提取,并在我的项目相加,然后我做了以下..

在我的意见

头文件,我宣布

CvvImage m_CVvImageObj; 
cv::Mat m_matImage; 

来看我的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(); 

以下的OnPaint的overided函数内部视图我增加

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

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 

和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)); 
} 

享受。

1

1.first load a picture获取图片名称和路径。

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跟随您的按钮回调函数中的代码。

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); 
    } 
} 

我希望那些能给你一些帮助。

0

你不需要IplImage。基本上你可以使用StretchDIBits来绘制一个cv :: Mat到一个MFC控件的DC。 它接受存储位图的内存块的指针......在这种情况下cv :: Mat。数据

但请记住,(这让我之前龟裂)

  • GDI需要DWORD对齐,而CV ::垫不使用任何行填充
  • 另外你垫可能是一个投资回报率这一手段,在年底各行没有下一行而是继续

你可以有DWORD对齐OpenCV中使用的图像,其中的cols%4 == 0,所以你可以添加一个边框图像图像

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 

使用copyMakeBorder将解决两方面的要求

另一个问题是灰度图像,因为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; 
    } 
    } 

终于画到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); 

您可以找到详细的信息和类来管理图像固定在这里: http://www.pklab.net/?&id=390&lang=EN&t=How-to-display-an-OpenCV-image-or-video-in-your-own-MFC-interface