opencv学习笔记(十三)——数据结构
来源:互联网 发布:网络零售交易额指什么 编辑:程序博客网 时间:2024/05/22 03:35
一、基础图像容器Mat
1.1Mat介绍
Mat是用来储存数字图像的一个类。它是IplImage的升级。Mat相对于IplImage最大的优点就是:不用手动开辟和释放图像内存,Mat能够自动管理内存。
Mat是一个类。包含两个数据部分:(1)矩阵头(包含矩阵尺寸,储存方法、存储地址等信息);(2)一个指向储存所有像素值的矩阵(根据所储存方法的不同,矩阵可以是不同的维数)的指针。
为了提高Opencv的运行速度,采用了引用计数机制。其思路是让每个Mat对象有自己的信息头(矩阵头),共享同一个矩阵。在Opencv中,各个函数之间传递图像就是传递信息头,而不是传递矩阵数据,从而提高Opencv运行速度。
注意:一个矩阵被多个Mat类型的对象使用,这个矩阵清理由最后一个使用它的对象负责清理。
1.2Mat的复制:
1,Mat类的拷贝构造函数只复制信息头和矩阵指针,而不复制矩阵。
下面是两种只复制矩阵头的方法例程:
Mat A, C; A = imread("psb.jpg"); /*使用构造函数进行复制*/ Mat B(A); /*使用赋值运算符进行复制*/ C = A;
2,复制矩阵数据:
在一些情况下我们必须要复制Mat类的矩阵数据,就可以使用clone()或者是copyTo()。
例1:
Mat F =A.clone();
例2:
Mat G;A.copyTo(G);
1.3,Mat对象创建的七种办法:
(1)【方法一】使用构造函数(最常用):
Mat M(2, 2, CV_8UC3, Scalar(0, 0, 255)); //创建cout << "M = " << endl << " " << M << endl << endl; //显示
首先定义其行数和列数,然后指定存储元素的数据类型以及每个矩阵点的通道数,(CV_[位数][带符号与否][类型前缀]C[通道数],例:CV_8UC3,预先定义的通道数最多只能四通道,若需要更多通道数,可以使用大写宏,并把通道数放在括号中,如:CV_8UC(1))
int sz[3] = { 2, 2, 2 }; Mat L(3, sz, CV_8UC(1), Scalar::all(1));
(2)【方法二】使用已存在的IplImage指针创建信息头
IplImage* img = cvLoadImage("G:\\Opencv\\素材\\楪析.jpg", 1); Mat mtx(img); //转换IplImage*->Mat
(3)【方法三】采用MATLAB式的初始化方式
采用MATLAB初始化矩阵的方式:zeros(),ones(),eyes().然后指定尺寸和数据类型:
Mat O = Mat::ones(2, 2, CV_32F); cout << "O = " << endl << O << endl << endl;
Mat E = Mat::eye(4, 4, CV_64F); cout << "E = " << endl << " " << E << endl << endl;
Mat Z = Mat::zeros(3, 3, CV_8UC1); cout << "Z = " << endl << " " << Z << endl << endl;
(4)【方法四】对小矩阵使用逗号直接初始化:
Mat C = (Mat_<double>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); cout << "C = " << endl << " " << C << endl << endl;
(5)【方法五】为已存在的对象创建新信息头
其实就是先创建一个信息头(Mat RowClone;),然后从一个带有矩阵数据的Mat对象中复制其数据给这个信息头,对其初始化。
Mat C = (Mat_<double>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);Mat RowClone = C.row(1).clone(); cout << "RowClone = " << endl << " " << RowClone << endl << endl;
1.4、Mat的格式化输出
主要介绍三种:
首先初始化一个Mat对象:
/*初始化一个Mat对象*/ Mat r = Mat(10, 3, CV_8UC3); randu(r, Scalar::all(0), Scalar::all(255));
(1)opencv默认风格输出:
/*opencv默认风格输出*/ cout << "r(opencv默认风格) = " << endl << r << ";" << endl << endl;
(2)C语言风格输出:
/*C语言风格*/ cout << "r(C语言风格)=" << endl << format(r, "C") << ";" << endl << endl;
(3)逗号分隔的风格:
/*逗号分隔的风格*/ cout << "r(逗号分隔) = " << endl << format(r, "csv") << ";" << endl << endl;
二、其他数据结构
2.1点的定义和输出:Point类
//二维点的定义和输出 Point2f p(6, 2); cout << "【二维点】 p = " << p << ";\n" << endl;
也可以这样表示:
Point point; point.x = 10; point.y = 8; cout << point << endl;
另外还有三维点:
//三维点的定义和输出 Point3f p3f(8, 2, 0); cout << "【三维点】p3f = " << p3f << ";\n" << endl;
然后我们查看Point的定义:
typedef Point_<int> Point2i;typedef Point2i Point;typedef Size_<int> Size2i;typedef Size_<double> Size2d;typedef Size2i Size;typedef Rect_<int> Rect;typedef Point_<float> Point2f;typedef Point_<double> Point2d;typedef Size_<float> Size2f;typedef Point3_<int> Point3i;typedef Point3_<float> Point3f;typedef Point3_<double> Point3d;
可以发现:Point_,Point2i,Point互相等价。
2.2基于Mat的std:vector定义和输出
//基于Mat的std:vector定义和输出 vector<float> v; v.push_back(3); v.push_back(5); v.push_back(7); cout << "【基于Mat的vector】shortvec = " << Mat(v) << ";\n" << endl;
2.3定义和输出std::vector点
vector<Point2f> points(20); for (size_t i = 0; i < points.size(); ++i) { points[i] = Point2f((float)(i * 5), (float)(i % 7)); } cout << "【二维点向量】points =" << points << ";";
2.4颜色的表示:Scalar类
Scalar表示具有4个元素的数组,通常用来传递像素值。例如:RGB的颜色值。对于这个函数可以写三个函数,第四个可以不写。
如:
Scalar(a,b,c)
那么定义RGB颜色值:红色分量为c,绿色为b,蓝色为a;
2.5尺寸的表示:Size类
typedef Size_<int> Size2i;typedef Size2i Size;
其中Size_是个模板类,在这里Size_表示类体内部的模板所代表的类型为int,这两句代码意思是:首先给已知的数据类型Size_起个新名字,叫Size2i.然后又给已知数据类型Size起个新名字,叫Size。这里主要是typedef的用法。
对于Size_模板类的内部构造函数,我们使用频率最高的是:
Size_(_Tp _width,_Tp_height);
定义的是宽度和高度。
例:
Size(5,5),表示XXX的宽度和高度都是5。
2.6矩阵的表示:Rect类
Rect类的成员变量有x,y,width,hight,分别为左上角的坐标和矩阵的宽和高。常用的成员函数有:size()返回值为size,area()返回矩阵的面积contains(Point)判断点是否在矩形中,inside(Rect)函数判断矩形是否在矩形内。t1()返回左上角点坐标,br()放回右下角点坐标。
Scalar和Point综合运用实例:
Draw.cpp文件:
#include"Draw.h"/* *主要功能:实现绘制不同角度,相同尺寸的椭圆 *椭圆绘制函数ellipse()函数参数介绍: *将图像画到图像img上 *椭圆中心点Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2) *椭圆旋转角度angle *扩展的弧度从0度到360度 *图形颜色Scalar(255,129,0) *线宽(thickness)为2 *线(lineType)为8(联通线型) */void DrawEllipse(Mat img,double angle){ int thickness = 2; int lineType = 8; ellipse(img, Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2), Size(WINDOW_WIDTH / 4, WINDOW_WIDTH / 16), angle, 0, 360, Scalar(255, 129, 0), thickness, lineType);}/* *功能:实现实心圆的绘制 *圆形绘制circl函数参数介绍: *将图像画到图像img上 *圆的半径WINDOW_WIDTH/32 *圆的颜色Scalar(0,0,255),为红色 *线宽为 -1,即为实心 *线型(lineType)为8(联通线型) */void DrawFilledCircle(Mat img, Point center){ int thickness = -1; int lineType = 8; circle(img, center, WINDOW_WIDTH / 32, Scalar(0, 0, 255), thickness, lineType );}/* *功能:实现多边形的绘制 *函数fillPoly():用于将多边形画到图像img上 *多边形顶点集为ppt *要绘制的多边形顶点数目为npt *要绘制多边形数量仅为1 *多边形的颜色定义为白色Scalar(255,255,255) */void DrawPolygon(Mat img){ int lineType = 8; //创建一些点 Point rookPoint[1][20]; rookPoint[0][0] = Point(WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8); rookPoint[0][1] = Point(3 * WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8); rookPoint[0][2] = Point(3 * WINDOW_WIDTH / 4, 13 * WINDOW_WIDTH / 16); rookPoint[0][3] = Point(11 * WINDOW_WIDTH / 16, 13 * WINDOW_WIDTH / 16); rookPoint[0][4] = Point(19 * WINDOW_WIDTH / 32, 3 * WINDOW_WIDTH / 8); rookPoint[0][5] = Point(3 * WINDOW_WIDTH / 4, 3 * WINDOW_WIDTH / 8); rookPoint[0][6] = Point(3 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 8); rookPoint[0][7] = Point(26 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 8); rookPoint[0][8] = Point(26 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4); rookPoint[0][9] = Point(22 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4); rookPoint[0][10] = Point(22 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 8); rookPoint[0][11] = Point(18 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 8); rookPoint[0][12] = Point(18 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4); rookPoint[0][13] = Point(14 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4); rookPoint[0][14] = Point(14 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4); rookPoint[0][15] = Point(WINDOW_WIDTH / 4, WINDOW_WIDTH / 8); rookPoint[0][16] = Point(WINDOW_WIDTH / 4, WINDOW_WIDTH / 8); rookPoint[0][17] = Point(13 * WINDOW_WIDTH / 32, 3 * WINDOW_WIDTH / 8); rookPoint[0][18] = Point(5 * WINDOW_WIDTH / 16, 13 * WINDOW_WIDTH / 16); rookPoint[0][19] = Point(WINDOW_WIDTH / 4, 13 * WINDOW_WIDTH / 16); const Point* ppt[1] = { rookPoint[0] }; int npt[] = { 20 }; fillPoly(img, ppt, npt, 1, Scalar(255, 255, 255), lineType);}/* *函数功能:实现线的绘制 * */void DrawLine(Mat img, Point start, Point end){ int thickness = 2; int lineType = 8; line(img, start, end, Scalar(0, 0, 0), thickness, lineType);}
Draw.h文件:
#ifndef _DRAW_H#define _DRAW_H#include <opencv2/opencv.hpp>using namespace cv;using namespace std;#define WINDOW_WIDTH 600#define WINDOW_NAME1 "【绘制图1】"#define WINDOW_NAME2 "【绘制图2】"void DrawEllipse(Mat img, double angle);void DrawFilledCircle(Mat img, Point center);void DrawPolygon(Mat img);void DrawLine(Mat img,Point start,Point end);#endif
main函数:
int main(){ Mat atomImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3); Mat rookImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3); /*绘制原子示例图*/ //绘制椭圆 DrawEllipse(atomImage, 90); DrawEllipse(atomImage, 0); DrawEllipse(atomImage, 45); DrawEllipse(atomImage, -45); //绘制圆心 DrawFilledCircle(atomImage, Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2)); /*制组合图*/ //绘制多边形 DrawPolygon(rookImage); //绘制矩形 rectangle(rookImage, Point(0, 7 * WINDOW_WIDTH / 8), Point(WINDOW_WIDTH, WINDOW_WIDTH), Scalar(0, 255, 255), -1, 8); DrawLine(rookImage, Point(0, 15 * WINDOW_WIDTH / 16), Point(WINDOW_WIDTH, 15 * WINDOW_WIDTH / 16)); imshow(WINDOW_NAME1, atomImage); imshow(WINDOW_NAME2, rookImage); waitKey(0); return 0;}
效果:
- opencv学习笔记(十三)——数据结构
- OpenCV学习笔记(十三)——模板匹配
- OpenCV学习笔记(十三)——模板匹配
- OpenCV学习笔记(二十三)——OpenCV的GUI之凤凰涅槃Qt
- OpenCV学习笔记(十三)边缘检测
- java学习笔记(二十三)数据结构
- 《学习opencv》笔记——IplImage数据结构
- OpenCV学习笔记(二)—IplImage数据结构
- OpenCV笔记(十三)
- opencv学习笔记(二十三)——相机标定原理详解
- openCv学习笔记(十三)—贝叶斯分类器的实现
- openCv学习笔记(十三)—贝叶斯分类器的实现
- python学习笔记(十三)——常用数据结构概述+数组
- 学习OpenCV范例(十三)——图像金字塔
- 属性—Swift学习笔记(十三)
- OpenCV学习笔记(三十九)——再谈OpenCV的数据结构,Mat是如此强大
- OpenCV学习笔记(四十)——再谈OpenCV数据结构Mat详解
- openCv学习笔记(三)——openCv数据结构之间的转换
- css filter详解
- matlab中的eps功能
- html使用Frameset快速方便制作导航栏
- 由阿里一道笔试题引发的思考/ String
- ping 错误信息返回分析
- opencv学习笔记(十三)——数据结构
- <LeetCode><Easy> 118 Pascal's Triangle II
- iOS开发多线程篇—自定义NSOperation
- MySQL找出表中重复字段的内容
- SolrCloud4.9+zookeeper在CentOS上的搭建与安装
- Android 编译重要参数 LOCAL_MODULE_TAGS
- CocoaPods
- VM-based OpenStack Neutron Framework解析
- ios 下CGImageCreateWithImageInRect 内存泄露