本图像是基于对话框为基础上而建立的。
在图像框中打开图像需要一个基本的函数CvvImage。因为有了这个函数才能够很方便的调用其完成将cv格式的图像转换成VS所能显示的图像。但是遗憾的是,在opencv2.2中并不存在这个函数,不知道opencv2.3中有没有。但是没有这个函数我们也一样可以用它。具体方法如:
现在开始来建立一个打开图像的程序了:
第一步:首先创建一个MFC对话框应用程序(Dialog-based Application),这一步并不难只要按默认设置就可以了;但是有一点要注意:
最下面的“Use Unicode libraries”最好去掉。如果勾选了这个选项,程序代码就会使用16bit的Unicode字符集来编码,但是很多函数虽然使用 char* (ASCII stings) 类型字符,而将字符串从 Unicode 转换到 ASCII 是非常麻烦的。使用 Unicode 在编译时可能会遇到下列错误:
cannot convert parameter 1 from 'CString' to 'const char *' cannot convert from 'const char [11]' to 'LPCWSTR'
这意味着在Unicode和Multi-byte字符串的转换中出现了问题。
第二步:创建对话框框架
第三步:对程序初始化
首先定义图像:
IplImage* img_src;//定义原始图像
IplImage* img_gray;//灰度图像定义
其次初始化图像:这一点非常重要因为后面要用到,否则即使能够编译,也不一定能实现打开图像。
CvSize ImgSize; //定义图像的尺寸大小;
ImgSize.height = IMAGE_HEIGHT; //图像高度;
ImgSize.width = IMAGE_WIDTH; //图像宽度;
img_src = cvCreateImage( ImgSize, IPL_DEPTH_8U, IMAGE_CHANNELS ); //创建图像模板;
其中的几个参数在 #include "resource.h" 下加入如下代码:
#include "cv.h" #include "highgui.h"
#define IMAGE_WIDTH 256
#define IMAGE_HEIGHT 256
#define IMAGE_CHANNELS 3
第四步,编写图像打开和显示函数
打开显示函数主要的触发是同按钮来实现,其主要函数如下:
void CParorize_exe2Dlg::OnBnClickedBtnShowpic() { CFileDialog dlg( TRUE, _T("*.bmp;*.jpg;*.tif"), NULL, OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, _T("image files All Files (*.*) |*.*||"), NULL ); // 选项图片的约定; dlg.m_ofn.lpstrTitle = _T("打开图片"); // 打开文件对话框的标题名;(*.bmp; *.jpg) |*.bmp; *.jpg | if( dlg.DoModal() == IDOK ) // 判断是否获得图片; { if(dlg.GetFileExt()!="bmp" && dlg.GetFileExt()!="jpg"&&dlg.GetFileExt()!="tif") { AfxMessageBox(_T("请选择正确的图片格式!"),MB_OK); return; } CString mPath = dlg.GetPathName(); // 获取图片路径; IplImage* ipl = cvLoadImage( mPath ); // 读取图片、缓存到一个局部变量ipl中; if( !ipl ) // 判断是否成功载入图片; return; if( img_src ) // 对上一幅显示的图片数据清零; cvZero( img_src ); ResizeImg( ipl ); // 对读入的图片进行缩放,使其宽或高最大值者刚好等于 256,再复制到 TheImage 中; ShowImg( img_src, IDC_SHOWPIC ); // 调用显示图片函数; cvReleaseImage( &ipl ); // 释放 ipl 占用的内存; } }
这个函数不是我写的,是盗用人家的,嘿嘿!不过里面有几个注意点:
a. IplImage* ipl = cvLoadImage( mPath ); 这地方容易出错,如果你没有按照第一步的操作的话:“Use Unicode libraries”最好去掉!一般是编译不过去。那么要是现在初现这个问题,我们是不是要重新来过呢?不必啊!亡羊补牢,并不晚。具体操做是:
可以通过s.Format(_T("%d"), i);方法来消除错误。另外也可以把unicode字符集的设置去掉,方法是:
项目 -> 属性 -> 配置属性 -> 常规 -> 字符集 由"使用 Unicode 字符集" 改为 "未设置"。
b.刚刚上面讲的初始化的情况,cvZero( img_src ) ;如果没有对img_src初始化,就会初现错误。
c. 里面有两个重要的显示函数,ResizeImg( ipl );ShowImg( img_src, IDC_SHOWPIC );还得好好想想怎么实现。
具体代码如下:
在头文件中定义:
void ResizeImg(IplImage* img);
void ShowImg(IplImage* img, UINT ID);
void CParorize_exe2Dlg::ResizeImg( IplImage* img ) { // 读取图片的宽和高; int w = img->width; int h = img->height; // 找出宽和高中的较大值者; int max = (w > h)? w: h; // 计算将图片缩放到TheImage区域所需的比例因子; float scale = (float) ( (float) max / 300.0f ); // 缩放后图片的宽和高; int nw = (int)( w/scale ); int nh = (int)( h/scale ); // 为了将缩放后的图片存入 SrcImage 的正中部位,需计算图片在 SrcImage 左上角的期望坐标值; int tlx = (nw > nh)? 0 : (int)(300-nw)/2; int tly = (nw > nh)? (int)(240-nh)/2 : 0; // 设置 SrcImage 的 ROI 区域,用来存入图片 img; cvSetImageROI( img_src, cvRect( tlx, tly, nw, nh) ); // 对图片 img 进行缩放,并存入到 SrcImage 中; cvResize( img, img_src ); // 重置 SrcImage 的 ROI 准备读入下一幅图片; cvResetImageROI( img_src ); } void CParorize_exe2Dlg::ShowImg( IplImage* img, UINT ID ) { CDC* pDC = GetDlgItem( ID ) ->GetDC(); // 获得显示控件的 DC; HDC hDC = pDC ->GetSafeHdc(); // 获取 HDC(设备句柄) 来进行绘图操作; CRect rect; GetDlgItem(ID) ->GetClientRect( &rect ); int rw = rect.right - rect.left; // 求出图片控件的宽和高; int rh = rect.bottom - rect.top; int iw = img->width; // 读取图片的宽和高; int ih = img->height; int tx = (int)(rw - iw)/2; // 使图片的显示位置正好在控件的正中; int ty = (int)(rh - ih)/2; SetRect( rect, tx, ty, tx+iw, ty+ih ); CvvImage cimg; cimg.CopyOf( img ); // 复制图片; cimg.DrawToHDC( hDC, &rect ); // 将图片绘制到显示控件的指定区域内; ReleaseDC( pDC ); }
这样一段代码也不是我自己的,借来用了,但是很实用哦!经过这样几番折腾图像显示就可以实现了。还等什么呢?