现在的位置: 首页 > 综合 > 正文

Opencv学习之旅1—打开并显示图像

2012年06月13日 ⁄ 综合 ⁄ 共 3321字 ⁄ 字号 评论关闭

 本图像是基于对话框为基础上而建立的。

在图像框中打开图像需要一个基本的函数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 );

}

这样一段代码也不是我自己的,借来用了,但是很实用哦!经过这样几番折腾图像显示就可以实现了。还等什么呢?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

抱歉!评论已关闭.