OpenCV学习笔记(基于OpenCV 2.4)二:图像的加载显示及简单变换

来源:互联网 发布:extjs object转json 编辑:程序博客网 时间:2024/05/20 11:47


转载:http://www.coridc.com/archives/2639.html (感谢贝壳里的海的无私奉献)

摘要(Abstract) 通过笔记一的学习,我们已经能够下载、安装OpenCV并新建VS2010项目进行相关的配置,笔记一也已完成第一个程序HelloCV的演示。本文首先通过详细介绍OpenCV中如何从硬盘加载/读取一幅图像,并在窗口中进行显示来对笔记一中的演示程序做详解。其次,本文实现了简单的图像变换,将一幅RGB颜色的图片lena.jpg转化成灰度图像,以达到修改的目的,另外,在此变换中,我们还对如何将图片保存到硬盘上进行讲解。实验结果表明,通过笔记二的学习,不但能够增强对OpenCV的学习兴趣,还能有初体验OpenCV的成就感,吃嘛嘛香,为后续的学习打下坚实的基础。

关键词(Keywords):OpenCV;imread;namedWindow;imshow;cvtColor;imwrite;

1、加载并显示图像(Load and Display an Image)

1.1 学习目标

在本节中,我们预期达到以下学习目标:1) 加载一幅图像(采用imread方法);2)创建一个指定的OpenCV窗口(采用namedWindow方法);3)在OpenCV窗口中显示图像(采用imshow方法)。

1.2 源代码

#include “StdAfx.h”

#include <string>

#include <iostream>

#include <opencv2\core\core.hpp>

#include <opencv2\highgui\highgui.hpp>

 

using namespace cv;

using namespace std;

 

int main()

{

         string imageName = “lena.jpg”;

         //读入图像

         Mat img = imread(imageName, CV_LOAD_IMAGE_COLOR);

 

         //如果读入图像失败

         if (img.empty())

         {

                   cout<<”Could not open or find the image!”<<endl;

                   return -1;

         }

 

         //创建窗口

         namedWindow(“lena”, CV_WINDOW_AUTOSIZE);

 

         //显示图像

         imshow(“lena”, img);

 

         //等待按键,按键盘任意键返回

         waitKey();

 

         return 0;

}

1.3 源码详解

1.3.1 头文件

OpenCV有许多不同的模块,每个模块关心图像处理中不同的领域及方法(参见:OpenCV学习笔记(基于OpenCV 2.4)一:哈喽CV),在使用之前我们首先需要对相应的头文件进行包含,一般情况下我们都会用到的两个模块:

1)core section. 这里定义了OpenCV的一些基本的块(Blocks);

2)highgui module. 该模块包含了一些图像的输入输出操作(UI)。

另外,为了能够在控制台做输入输出,我们会包含iostream,而string是用于字符串的处理。接下来,为了防止OpenCV的数据结构或命名与其它库函数比如STL有冲突,我们引入命名空间cv,在有冲突的情况下可以用前缀cv::来指定具体使用哪个库(关于命名空间,我们会在下一讲做详细介绍)。

1.3.2 主函数


①Mat img = imread(imageName, CV_LOAD_IMAGE_COLOR);


imread的函数原型是:Mat imread( const string& filename, int flags=1 );

Mat是OpenCV里的一个数据结构,在这里我们定义一个Mat类型的变量img,用于保存读入的图像,在本文开始有写到,我们用imread函数来读取图像,第一个字段标识图像的文件名(包括扩展名),第二个字段用于指定读入图像的颜色和深度,它的取值可以有以下几种:

1) CV_LOAD_IMAGE_UNCHANGED (<0),以原始图像读取(包括alpha通道),

2) CV_LOAD_IMAGE_GRAYSCALE ( 0),以灰度图像读取

3) CV_LOAD_IMAGE_COLOR (>0),以RGB格式读取

这三点是在OpenCV的官方教程(opencv_tutorials.pdf)里摘录并翻译过来的,但是网上还有关于CV_LOAD_IMAGE_ANYDEPTH和CV_LOAD_IMAGE_ANYCOLOR的传说,而且查看OpenCV的源码可以发现,这些取值放在一个枚举(enum)类型中(opencv\build\include\opencv2\highgui\highgui_c.h),定义如下:

enum

{

/* 8bit, color or not */

    CV_LOAD_IMAGE_UNCHANGED  =-1,

/* 8bit, gray */

    CV_LOAD_IMAGE_GRAYSCALE  =0,

/* ?, color */

    CV_LOAD_IMAGE_COLOR      =1,

/* any depth, ? */

