目录
第四章、OpenCV基本结构与数据绘图
4.1、基础图像容器Mat
4.1.1、数字图像存储概述
4.1.2、Mat结构的使用
4.1.3、像素值的存储方法
4.1.4、显式创建Mat对象的七种方法
4.1.5、OpenCV中的格式化输出方法
4.1.6、输出其他常用数据机构
4.2、常用数据结构和函数
4.2.1、点的表示:Point类
4.2.2、颜色的表示:Scalar类
4.2.3、尺寸的表示:Size类
4.2.4、矩阵的表示:Rect类
4.2.5、颜色空间转换:cvtColor()
4.2.6、其他常用知识点
4.3、基本图形的绘制
第四章、OpenCV基本结构与数据绘图
4.1、基础图像容器Mat
4.1.1、数字图像存储概述
4.1.2、Mat结构的使用
- Mat是一个类,有两个数据部分组成:矩阵头(矩阵尺寸、存储方法、存储地址);指向存储所有像素值的矩阵(根据所选存储方法的不同,矩阵可以是不同的维数)的指针。矩阵头的尺寸是常数值,但矩阵本身的尺寸会依图像的不同而不同,通常比及枕头的尺寸大数个数量级。
- 赋值运算符和拷贝构造函数值复制信息头
- 使用函数clone()和copyTo()来复制一副图像的矩阵
4.1.3、像素值的存储方法
- 存储像素值需要指定颜色空间和数据类型。颜色空间是指针对一个给定的颜色,如何组合颜色元素对其编码。
- RGB+A(透明颜色)
4.1.4、显式创建Mat对象的七种方法
- 1、使用Mat()构造函数
Mat m(2,2,CV_8UC3,Scalar(0,0,255))
- 对于二维多通道图像,首先要定义其尺寸,即行数和列数。然后需要指定存储元素的数据类型以及每个矩阵点的通道数。
- CV_[位数][带符号与否][类型前缀]C[通道数]
- 2、在c++中通过构造函数进行初始化
int sz[3]={2,2,2}
Mat m(3,sz,CV_8UC,Scalar::all(0))
- 创建一个超过两维的矩阵:指定维数,传递一个指向一个数组的指针,数组包括每个维度的尺寸;后续的两个参数与第一种方法一样
- 3、为已存在的IplImage指针创建信息头
IplImage* img = cvLoadImage("1.jpg",1)
-
Mat mtx(img)
;转换
- 4、利用Create()函数
- M.Create(4,4,CV_8UC(2));此方法不能为矩阵设初值,只是在改变尺寸时重新为矩阵数据开辟内存而已
- 5、采用Matlab的初始化方式
- Mat e=Mat::eye(4,4,CV_64F)
- 6、对小矩阵使用逗号分隔式初始化函数
- Mat c = (Mat_<double>(3,3)<<0,-1,0,-1,0,-1,0)
- 7、为已存在的对象创建新信息头
- Mat R=C.row(1).clone();
4.1.5、OpenCV中的格式化输出方法
- Mat r = Mat(10,3,CV_8UC3);
- randu(r,Scalar::all(0),Scalar::all(255))
- 初始化完r矩阵:
- opencv默认风格
cout<<r
- python风格
cout<<format(r,Formatter::FMT_PYTHON)
- 逗号分隔符风格
cout<<format(r,Formatter::FMT_CSV)
- Numpy
format(r,Formatter::FMT_NUMPY)
- c语言风格
format(r,Formatter::FMT_C)
4.1.6、输出其他常用数据机构
- 1、定义和输出二维点
-
Point2f p(6.2)
;cout<<p
- 2、定义和输出三维点
Point3f p3f(8,2,0)
- 3、定义和输出基于Mat的vector
vector<float> v
v.push_back(3);v.push_back(5);v.push_back(7)
- 4、定义和输出vector点
points[i]=Point2f((float)(i*5),(float)(i%7))
4.2、常用数据结构和函数
- 4
4.2.1、点的表示:Point类
- Point point; point.x =10; point.y =8
- Point point = Point(10,8)
4.2.2、颜色的表示:Scalar类
- Scalar()表示具有4个元素的数组,用于传递像素值,对于此函数用不到第四个参数则不需要写出来,Scalar(a,b,c)表示RGB颜色,红c,绿b,蓝a
4.2.3、尺寸的表示:Size类
- Size(5,5);
4.2.4、矩阵的表示:Rect类
- Rect的成员变量有x,y,width,height,分别为左上角点的坐标和矩形的宽和高。常见的成员函数有Size()返回值为Size;area()返回矩形的面积;contains(Point)判断点是否在矩形内、inside(Rect)判断矩形是非在该矩形内;tl()返回左上角点坐标,br()返回右下角坐标。
- 求两个矩形的交集和并集:rect1 & rect2; rect1 | rect2
- 进行平移和缩放:rect+point; rect+size
4.2.5、颜色空间转换:cvtColor()
void cvtColor(InputArray src,OutputArray dst, int code, int dstCn=0)
- 第一个参数为输入图像,第二个为输出图像,第三个为颜色空间转换的标识符,第四个为目标图像的通道数,为0表示目标图像取源图像的通道数
-
cvtColor(srcImage,dstImage.COLOR_GRAY2BGR)
转换原始图为灰度图
4.2.6、其他常用知识点
4.3、基本图形的绘制
- 用于绘制椭圆的ellipse函数
- 实心圆的绘制
- 多边形
- 线
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
#define WINDOWNAME1 "【绘制图1】"
#define WINDOWNAME2 "【绘制图2】"
#define WINDOWWIDTH 600 //定义窗口大小的宏
//--------[DrawEllipse]函数--------------
//自定义的绘制函数,实现了绘制不同角度、相同尺寸的椭圆
void DrawEllipse(Mat img, double angle)
{
int thickness = 2;
int lineType = 8;
ellipse(img,
Point(WINDOWWIDTH / 2, WINDOWWIDTH / 2),
Size(WINDOWWIDTH / 4, WINDOWWIDTH / 16),
angle, 0, 360, Scalar(255, 129, 0),
thickness, lineType);
}
//-----------DrawFilledCircle()函数------------
//自定义的绘制函数,实现实心圆的绘制
void DrawFilledCircle(Mat img, Point center)
{
int thickness = -1;
int lineType = 8;
circle(img, center, WINDOWWIDTH / 32,
Scalar(0,0,255),thickness,lineType);
}
//--------DrawPolygon
//实现了凹多边形的绘制
void DrawPolygon(Mat img)
{
int lineType = 8;
//创建一些点
Point rookPoints[1][20];
rookPoints[0][0] = Point(WINDOWWIDTH / 4, 7 WINDOWWIDTH / 8);
rookPoints[0][1] = Point(3 WINDOWWIDTH / 4, 7 WINDOWWIDTH / 8);
rookPoints[0][2] = Point(3 WINDOWWIDTH / 4, 13 WINDOWWIDTH / 16);
rookPoints[0][3] = Point(11 WINDOWWIDTH / 16, 13 WINDOWWIDTH / 16);
rookPoints[0][4] = Point(19 WINDOWWIDTH / 32, 3 WINDOWWIDTH / 8);
rookPoints[0][5] = Point(3 WINDOWWIDTH / 4, 3 WINDOWWIDTH / 8);
rookPoints[0][6] = Point(3 WINDOWWIDTH / 4, WINDOWWIDTH / 8);
rookPoints[0][7] = Point(26 WINDOWWIDTH / 40, WINDOWWIDTH / 8);
rookPoints[0][8] = Point(26 WINDOWWIDTH / 40, WINDOWWIDTH / 4);
rookPoints[0][9] = Point(22 WINDOWWIDTH / 40, WINDOWWIDTH / 4);
rookPoints[0][10] = Point(22 WINDOWWIDTH / 40, WINDOWWIDTH /8);
rookPoints[0][11] = Point(18 WINDOWWIDTH / 40, WINDOWWIDTH / 8);
rookPoints[0][12] = Point(18 WINDOWWIDTH / 40, WINDOWWIDTH / 4);
rookPoints[0][13] = Point(14 WINDOWWIDTH / 40, WINDOWWIDTH / 4);
rookPoints[0][14] = Point(14 WINDOWWIDTH / 40, WINDOWWIDTH / 8);
rookPoints[0][15] = Point( WINDOWWIDTH / 4, WINDOWWIDTH / 8);
rookPoints[0][16] = Point(WINDOWWIDTH / 4, WINDOWWIDTH / 8);
rookPoints[0][17] = Point(13 WINDOWWIDTH /32, 3WINDOWWIDTH / 8);
rookPoints[0][18] = Point(5 WINDOWWIDTH / 16, 13 WINDOWWIDTH / 16);
rookPoints[0][19] = Point(WINDOWWIDTH / 4, 13WINDOWWIDTH / 16);
const Point ppt[1] = { rookPoints[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);
}
int main(void)
{
//创建空白的Mat图像
Mat atomImage = Matzeros(WINDOWWIDTH, WINDOWWIDTH, CV8UC3);
Mat rookImage = Matzeros(WINDOWWIDTH, WINDOWWIDTH, CV8UC3);
//-------------1、绘制化学中的原子示例图------------
//1.1、先绘制椭圆
DrawEllipse(atomImage, 90);
DrawEllipse(atomImage, 0);
DrawEllipse(atomImage, 45);
DrawEllipse(atomImage, -45);
//1.2、绘制圆心
DrawFilledCircle(atomImage, Point(WINDOWWIDTH / 2, WINDOWWIDTH / 2));
//----------2、绘制组合图------------
//2.1、绘制椭圆
DrawPolygon(rookImage);
//2.2、绘制矩形
rectangle(rookImage,
Point(0, 7 WINDOWWIDTH / 8),
Point(WINDOWWIDTH, WINDOWWIDTH),
Scalar(0, 255, 255),
-1, 8
);
//2.3、绘制一些线段
DrawLine(rookImage, Point(0, 15 WINDOWWIDTH / 16), Point(WINDOWWIDTH, 15 WINDOWWIDTH / 16));
DrawLine(rookImage, Point(WINDOWWIDTH/4, 7 WINDOWWIDTH / 8), Point(WINDOWWIDTH/4, WINDOWWIDTH));
DrawLine(rookImage, Point(WINDOWWIDTH /2, 7 WINDOWWIDTH / 8), Point(WINDOWWIDTH / 2, WINDOWWIDTH));
DrawLine(rookImage, Point(3WINDOWWIDTH / 4, 7 WINDOWWIDTH / 8), Point(3WINDOWWIDTH / 4, WINDOWWIDTH));
//-----------3、显示绘制出的图像
imshow(WINDOWNAME1, atomImage);
moveWindow(WINDOWNAME1, 0, 200);
imshow(WINDOWNAME2, rookImage);
moveWindow(WINDOWNAME2, WINDOWWIDTH, 200);
waitKey(0);
return 0;
}