我是靠谱客的博主 冷傲过客,最近开发中收集的这篇文章主要介绍【OpenCV学习笔记】1-Mat数据结构,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

【OpenCV学习笔记】数据结构

    • 像素值的存储方法
    • 显示创建Mat对象
    • Mat对象组成结构
    • OpenCV的格式化输出
    • 一些类的关键字
    • 其他常用知识点

本笔记来源于《OpenCV3编程入门》 毛星云等著

像素值的存储方法

RGB是最常见的颜色系统,它与人眼采用相似的工作机制,被显示设备所采用。
OpenCV中RGBBGR有所区别。其中后者是OpenCV默认通道储存顺序。

HSVHLS把颜色分解成色调、饱和度和亮度/名都。这是描述颜色更自然的方式。可以通过抛弃最后一个元素,使算法对输入图像的光照条件不敏感。

YCrCb在JPEG图像格式中被广泛使用

显示创建Mat对象

最常用的方法就是直接使用Mat()构造函数
如:
Mat M(2,2, CV_8UC3 ,Scalar(0,0,255));

CV_8UC3 和 Scalar(0,0,255)各代表什么?

对于二维多通道图像,首先要定义其尺寸,即行数和列数,然后,需要制定存储元素的数据类型以机每个矩阵点的通道数。为此,依据下面的规则有多种定义:

CV_[位数][带符号与否][类型前缀]C[通道数]

由此可以知道
CV_8UC3代表的是: 使用8位的unsigned char型,每个像素由三个元素组成三通道(预先定义的通道数可达4个)。

Scalar是个short型的向量,能够使用制定的定制化值来初始化矩阵,还可以用来表示颜色

如何创建三维矩阵?

/*-------------朱砂青瓦 创建三维矩阵--------------*/
int sz[3]={2,2,2};
Mat L(3,sz,CV_8UC,scalar::all(0));

第一个参数指定维数,然后传递一个指向一个数组的指针,包含每个维度的尺寸。

另外可以使用Mat类自带的Create()函数来初始化Mat类

/*-------------朱砂青瓦 Creat()初始化Mat--------------*/
mat.create(4,4,CV_8UC(2));
cout << "M = " << endl << " " << M << endl << endl;

但是这种方法并不能够位矩阵设定初始值,只能够开辟内存

Matlab式方法初始化

/*-------------朱砂青瓦 Matlab式初始化Mat--------------*/
//对角矩阵
Mat E = Mat::eye(4,4,CV_64F);
//1矩阵
Mat O = Mat::ones(2,2,CV_32F);
//0矩阵
Mat Z = Mat::zeros(3,3,cv_8UC1);

Mat对象组成结构

Mat是OpenCV储存图像的类,由两个数据部分组成:

  • 矩阵头(包含矩阵尺寸、存储方法、存储地址等信息)类似段表
  • 一个指向存储所有像素值的矩阵

矩阵头的尺寸是常数值,但矩阵本身的尺寸会依图像的不同而不同,通常比矩阵头的尺寸大数个数量级。
但是为了解决问题通常要使用库中的多个函数,因此在函数中传递图像是常有的事。
为了解决这个问题,OpenCV使用了计数机制。思路是让每个Mat对象由自己的信息头,但共享同一个矩阵。
也就是说,每个Mat对象的实例只是信息头有所区别,但是他们使用的矩阵都是一个。

因此,通过赋值运算符"="和拷贝构造函数(构造函数)只复制信息头。比如Mat B = A、Mat C(A)
A、B、C使用的是同一个矩阵。三者中只要有一个对象做出改变,其他两个也会被影响

当Mat对象被复制一次,计数就会+1.当一个头被释放,计数就会-1.当计数值为0,矩阵就会被清理。(感觉类似操作系统中的信号量)

那么如何复制矩阵本身?
答:使用clone()和copyTo()函数
例:

/*-------------朱砂青瓦 复制矩阵--------------*/
Mat D = A.clone();
Mat F;
A.copyTo(F);