    CV_LOAD_IMAGE_ANYDEPTH   =2,

/* ?, any color */

    CV_LOAD_IMAGE_ANYCOLOR   =4

};

关于该枚举类型的详细信息,官方教程的写法跟官方发布的正式版代码描述的不相同,可能是我理解不够深入,或者两者是等价的,这点以后再找时间研究,但这并不影响我们对这一章节的学习。

Note:OpenCV提供了多种格式图像的支持,包括Windows bitmap(bmp),portable image formats (pbm, pgm,ppm) 以及 Sun raster (sr, ras)。关于其它的格式,有JPEG (jpeg, jpg, jpe),JPEG 2000,TIFF 文件 (tiff, tif),portable network graphics (png),还有openEXR格式,如果OpenCV是自己打包的话,读取这些格式需要有插件支持,如果是官方提供的库,则不需再添加插件。

 

在检查图像是否读取成功之后,我们需要显示读入的图像,因此,我们采用namedWindow函数来创建一个OpenCV窗口,该函数的定义如下:

CV_EXPORTS_W void namedWindow(const string& winname, int flags = WINDOW_AUTOSIZE);

为此,我们需要指定该窗口的名称(窗口标识符, window identifier)以及如何处理窗口大小。①窗口标识符需要唯一指定,如果已经存在一个该名字的窗口,则此函数不进行任何处理;②flags参数目前只支持CV_WINDOW_AUTOSIZE,在highgui_c.h中,OpenCV定义了CV_WINDOW_AUTOSIZE= 0×00000001,如果设置该参数,则表示显示的时候窗口自适应于需要显示的图像,而且不能修改窗口大小,如果不设置(省略此参数),可以通过代码进行修改;③如果将OpenCV用于Qt后端开发,该参数还支持其它值,具体可查看OpenCV开发文档,这里不再赘述。


②imshow(“lena”, img);


imshow用于在我们创建的窗口中显示需要显示的图像,其函数原型为:

void imshow(const string& winname, InputArray mat);

第一个参数winname是指窗口的名称,也就是窗口标识符,第二个参数mat就是我们要显示的图像了。正如我们在namedWindow函数中所描述的那样,如果namedWindow指定了参数CV_WINDOW_AUTOSIZE,则图像会按原始大小显示,否则图像会根据窗口大小进行缩放。


③waitKey();


这条语句表示等待用户键盘操作,waitKey函数的函数原型如下:

int waitKey(int delay = 0);

我们可以看到,该函数可包含一个整形参数,不设置参数的情况下,默认为0,也就是无限制等待。该整数表示需要等待用户操作的毫秒数。

2 加载、修改并保存图像(Load, Modify, and Save an Image)

2.1 学习目标

在这一章,我们将学习:1)加载一副图像(采用imread函数,同第一章);2)将一副图像从RGB格式转换成灰度图(grayscale,采用cvtColor函数);3)保存转换后的图像到磁盘上(采用imwrite函数)。

2.2 源代码

<pre lang=”cpp”>

#include “StdAfx.h”

#include <cv.h>

#include <highgui.h>

#include <string>

 

using namespace cv;

using namespace std;

 

int main()

{

         char* imageName = “lena.jpg”;

         Mat image = imread(imageName, 1);

 

         if (!image.data)

         {

                   cout<<”Could not open or find the image!”<<endl;

                   return -1;

         }

 

         Mat gray_image;

         String grayImageName = “lena_gray”;

 

         cvtColor(image,gray_image,CV_RGB2GRAY);//将RGB图像转换成灰度图像

         imwrite(“../../lena_gray.jpg”,gray_image);//保存图像

 

         namedWindow(imageName, CV_WINDOW_AUTOSIZE);//创建用于显示元图像窗口

         namedWindow(grayImageName,CV_WINDOW_AUTOSIZE);//创建用于显示转换后图像窗口

 

         imshow(imageName,image);

         imshow(“grayImageName”, gray_image);

 

         waitKey(0);

         return 0;

}

</pre>

2.3 源码详解

有了第一章的基础后,再来理解本章代码相对就很容易,在这一节,关于imread函数的使用则不再赘述,下面给cvtColor和imwrite来一个特写。


①cvtColor(image,gray_image,CV_RGB2GRAY);// 将RGB图像转换成灰度图像


cvtColor函数用于将图像从一个颜色空间转换到另一个颜色空间,其函数原型为:

void cvtColor( InputArray src, OutputArray dst, int code, int dstCn=0 );

参数src:是指需要转化的图像,可以是8位或16位等的无符号型或者是单精度浮点型(Single-Precision Floating-Point);

参数dst:与原始图像具有相同大小和深度的目标图像;

