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>¶ms=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
完整文章下载