这样,改变D或F就不会影响到A了。

OpenCV的格式化输出

randu()函数产生随机值来填充矩阵

/*-------------朱砂青瓦 复制矩阵--------------*/
Mat r = Mat(10, 3, CV_8UC3);
randu(r, Scalar::all(0), Scalar::all(255));

其中第一个参数是Mat类,后面两个参数指定了生成的随机数的上限和下限

/*-------------朱砂青瓦 格式化输出Mat--------------*/
Mat r = Mat(10, 3, CV_8UC3);
	randu(r, Scalar::all(0), Scalar::all(255));
	//默认风格
	cout << "r (默认)=" << r << ";" << endl << endl;
	//Python风格
	cout << "r (Python)" << format(r, Formatter::FMT_PYTHON) << ";" << endl << endl;
	//逗号分隔风格
	cout << "r (逗号分隔风格)" << format(r, Formatter::FMT_CSV) << ";" << endl << endl;
	//Numpy风格
	cout << "r (Numpy)" << format(r, Formatter::FMT_NUMPY) << ";" << endl << endl;
	//C语言风格
	cout << "r (C)" << format(r, Formatter::FMT_C) << ";" << endl << endl;

结果显示如下:
默认风格和Python风格
逗号分隔风格和Numpy风格
C语言风格

一些类的关键字

Point类
Point_<int> 、Point2i、Point互相等价(Point类默认为int)
Point_<float>、Point2f互相等价

Scalar类
Scalar表示具有4个元素的数组。如果用不到第四个参数,就不用写出来。

Scalar(a,b,c)

那么定义的RGB颜色值:红色为c,绿色为b,蓝色为1
注意:默认通道储存顺序:BGR

Size类
Size_<int> 、Size2i、Size互相等价(Size类默认为int)
一般为2维。Size(2,3)表示宽度为2,高度为3.

Rect类
Rect类成员变量有x、y、width、height
常用成员函数有:

  • Size()返回Size
  • area()返回面积
  • contains(Point)判断点是否在矩形内
  • inside(Rect)判断矩形是否在该矩形内
  • tl()返回左上角点坐标(topleft),br()返回右下角点坐标(bottomright)

求交集和并集:
Rect rect = rect1 & rect2;
Rect rect = rect1 | rect2;

平移和缩放操作:
Rect rectShift = rect + point;
Rect rectScale = rect + size;

小结
OpenCV中变量一般是[变量名]_<变量类型> 、 [变量名][维数][变量类型]

其他常用知识点

  • Matx是个轻量级的mat,必须在使用前规定好大小。比如2*3的float型的Matx,可以声明为Matx23f
  • Vec是Matx的一个派生类,是一个一维的Matx,和vector相似。
  • Rnage类其实就是为了使OpenCV的使用更像Matlab而产生的。Range(a,b)其实就是Matlab中的a:b,a和b都应为整型。
  • OpenCV中防止内存溢出的函数有:alignPtr、alignSize、allocate、deallocate、fastMalloc、fastFree
  • <math.h>中一些函数使用起来很方便如:计算向量角度的函数fastAtan2、计算立方根函数cubeRoot、向上取整函数cvCeil、向下取整函数cvFloor、四舍五入函数cvRound等。另外比如判断变量是否无穷大cvIsInf、判断自变量是否不是一个数cvIsNaN
  • 显示文字相关:getTextSize、cvInitFont、putText
  • 作图相关:circle、clipLine、ellipse、ellipse2Poly、line、rectangle、polylines、类LineIterator
  • 填充相关函数:fillConvexPoly、fillPoly
  • OpenCV中RNG()函数的作用为初始化随机数状态的生成器。

最后

以上就是冷傲过客为你收集整理的【OpenCV学习笔记】1-Mat数据结构的全部内容,希望文章能够帮你解决【OpenCV学习笔记】1-Mat数据结构所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部