参数code:颜色空间转换代码;

参数dstCn:目标图像的通道数,如果该参数为0,则通道数可由src和code自动获得;

对于一个原图像或目标图像是RGB的转换,我们需要详细地指定通道的顺序(RGB or BGR)。我们注意到,OpenCV默认情况下的颜色格式一般是指RGB,但实际上却进行了一个反转变成BGR,因此对一个标准的24位图像来说,其第一个字节为8位的蓝色部分(Blue Component),其次是绿色,接着是红色,再然后就是第二个像素,同样以BGR的通道顺序排列。

常规的RGB通道的值的范围如下:

对于8位无符号精度图像(CV_8U Images),其范围是0~255

对于16位无符号精度图像(CV_16U Images),其范围是0~65535

对于32位单精度浮点型图像(CV_32F Images),其范围是0~1

在线性变换的情况下,我们可以不用考虑其通道的取值范围,但对于非线性变换(Non-Linear Transformation),一个RGB输入图像应该先做规格化处理(Normalized),以便得到一个合适的范围来获取正确的结果。比如对于一个RGB颜色空间到LUV颜色空间的变换,如果我们需要将一副8位图像转换到一副32位的浮点型精度图像而不进行任何缩放,也就是说,我们将一个从0~255的范围替换成0~1的范围,那么我们首先要将图像按比例缩小(Scale the Image Down):

img *= 1./255;

cvtColor(img, img, CV_BGR2Luv);

如果我们采用8位的图像进行转换,该过程中可能会有信息的丢失,尽管在一般的应用中,这种丢失并不明显(Noticeable),但我们强烈建议使用一个32位的图像或者在变换之前先转换成32位。

备注:关于参数code的跟多取值,可以参见OpenCV 2.4.0官方文档:cvtColor函数指南及使用方法


 

②imwrite(“../../lena_gray.jpg”,gray_image);// 保存图像


imwrite函数用于将图像保存到指定的文件,其函数原型为:

bool imwrite(const string& filename, InputArray image, const vector<int>& params=vector<int>())

参数filename:指代需要保存文件的名称

参数image:需要保存的图像

参数params:保存至指定格式图像格式时的参数设置

关于params参数的取值如下:

对JPEG图像,它表示图像质量(CV_IMWRITE_JPEG_QUALITY),取值从1~100,值越大质量越高,默认为95;

对PNG图像,它表示图像压缩率(CV_IMWRITE_PNG_COMPRESSION),取值从0~9,值越大压缩率越大压缩时间越长,默认值为3;

对PPM,PGM或PBM,它是一个二进制标识(CV_IMWRITE_PXM_BINARY),取值为0或1,默认为1。

有关于该函数及参数params的详细信息及应用可参见开发文档:imwrite函数指南及使用方法

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 唯品会在线支付后商品有问题怎么办 红米手机把时间删了怎么办 红米桌面上的时间删了怎么办 华为手机玩游戏老是闪退怎么办 别人家无线网距离太远信号差怎么办 微信公众号交话费交错了怎么办 手机卡里还有话费销户的话怎么办 号码忘记交话费变成空号怎么办 多屏互动没办法隔空播放怎么办? 一个人长期受一件事的打击怎么办 物流信息显示快递被别人签收怎么办 现在打工的人被领导骂怎么办 加密狗丢了打不开软件了怎么办 手机微信可以打开网页打不开怎么办 手机中国网打开网速慢该怎么办 在韩国用中国软件网速特别慢怎么办 淘宝退货快递一直没显示到货怎么办 高二美术生集训时文化课怎么办 唯品会不支持7天无理由退货怎么办 sy来4am了孤存怎么办 淘宝网买的电器坏了怎么办 在闲鱼上买的电器是坏的怎么办 打开时全屏不知变成小屏怎么办 苹果6s原装数据线不充电怎么办 vivo手机安卓系统耗电快怎么办 电视机机顶盒插了电源开不了怎么办 苹果手机更新系统后老是闪退怎么办 16g苹果6s手机内存不足怎么办 苹果以前浏览器页面忽然没了怎么办 白衬衣被别的衣服染了怎么办 把宝贝标题改了没访客了怎么办 微信公众号看不到评论时间了怎么办 微店退款退货买家发空快递怎么办 微信二维码收款顾客少付款了怎么办 江西高考二本差5分上线怎么办 湖南文科考生二本上线差两分怎么办 在商场试鞋自己鞋子被偷怎么办 网易账号忘记密码更换手机了怎么办 一人在外地钱花光了怎么办 银行卡被公安冻结卡里的钱怎么办 在店铺不上班了押工资了怎么办?