《OpenCV3编程入门》学习笔记4 OpenCV数据结构与基本绘图
第4章 OpenCV数据结构与基本绘图
4.1 基础图像容器Mat
4.1.1 数字图像存储概述
图像在数码设备中的表现形式:像素点矩阵
4.1.2 Mat结构的使用
1.OpenCV1.x时代:
基于C语言接口而建的图像存储格式IplImage*
缺点:退出时忘记relese掉的话,会造成内存泄漏,手动释放内存耗费时间
2.C++出现后:
自动的内存管理
不足:许多嵌入式开发系统只支持C语言
3.OpenCV2.0时代:
Mat类数据结构
优点:不必手动开辟空间、不必再在不需要时立即释放空间
4.Mat类数据部分组成:
(1)矩阵头:矩阵尺寸、存储方法、存储地址等
(2)指向存储所有像素值的矩阵的指针
5.计数机制:
矩阵本身尺寸数量级很大,传递图像时造成比较大的开销,为解决此问题,引入计数机制。
计数机制:让每个Mat对象有自己的信息头,但共享同一个矩阵。通过让矩阵指针指向同一个地址而实现,拷贝构造函数则只复制信息头和矩阵指针,而不复制矩阵。这时,通过任何一个对象所做的改变会影响其他图像。
(1)创建信息头:
Mat A,C; //仅创建信息头
Mat D(A,Rect(10,10,100,100)); //使用矩形界定信息头
Mat E=A(Range:all(),Range(1,3)); //用行和列界定信息头
(2)矩阵清理:复制一个信息头会增加矩阵的引用次数,反之,当一个头被释放后,计数会减一,当计数值为0,矩阵会被清理。
(3)复制矩阵本身函数:clone()或copyTo(),改变一个对象不会影响其他对象,例如:
Mat F=A.clone();
Mat G;
A.copyTo(G);
4.1.3 像素值的存储方法
1.存储像素值需要指定颜色空间和数据类型,颜色空间:
(1)灰度级空间:黑白组合
(2)其他颜色空间:
1)RGB颜色空间最常用;
2)HSV和HLS把颜色分解成色调、饱和度和亮度/明度,抛弃最后一个元素算法对输入图像的光照条件不敏感
3)YCrCb在JPEG图像格式中广泛使用
4)CIE L*a*b*是一种在感知上均匀的颜色空间,它适合用来度量两个颜色之间的距离
2.每个组成元素都有自己的定义域,定义域取决于其数据类型:
(1)char:最小数据类型,1字节(8位),RGB颜色空间使用三个char,可表示1600万种
(2)有符号型:0到255
(3)无符号型:-127到+127
(4)float或double:能给出更加精细的颜色分辨能力
4.1.4 显式创建Mat对象的7种方法
(Mat不但是图像容器类,也是通用矩阵类,可以用来创建多维矩阵)
1.Mat()构造函数
二维多通道图像定义:行数,列数,存储元素数据类型和矩阵点通道数(CV_[位数][带符号与否][类型前缀]C[通道数]),定制化值初始化矩阵,如:
Mat M(2,2,CV_8UC3,Scalar(0,0,255));//CV_8UC3:8位的unsigned char,每个像素由3个元素组成三通道
cout<<”M=”<<endl<<” “<<M<<endl<<endl;
2.C\C++中通过构造函数进行初始化
int sz[3] = { 2,2,2 };Mat L(3, sz, CV_8UC3, Scalar::all(0));//创建超过2维的矩阵,指定维度,传递一个指向一个数组的指针,数组包含每个维度的尺寸
3.唯一存在的IplImage指针创建信息头,转换IplImage*->Mat
//IplImage* img = cvLoadImage("1.jpg", 1);//Mat mtx(img); //报错,"Mat没有匹配IplImage*参数的构造函数"
4.利用Create()函数,此方法不能为矩阵设初值,只是在改变尺寸时重新为矩阵数据开辟内存
M.create(4, 4, CV_8UC(2));cout << "M= " << endl << " " << M << endl << endl;
5.采用Matlab式的初始化方式
Mat E = Mat::eye(4, 4, CV_64F);//单位矩阵cout << "E= " << endl << " " << E << endl << endl;Mat O = Mat::ones(2, 2, CV_32F);//全1矩阵cout << "O= " << endl << " " << O << endl << endl;Mat Z = Mat::zeros(3, 3, CV_8UC1);//全0矩阵cout << "Z= " << endl << " " << Z << endl << endl;
6.对小矩阵使用逗号分隔式初始化函数
Mat C = (Mat_<double>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);cout << "C= " << endl << " " << C << endl << endl;
7.为已存在的对象创建新信息头
Mat RowClone = C.row(1).clone();cout << "RowClone= " << endl << " " << RowClone << endl << endl;
4.1.5 OpenCV中格式化输出方法
r矩阵定义:通过randu()函数产生的随机值来填充矩阵,需要给定一个上限和下限确保随机值在期望的范围内。
Mat r=Mat(10,3,CV_8UC3);
randu(r,Scalar::all(0),Scalar::all(255));
//1.OpenCV默认风格cout << "r (OpenCV默认风格)= " << r << ";" << endl << endl;
//2.Python风格cout << "r (Python风格)= " << format(r, Formatter::FMT_PYTHON) << ";" << endl << endl;
//3.逗号分隔风格cout << "r (逗号分隔风格)= " << format(r, Formatter::FMT_CSV) << ";" << endl << endl;
//4.Numpy风格cout << "r (Numpy风格)= " << format(r, Formatter::FMT_NUMPY) << ";" << endl << endl;
//5.C语言风格cout << "r (C语言风格)= " << format(r, Formatter::FMT_C) << ";" << endl << endl;
4.1.6 输出其他常用数据结构
1.二维点
Point2f p2f(6, 2);cout << "[二维点]p2f = " << p2f << ";\n" << endl;
2.三维点
Point3f p3f(8, 2, 0);cout << "[二维点]p3f = " << p3f << ";\n" << endl;
3.基于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;
4.std::vector点,定义和输出存放点的vector容器,以存放二维点Point2f为例
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 << ";";
4.2 常用数据结构和函数
4.2.1 点的表示:Point类(OpenCV中Point_<int>、Point2i、Point等价,Point_<float>、Point2f等价)
Point point;point.x = 10;point.y = 8;//Point point = Point(10, 8);
4.2.2 颜色的表示:Scalar类
Scalar(a, b, c); 红c,绿b,蓝a
4.2.3 尺寸的表示:Size类(OpenCV中Size_、Size2i、Size等价)
Size(5, 5);
4.2.4 矩形的表示:Rect类
(1)成员变量:x,y,width,height
(2)成员函数:Size(),area(),contains(Point),inside(Rect),tl()返回左上角点坐标,br()返回右下角点坐标
(3)求两矩形交并集 Rect rect = rect1 & rect2; Rect rext = rext1 | rext2;
(4)矩形平移和缩放 Rect rextShift = rect + point; Rect rectScale = rect + size;
4.2.5 颜色空间转换:cvtColor()函数
(1)函数原型:void cvtColor(InputArray src,OutputArray dst,int code,int dstCn=0)
(2)参数说明:输入图像,输出图像,颜色空间转换标识符,目标图像通道数
(3)示例: cvtColor(srcImage, dstImage, COLOR_GRAY2BGR);
4.2.6 Core模块中的常用函数
1.<math.h>中,计算向量角度fastAtan2、计算立方根cubeRoot、向上取整cvCeil、向下取整cvFloor、四舍五入cvRound、判断自变量是否无穷大cvIsInf、判断自变量是否不是一个数cvIsNaN
2.显示文字相关:getTextSize、cvInitFont、putText
3.作图相关:circle、clipLine、ellipse、ellipse2Poly、line、rectangle、polylines、LineIterator
4.填充相关:fillConvexPoly、fillPoly
4.3 基本图形绘制
涉及绘制函数:line:直线;ellipse:椭圆;rectangle:矩形;circle:圆形;fillPoly:填充的多边形
#include<opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#define WINDOW_NAME1 "[绘制图1]"
#define WINDOW_NAME2 "[绘制图2]"
#define WINDOW_WIDTH 600 //定义窗口大小的宏
using namespace cv;
//4.3.1 DrawEllipse()函数
//自定义的绘制函数,实现绘制不同角度、相同尺寸的椭圆
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);
}//4.3.2 DrawFilledCircle()函数
//自定义的绘制函数,实现实心圆的绘制
void DrawFilledCircle(Mat img, Point center)
{int thickness = -1;int lineType = 8;circle(img, center, WINDOW_WIDTH / 32, Scalar(0, 0, 255), thickness, lineType);//图像,圆心,半径,颜色,线粗,线形
}
//4.3.3 DrawPolygon()函数
//自定义的绘制函数,实现凹多边形的绘制
void DrawPolygon(Mat img)
{int lineType = 8;Point rookPoints[1][20];rookPoints[0][0] = Point(WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8);rookPoints[0][1] = Point(3 * WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8);rookPoints[0][2] = Point(3 * WINDOW_WIDTH / 4, 13 * WINDOW_WIDTH / 16);rookPoints[0][3] = Point(11 * WINDOW_WIDTH / 16, 13 * WINDOW_WIDTH / 16);rookPoints[0][4] = Point(19 * WINDOW_WIDTH / 32, 3 * WINDOW_WIDTH / 8);rookPoints[0][5] = Point(3 * WINDOW_WIDTH / 4, 3 * WINDOW_WIDTH / 8);rookPoints[0][6] = Point(3 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 8);rookPoints[0][7] = Point(26 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 8);rookPoints[0][8] = Point(26 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 4);rookPoints[0][9] = Point(22 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 4);rookPoints[0][10] = Point(22 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 8);rookPoints[0][11] = Point(18 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 8);rookPoints[0][12] = Point(18 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 4);rookPoints[0][13] = Point(14 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 4);rookPoints[0][14] = Point(14 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 8);rookPoints[0][15] = Point(WINDOW_WIDTH / 4, WINDOW_WIDTH / 8);rookPoints[0][16] = Point(WINDOW_WIDTH / 4, 3 * WINDOW_WIDTH / 8);rookPoints[0][17] = Point(13 * WINDOW_WIDTH / 4, 3 * WINDOW_WIDTH / 8);rookPoints[0][18] = Point(5 * WINDOW_WIDTH / 4, 13 * WINDOW_WIDTH / 16);rookPoints[0][19] = Point(WINDOW_WIDTH / 4, 13 * WINDOW_WIDTH / 16);const Point* ppt[1] = { rookPoints[0] };//多边形顶点集int npt[] = { 20 }; //多边形顶点数目fillPoly(img, ppt, npt, 1, Scalar(255, 255, 255), lineType);//图像,顶点集,顶点数目,要绘制的多边形数量,颜色,线形
}
//4.3.4 DrawLine()函数
//自定义绘制函数,实现线的绘制
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()
{//创建空白的Mat图像Mat atomImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);Mat rookImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);//-------------------<1>绘制化学中的原子示例图--------------------------//1.绘制椭圆DrawEllipse(atomImage, 90);DrawEllipse(atomImage, 0);DrawEllipse(atomImage, 45);DrawEllipse(atomImage, -45);//2.绘制圆心DrawFilledCircle(atomImage, Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2));//-------------------------<2>绘制组合图---------------------------//1.绘制椭圆DrawPolygon(rookImage);//2.绘制矩形rectangle(rookImage, Point(0, 7 * WINDOW_WIDTH / 8), Point(WINDOW_WIDTH, WINDOW_WIDTH), Scalar(0, 255, 255), -1, 8);//3.绘制一些线段DrawLine(rookImage, Point(0, 15 * WINDOW_WIDTH / 16), Point(WINDOW_WIDTH, 15 * WINDOW_WIDTH / 16));DrawLine(rookImage, Point(WINDOW_WIDTH/4, 7 * WINDOW_WIDTH / 8), Point(WINDOW_WIDTH/4, WINDOW_WIDTH));DrawLine(rookImage, Point(WINDOW_WIDTH / 2,7 * WINDOW_WIDTH/8), Point(WINDOW_WIDTH/2, WINDOW_WIDTH));DrawLine(rookImage, Point(3 * WINDOW_WIDTH/4, 7 * WINDOW_WIDTH / 8), Point(3 * WINDOW_WIDTH/4, WINDOW_WIDTH));//显示绘制图像imshow(WINDOW_NAME1, atomImage);cvMoveWindow(WINDOW_NAME1, 0, 200);imshow(WINDOW_NAME2, rookImage);cvMoveWindow(WINDOW_NAME2, WINDOW_WIDTH, 200);waitKey(0);return 0;
}
4.4 颜色空间拓展
图像彩色模型包括RGB模型、CMY模型、HSI模型、YIQ模型、YUV模型、YCbCr模型等
4.4.1 RGB彩色模型
RGB彩色模型基于笛卡尔坐标系统,红、绿、蓝、青、深红、黄、黑和白分别位于立方体各个顶点,灰度级沿黑和白两点的连线分布。不同的颜色可以用从原点分布的向量来定义。归一化彩色子空间立方体如图所示:
4.4.2 HSI彩色模型
用色调、饱和度和强度描述彩色图像。饱和度是纯彩色被白光冲淡程度的度量,色调是用来描述纯色的属性,强度(灰度)是单色图像的描述算子。该模型可从彩色信息中消除强度分量的影响,更符合人类的视觉特性,是一种理想的彩色图像处理工具。
4.4.3 RGB与HSI彩色模型之间的转换
(1)RGB转换为HSI
色调分量转换公式:
其中,
饱和度分量转换公式:
亮度分量转换公式:
(2)HSI转换为RGB
RG区():若H在这个区域内,RGB分量公式为:
GB区():若H在这个区域内,RGB分量公式为:
BR区():若H在这个区域内,RGB分量公式为:
《OpenCV3编程入门》学习笔记4 OpenCV数据结构与基本绘图相关推荐
- 原创 OpenCV3编程入门 学习笔记(总)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/qq_36163358/article/ ...
- OpenCV3编程入门 学习笔记(总)
OpenCV3编程入门 学习笔记 2018.12.12-2018.12.29 此博客为在看过毛星云版<OpenCV3编程入门>后所总结的一本笔记,可供复习使用. 文章目录 OpenCV3编 ...
- Opencv3编程入门学习笔记(五)之通道分离(split)与合并(merge)
若要对Opencv中(BGR)颜色通道进行单一处理,那必然会涉及到通道分离(split)与合并(merge).那么本篇博客笔者记录了两个方法的使用方法和案例.案例来源于<Opencv3编程入门学 ...
- 【OpenCV3编程入门学习笔记】——第1章 邂逅OpenCV
邂逅OpenCV 文章目录 邂逅OpenCV 前言 1.1 OpenCV周边概念认知 1.1.1 图像处理.计算机视觉与OpenCV 1.1.2 OpenCV概述 1.1.3 起源及发展 1.1.4 ...
- Opencv3编程入门学习笔记(三)之访问图像像素的三种方法
访问图像像素的三种方法:指针访问,迭代器访问,动态地址访问.访问最快的为指针访问,以下算法在几毫秒,但指针访问容易造成内存泄漏:其次为迭代器访问:最后为动态地址访问. 以下程序是根据<OpenC ...
- 【OpenCV3编程入门学习笔记】——第3章 HighGUI图形用户界面初步
文章目录 前言 3.1 图形的载入.显示和输出到文件 3.1.1 OpenCV的命名空间 3.1.2 Mat类简析 3.1.3 图像的载入与显示概述 3.1.4 图像的载入:imread()函数 3. ...
- Opencv3编程入门学习笔记(四)之split通道分离Debug过程中0xC0000005内存访问冲突问题
这是笔者学习<Opencv3编程入门>的第四篇博客,这篇博客主要是解决在Windows系统下VS 2013中Debug含有split分离通道色彩函数时报出的0xC0000005内存访问冲突 ...
- Opencv3编程入门学习笔记(二)之显式创建Mat对象
以下总结是基于<Opencv3编程入门>一书4.1节总结的内容进行验证与总结,验证环境均为Windows10 ---VS2013 C++环境,验证Opencv3.0提供的开发包. 1. 方 ...
- 01.Java 编程入门学习笔记20210307
Java 编程入门学习笔记-day01 第0章:编程入门 1.计算机的概述 计算机 = 硬件 + 软件 1.1硬件:冯诺依曼体系 CPU: CPU的衡量标准:速度的计量单位是赫兹(Hz),1Hz相当于 ...
最新文章
- SecutrCRTt 连接VirtualBox 中的Ubuntu -端口转发
- Java中的IO整理完整版
- C#——LINQ技术DEMO
- 概率分布之间的距离度量以及python实现(三)
- 在github上搭建hexo博客
- 随便讲讲自己了解的ajax在JQ中的应用
- linux下dns服务器部署,linux系统下部署DNS服务器
- 盘点那些跨界玩到飞起的程序员们!
- 简述线程,程序、进程的基本概念。以及他们之间关系是什么?
- java学习日记-基础-列出2~100内的素数
- 用于小儿肺炎检测的无代码AI
- ArcGIS+Fragstats软件进行景观格局指数分析(附练习数据下载)
- 怎么用java打开pkg文件怎么打开,pkg文件怎么打开
【处置方式】
- JavaAwtSwing笔记之 Frame和JFrame的区别
- “我是技术总监,我确实答不出那么多技术细节”
- 网站服务器在本地是指,本地域名是什么意思?本地域名服务器在哪?
- Matplotlib-Python-绘制基础饼形图,分裂饼形图,环形饼形图
- 中医学专业学c语言吗,考研专业课中医学题型分析
- 1 CRM需求分析,数据库表,录入数据
- 2018 WAIC |最强阵容!各界大咖齐聚,推动视觉智能全领域发展