OpenCV基本操作——OpenCV从入门到实战(二)

OpenCV的大部分函数都是在cv的命名空间,所以在每个使用OpenCV函数的cpp文件头(不建议将命名空间的引入写在.h文件)部加上一句:using namespace cv;


但是,在实际应用的过程当中,我们发现,为了更加凸显出我们所以调用的函数来自于OpenCV,我们建议的写法是在函数、类、结构体等的前面显示地加入命名空间。


例如:

cv::MatmatSrc;

cv::RectrcROI;

cv::PointptPosition;


  1 读入图像imread()  

在OpenCV支持C++接口以后,图像的管理由Mat类进行实现。所以,在OpenCV中,所有的图像都可以用Mat对象来存。读取一副图像的函数由imread函数实现。imread函数原形为:

 

CV_EXPORTS_W Mat imread(conststring&filename,intflags=1); 

filename参数表示:图像的名称。

OpenCV支持的图像类型如下: 

Windows位图-*.bmp,*.dib;

JPEG文件-*.jpeg,*.jpg,*.jpe;

JPEG2000文件-*.jp2;

PNG图片-*.png 

便携文件格式-*.pbm,*.pgm,*.ppmSunraster;

光栅文件-*.sr,*.ras;

TIFF文件-*.tiff,*.tif 


flagship参数表示:读取的参数,默认为1。枚举声明如下:

enum{

IMREAD_UNCHANGED=-1,

IMREAD_GRAYSCALE=0,

IMREAD_COLOR=1,

IMREAD_ANYDEPTH=2,

IMREAD_ANYCOLOR=4

};


IMREAD_UNCHANGED:表示不对图像进行任何处理,按照原始图像类型将图像载入。IMREAD_GRAYSCALE:表示总是将真彩图像转化为灰度图像进行载入。

IMREAD_ANYDEPTH:表示不改变原始图像的位宽。比如32位深度图像载入便是相应的深度图像。

IMREAD_ANYCOLOR:表示总是以真彩模式将图像载入。


  4. 显示图像  

OpenCV矩阵的显示函数的调用有两种方式:一是提前建立显示窗口,然后再调用显示函数;二是直接调用显示函数。矩阵的显示按照显示比例可分为:1:1原图显示和自适应窗体大小显示。


  1.1  创建窗口namedWindow()  

函数原形如下:

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


其中,winname表示窗体名字;nflags表示显示的比例,对应的枚举变量声明为:

WINDOW_NORMAL:用户可以改变窗口大小,图像将自动填满窗体;

WINDOW_AUTOSIZE:用户不能改变窗体大小,1:1进行显示(默认值);

WINDOW_OPENGL:支持OpenG。


  1.2 窗体图像显示imshow()  

函数原形如下:

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


其中,winname表示窗体名字;mat表示你将要显示的矩阵;imshow函数对图像数据的缩放功能取决于图像的深度:


如果图像是8位无符号类型(8-bitunsigned),就按照原始灰度值进行映射;如果图像是16位无符号类型(16-bitunsigned)或32位整型(32-bitinteger),像素值除以256;如果图像是32位浮点型(32-bitfloating-point),像素值乘以255。


注:当不预先建立窗体,直接调用显示函数,将以1:1的方式进行展示。


  5. 保存图像 imwrite()  

原形声明如下: 

CV_EXPORTS_W bool imwrite(const string& filename, InputArray img, constvector<int>&params=vector<int>()); 


其中:

filename为所需保存图像的文件名,文件名需要带有图像格式后缀的。目前OpenCV该函数只支持JPEG,PNG,PPM,PGM,TIIF等。 


img为图像数据。目前OpenCV主要只支持单通道和3通道的图像,并且此时要求其深度为8bit和16bit无符号(即CV_16U)。 


params是用来设置对应图片格式的压缩参数,默认为空。


  6. 图像矩阵Mat  

Mat是OpenCV最基本的数据结构,Mat即矩阵(Matrix)的缩写,Mat数据结构主要包含2部分:Header和Pointer。Header中主要包含矩阵的大小,存储方式,存储地址等信息;Pointer中存储指向像素值的指针。


关于Mat的定义见core.hpp的class CV_EXPORTS Mat。 


  1.3 Mat的参数  

rows –的行数。

cols– 的列数。

size –替代矩阵大小规格Size(cols, rows)的方法。

type – 创建的矩阵的类型。


  1.4 Mat初始化  

Mat(int _rows, int _cols, int _type, const Scalar& _s);

Mat(const IplImage* img, bool copyData=false);


