VS2010 + openCV2.4.9 利用MFC把图片显示在pictureControl上,并可以输出灰度图和二值图像

学习openCV也有一段时间了,今天想着怎么把图片显示在MFC上,就开始百度找案例和方法,结合了许多大神的博客,总结了他们的东西,完成了自己想要的东西,把自己做的过程贴出来,仅供参考。

参考的其中三个博客链接如下:

https://blog.csdn.net/sunrong0511/article/details/52052692

https://blog.csdn.net/wht18720080085/article/details/69259241

https://blog.csdn.net/sxlsxl119/article/details/51258998

1.建立MFC工程文件


2,

由于以后的代码会用到CvvImage类,而opencv2.3以后就去掉了对它的支持,这里先介绍添加CvvImage支持的方法,直接能用的可以略过这一步。


点“头文件”和“源文件”,单击右键,新建项

 
 
这里附上两个文件的源码方便使用:
CvvImage.h
 
  
#pragma once
#ifndef CVVIMAGE_CLASS_DEF
#define CVVIMAGE_CLASS_DEF
#include "opencv.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 );
#endif
protected:
IplImage * m_img ;
};
typedef CvvImage CImage ;
#endif


CvvImage.cpp

#include "StdAfx.h"
#include "CvvImage.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
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 :: Fill ( int color )
{
cvSet ( m_img , cvScalar ( color & 255 ,( color >> 8 ) & 255 ,( color >> 16 ) & 255 ,( color >> 24 ) & 255 ) );
}

3.在需要引用该类的地方添加如下引用:
在newgrayANDbwDlg.cpp中添加包含头文件:

在newgrayANDbwDlg.h 中添加包含文件:



4.添加显示图片函数DrawPicToHDC,在类视图中,在cnewgrayANDbwDlg单击右键添加void类型函数


(注:此时,我们要添加的是UINT型和IplImage型,在这里可能添加不成,就不必在此添加参数名和参数列表,后面自己在函数里面添加)


自己讲“void”改为“IplImage * img, UINT ID”:

void CnewgrayANDbwDlg::DrawPicToHDC(IplImage * img, UINT ID)
{
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);  


}
IplImage *Src=NULL;  
IplImage *TheImage=NULL;  

CString m_strPicPath;//弹出选择图片对话框 

(注:最后三行要在大括号外,否则会报错,且这个函数必须在其他的控件之前,否则会报错:没有定义的标识符

改完了newgrayANDbwDlg.cpp这个里面的参数名,还要改newgrayANDbwDlg.h里面的 ):



5.为控件“打开文件”、“灰度图”和“二值图”添加消息响应函数,双击控件,在各自的函数框中添加如下函数:

void CnewgrayANDbwDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
   CFileDialog dlg(true,_T("*.bmp"),NULL,OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,_T("image file(*.bmp;*.jpg)|*.bmp;*.jpg|All Files(*.*)|*.*|"),NULL);  
dlg.m_ofn.lpstrTitle = _T("Open Image");// 打开文件对话框的标题名  
if( dlg.DoModal() != IDOK )        // 判断是否获得视频  
return;  
m_strPicPath = dlg.GetPathName();           //获取图片路径  
m_strPicPath.Replace(_T("//"),_T("////"));  
TheImage=cvLoadImage((CT2CA)m_strPicPath,1); //读取彩色图  
DrawPicToHDC(TheImage,IDC_STATIC); 
}

void CnewgrayANDbwDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
Src = cvLoadImage((CT2CA)m_strPicPath,0);//读取灰度图片  
    DrawPicToHDC(Src,IDC_STATIC); 
}

void CnewgrayANDbwDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
   cvCvtColor(TheImage,Src,CV_BGR2GRAY);  
   IplImage *dst=cvCreateImage(cvGetSize(Src),IPL_DEPTH_8U, 1);  
    cvThreshold(Src,dst,40, 255 ,CV_THRESH_BINARY);  
    DrawPicToHDC(dst,IDC_STATIC); 

}


6.编译运行,效果图如下:




上面的描述已经很清楚了,按照这个一步步做就可以做出来,这里贴出我做的整个工程文件,下载下来解压缩,在配置了openCV的VS上可以直接

编译运行,有兴趣的可以下载。

下载链接:https://download.csdn.net/my

猜你喜欢

转载自blog.csdn.net/qq_40969467/article/details/80720286
今日推荐