®.运行环境:Linux(RedHat+OpenCV3.0)ios
Mat类用于表示一个多维的单通道或者多通道的稠密数组。可以用来保存实数或复数的向量、矩阵,灰度或彩色图像,立体元素,点云,张量以及直方图(高维的直方图使用SparseMat保存比较好)。简而言之,Mat就是用来保存多维的矩阵的。c++
uchar类型的指针,指向Mat数据矩阵的首地址。能够理解为标示一个房屋的门牌号;数组
Mat矩阵的维度,若Mat是一个二维矩阵,则dims=2,三维则dims=3,大多数状况下处理的都是二维矩阵,是一 个平面上的矩阵。安全
能够理解为房屋是一个一层的平房,三维或更多维的则是多层楼房;数据结构
Mat矩阵的行数。可理解为房屋内房间行数;函数
Mat矩阵的列数。可理解为房屋内房间列数;布局
首先size是一个结构体,定义了Mat矩阵内数据的分布形式,数值上有关系式:spa
image.size().width==image.cols; image.size().height==image.rows .net
能够理解为房屋内房间的总体布局,这其中包括了房间分别在行列上分布的数量信息;指针
Mat矩阵元素拥有的通道数。例如常见的RGB彩色图像,channels==3;而灰度图像只有一个灰度份量信息, channels==1。
能够理解为每一个房间内放有多少床位,3通道的放了3张床,单通道的放了1张床;
用来度量每个像素中每个通道的精度,但它自己与图像的通道数无关!depth数值越大,精度越高。在 Opencv中,Mat.depth()获得的是一个0~6的数字,分别表明不一样的位数,对应关系以下:
enum{CV_8U=0,CV_8S=1,CV_16U=2,CV_16S=3,CV_32S=4,CV_32F=5,CV_64F=6}
其中U是unsigned的意思,S表示signed,也就是有符号和无符号数。
能够理解为房间内每张床能够睡多少人,这个跟房间内有多少床并没有关系;
elem是element(元素)的缩写,表示矩阵中每个元素的数据大小,若是Mat中的数据类型是CV_8UC1,那么 elemSize==1;若是是CV_8UC3或CV_8SC3,那么elemSize==3;若是是CV_16UC3或者CV_16SC3,那么 elemSize==6;即elemSize是以8位(一个字节)为一个单位,乘以通道数和8位的整数倍;
能够理解为整个房间能够睡多少人,这个时候就得累计上房间内全部床位数(通道)和每张床的容纳量了;
elemSize加上一个“1”构成了elemSize1这个属性,1能够认为是元素内1个通道的意思,这样从命名上拆分后就很 容易解释这个属性了:表示Mat矩阵中每个元素单个通道的数据大小,以字节为一个单位,因此有:
eleSize1==elemSize/channels;
能够理解为Mat矩阵中每一行的“步长”,以字节为基本单位,每一行中全部元素的字节总量,是累计了一行中所 有元素、全部通道、全部通道的elemSize1以后的值;
以字节为基本单位,Mat矩阵中每个像素的大小,累计了全部通道、全部通道的elemSize1以后的值,因此有:
step1==step/elemSize1;
Mat矩阵的类型,包含有矩阵中元素的类型以及通道数信息,type的命名格式为CV_(位数)+(数据类型)+(通道数),全部取值以下:
注:一、在程序的最开始加上: using namespace cv; 二、把Mat改成 cv::Mat (因为本人不会C++全部开始有点没明白如何使用函数)
建立Mat类的方式:1.构造函数 2.create()函数建立对象3.从已有的数据源初始化
1.构造函数
Mat::Mat()
无参数构造方法;
Mat::Mat(int rows, int cols, int type)
建立行数为 rows,列数为col,类型为type的图像;
Mat::Mat(Size size, int type)
建立大小为 size,类型为type的图像;
Mat::Mat(int rows, int cols, int type, const Scalar& s)
建立行数为rows,列数为col,类型为type的图像,并将全部元素初始化为值s;
Mat::Mat(Size size, int type, const Scalar& s)
建立大小为 size,类型为type的图像,并将全部元素初始化为值s
Mat::Mat(const Mat& m)
将 m 赋值给新建立的对象,此处不会对图像数据进行复制, m 和新对象共用图像数据;
Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
建立行数为 rows,列数为col,类型为type的图像,此构造函数不建立图像数据所需内存,而是直接使用data所指内存,图像的行步长由step指定。
Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)
建立大小为 size,类型为type的图像,此构造函数不建立图像数据所需内存,而是直接使用data所指内存,图像的行步长由step指定。
Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)
建立的新图像为 m 的一部分,具体的范围由 rowRange 和 colRange 指定,此构造函数也不进行图像数据的复制操做,新图像与m共用图像数据;
Mat::Mat(const Mat& m, const Rect& roi)
建立的新图像为 m 的一部分,具体的范围 roi 指定,此构造函数也不进行图像数据的复制操做,新图像与m共用图像数据。
type的类型有CV_8UC1,CV_16SC1,…,CV_64FC4等。里面的8U表示8位无符号整数,16S表示16位有符号整数,64F表示64位浮点数(即double类型);C后面的数表示通道数,例如C1表示一个通道的图像,C4表示4个通道的图像,以此类推。
若是你须要更多的通道数,须要用宏CV_8UC(n),例如:Mat M(3,2, CV_8UC(5));//建立行数为3,列数为2,通道数为5的图像
计算机视觉中,图像的读取是图像处理的基础,图像就是一系列像素值,OpenCV使用数据结构cv::Mat来存储图像。cv::Mat是一个矩阵类,矩阵中每个元素都表明一个像素,对于灰度图像,像素用8位无符号数,0表示黑色,255表示白色。对于彩色像素而言,每一个像素须要三位这样的8位无符号数来表示,即三个通道(R,G,B),矩阵则依次存储一个像素的三个通道的值,而后再存储下一个像素点。
cv::Mat中,
cols表明图像的宽度(图像的列数),
rows表明图像的高度(图像的行数),
step表明以字节为单位的图像的有效宽度,
elemSize返回像素的大小,
channels()方法返回图像的通道数,
total函数返回图像的像素数。
像素的大小 = 颜色大小(字节)*通道数,
好比:
三通道short型矩阵(CV_16SC3)的大小为2*3 = 6,
三通道Byte型矩阵(CV_8UC3)的大小为1*3= 3,像素的channels方法返回图像的通道数,total函数返回图像的像素数。
RGB图像的颜色数目是256*256*256,本文对图像进行量化,缩减颜色数目到256的1/8(即32*32*32)为目标,分别利用一下几种方法实现,比较几种方法的安全和效率。
方法一:使用Mat的成员函数ptr<>()
cv::Mat中提供ptr函数访问任意一行像素的首地址,特别方便图像的一行一行的横向访问,若是须要一列一列的纵向访问图像,就稍微麻烦一点。可是ptr访问效率比较高,程序也比较安全,有越界判断。
方法二:使用迭代器遍历图像
cv::Mat一样有标准模板库(STL),可使用迭代器访问数据。
用迭代器来遍历图像像素,可简化过程下降出错的机会,比较安全,不过效率较低;若是想避免修改输入图像实例cv::Mat,可采用const_iterator。iterator有两种调用方法,cv::MatIterator_<cv::Vec3b>it;cv::Mat_<cv::Vec3b>::iterator it;中间cv::Vec3b是由于图像是彩色图像,3通道,cv::Vec3b能够表明一个像素。
方法三:使用Mat的成员函数at<>()
cv::Mat也是向量,可使at方法取值,使用调用方法image.at<cv::Vec3b>(j,i),at方法方便,直接给i,j赋值就能够随意访问图像中任何一个像素,其中j表示第j行,i表示该行第i个像素。可是at方法效率是这3中访问方法中最慢的一个,因此若是遍历图像或者访问像素比较多时,建议不要使用这个方法,毕竟程序的效率仍是比程序的可读性要重要的。下面是完整的调用方法,其运行时间在下面会介绍。
注意:使用at函数时,应该知道矩阵元素的类型和通道数,根据矩阵元素类型和通道数来肯定at函数传递的类型,使用的是Vec3b这个元素类型,他是一个包含3个unsigned char类型向量。之因此采用这个类型来接受at的返回值,是由于,咱们的矩阵im是3通道,类型为unsigned char类型
完整实例:
时间:2018.1.21.1.41{失眠夜总结OpenCV吧想起了一段话送给本身}{Can not force others to love themselves only to make themselves worthy of love ,and the rely on fate.}@晚安 Liu在身边 27