IplImage*是C语言操作OpenCV的数据结构,在当时C操纵OpenCV的时候,地位等同于Mat,OpenCV为其提供了一个接口,很方便的直接将IplImage转化为Mat,即使用构造函数。


  1.5 Mat复制  

Mat包括头和数据指针,当使用Mat的构造函数初始化的时候,会将头和数据指针复制(注意:只是指针复制,指针指向的地址不会复制),若要将数据也复制,则必须使用copyTo或clone函数


  1.6 Mat数据存储  

灰度图(单通道)存储按行列存储;三通道RGB存储方式如下,每列含有三个通道。


为了加快访问的速度,openCV往往会在内存中将像素数据连续地存储成一行,isContinus()函数的作用就是用于判断是否连续存储成一行。存储成一行有什么好处呢?给定这行的头指针p,则只要使用p++操作就能逐个访问数据。


因此当判断存放在一行的时候,可以通过数据指针++很容易遍历图像像素:


  1.7  兴趣区间ROI  

在图像处理领域,我们常常需要设置感兴趣区域(ROI,region of interest),来专注或者简化我们的工作过程 。也就是从图像中选择的一个图像区域,这个区域是我们图像分析所关注的重点。


我们圈定这个区域,以便进行进一步处理。而且,使用ROI指定我们想读入的目标,可以减少处理时间,增加精度,给图像处理来带不小的便利。


ROI区域定义有两种方法。

原图:Mat imageSrc;  

ROI图:Mat imageROI; 


  1.7.1  cv::Rect  

cv::Rect表示一个矩形区域。指定矩形的左上角坐标(构造函数的前两个参数)和矩形的长宽(构造函数的后两个参数)就可以定义一个矩形区域。


imageROI = imageSrc (Rect(x1, y1, w, h));


  1.7.2   cv::Range  

cv::Range是指从起始索引到终止索引(不包括终止索引)的一连段连续序列。cv::Range可以用来定义Range。如果使用cv::Range来定义ROI,那么前例中定义ROI的代码可以重写为:


imageROI = imageSrc (Range(x1, x2),Range(y1, y2));


  1.8  颜色分离与合成  


  1.8.1  分离颜色通道 split()  

原函数:

void split(const Mat& src,  Mat*mvbegin);  

void split(InputArray m, OutputArrayOfArrays mv);


第一个参数,InputArray类型的m或者const Mat&类型的src,填我们需要进行分离的多通道数组。


第二个参数,OutputArrayOfArrays类型的mv,填函数的输出数组或者输出的vector容器。


例如:

Mat srcImage;    

vector<Mat> channels;  

srcImage= cv::imread("dota.jpg");  

namedWindow("srcImage");  

imshow("srcImage",  srcImage);


// 把一个3通道图像转换成3个单通道图像  

split(srcImage,channels);//分离色彩通道

     

Mat imageBlueChannel;  

Mat imageGreenChannel;  

Mat imageRedChannel;  

imageBlueChannel = channels.at(0);  

imageGreenChannel = channels.at(1);  

imageRedChannel = channels.at(2);


namedWindow("Blue");  

imshow("Blue",  imageBlueChannel );

namedWindow("Green");  

imshow("Green",  imageGreenChannel );

namedWindow("Red");  

imshow("Red",  imageRedChannel );


注:Mat::at()方法,返回一个引用到指定的数组元素。注意是引用,相当于两者等价,修改其中一个另一个跟着变。  


  1.8.2 合成颜色通道merge()  

原函数:

void merge(const Mat* mv, size_tcount, OutputArray dst)  

void merge(InputArrayOfArrays mv,OutputArray dst)


第一个参数,mv,填需要被合并的输入矩阵或vector容器的阵列,这个mv参数中所有的矩阵必须有着一样的尺寸和深度。


第二个参数,count,当mv为一个空白的C数组时,代表输入矩阵的个数,这个参数显然必须大于1.


第三个参数,dst,即输出矩阵,和mv[0]拥有一样的尺寸和深度,并且通道的数量是矩阵阵列中的通道的总数。


函数解析:

merge函数的功能是将一些数组合并成一个多通道的数组。关于组合的细节,输出矩阵中的每个元素都将是输出数组的串接,其中,第i个输入数组的元素被视为mv[i]。 c一般用其中的Mat::at()方法对某个通道进行存取,也就是这样用channels.at(0)。


例如(接上):

// 把3个单通道图像转合成1个3通道图像  

merge (channels, srcImage);    

namedWindow("RGB");  

imshow("RGB",  srcIma






  联系方式  

邮箱:david.lu@lontry.cn

电话:0755-29952252, 陆工:15999607370

QQ:457841768


  完整文章下载  

《OpenCV从入门到实战》