一、什么是Mat?
在计算机内存中,数字图像都是以矩阵的形式存储和运算的。而OpenCV中的Mat类就是用于保存图像以及其他矩阵数据的数据结构的。
二、Mat的方法介绍
1.构造方法(如何创建Mat)
/**
* Mat(int rows, int cols, int type, void* data);
* 作用:创建矩阵
*
*【参数:
* 1.行数。
* 2.列数。
* 3.数组类型(图像类型,关于图像类型请看上图列表)
* 4.图像数据,在Android中一般为数组或Bitmap 】
* */
// 例如:
//创建一个 height x width 的 8 位无符号型 4 通道全 0 的 Mat
Mat imgData(height, width, CV_8UC4, pixels);
图像类型解释:
OpenCV中Mat存在各种类型,其中mat有一个type()的函数可以返回该Mat的类型。类型表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为
CV_<bit_depth>(S|U|F)C<number_of_channels>
1--bit_depth---比特数---代表8bite,16bites,32bites,64bites
举个例子吧--比如说,
如果你现在创建了一个存储灰度图片的Mat对象,这个图像的大小为宽高都为
100,那么,现在这张灰度图片中有10000个像素点,它每一个像素点在内存
空间所占的空间大小是8bite,8位--所以它对应的就是CV_8
2--S|U|F--S--代表--signed int----> 有符号整形
U--代表--unsigned int--> 无符号整形
F--代表--float---------> 单精度浮点型
3--C<number_of_channels>----代表--- 一张图片的通道数,
例如:
1--灰度图片--grayImg--- 是 --- 单通道图像
2--RGB彩色图像--------- 是 --- 3通道图像
3--带Alph通道的RGB图像-- 是 --- 4通道图像
【1】CV_8UC1---则可以创建---8位无符号的单通道---灰度图片
【2】CV_8UC3---则可以创建---8位无符号的三通道--RGB彩色图像
【3】CV_8UC4---则可以创建---8位无符号的四通道--带透明色的RGB图像
具体的有以下值:
类型 | C1 | C2 | C3 | C4 |
---|---|---|---|---|
CV_8U | 0 | 8 | 16 | 24 |
CV_8S | 1 | 9 | 17 | 25 |
CV_16U | 2 | 10 | 18 | 26 |
CV_16S | 3 | 11 | 19 | 27 |
CV_32S | 4 | 12 | 20 | 28 |
CV_32F | 5 | 13 | 21 | 29 |
CV_64F | 6 | 14 | 22 | 30 |
2. Mat 像素读取方式 ----- at() 、ptr() 、迭代器遍历图像 等
大家都是成年人(老码农)我们先直接讲区别
at()可用來读取和修改某个像素值,通常用來对随机位置的像素进行读写,就效率考量
,並不适合用在循序查访影像所有像素
ptr()函式返回指标,指向图像指定列的首像素,使用时须输入像素位深度和第几列,
对于一个深度8位的图,我们可用img.ptr(j)指到第j列的第一个像素,接着逐列查访
,最后可查访图像所有像素,这种方法运行速度较at()快,在分辨率大或是重视效率
的地方,是比较好的方法。
迭代器遍历图像:
用迭代器来遍历图像像素,可简化过程降低出错的机会,比较安全,不过效率较低。
其他方式 【略】(有很多种方式自己百度搜吧!不一一例举了!!!)
================================================================
at()函数读取像素:
Mat image(height, width, CV_8UC4, pixels);
for(int i=0; i<image.rows;i++){
for(int j=0; j<image.cols; j++){
//随意访问图像中任何一个像素,i表示第i行,j表示该行第j个像素。
image.at<Vec3f>(i,j)[0]= ;
}
};
================================================================
ptr()函数读取像素:
Mat imgData(height, width, CV_8UC4, pixels);
//指向imgData第一行第一个元素的指针
uchar *ptr = imgData.ptr(0);
//找到所有像素点
for (int i = 0; i < width * height; i++) {
ptr[4 * i + 0] = ;//蓝色通道
ptr[4 * i + 1] = ;//红色通道
ptr[4 * i + 2] = ;//绿色通道
}
===============================================================
//迭代器遍历图像:
Mat image(height, width,CV_8UC1);
MatIterator_<uchar>Mbegin,Mend;
//遍历所有像素,设置像素值
for (Mbegin=image.begin<uchar>(),
Mend=image.end<uchar>();Mbegin!=Mend;++Mbegin){
*Mbegin=rand()%255;
}
3. Mat 类型转换 ---- convertTo
/**
* convertTo(OutputArray m, int rtype,
* double alpha=1, double beta=0 )const;
*
* 作用:矩阵类型转换
*
* 【参数:
* 1.输出矩阵(就是修改后的结果矩阵)。
* 2.输出矩阵的类型
* 3.尺度变换因子(可选)
* 4.附加到尺度变换后的值上的偏移量(可选)
*
* 注意:
* 1.OpenCV的convertTo函数如果第三个参数使用默认的话,就会导致数值只
* 是类型的改变,但在浮点数表示的颜色空间中,数值范围是0-1.0。
*
* 2.灰度或rgb图像的颜色分量都在0~255之间,
* 而CV_64FC1取值范围远远不止0~255,需要先归一化成0~1.0。
* 所以要这样写 convertTo(Mat,CV_64FC1,1/255.0);
*
* */
例如: 把 CV_32F 转为 CV_8U
//得到一个浮点型的100*100的矩阵
Mat matTemp = cv::Mat::zeros(100,100,CV_32F);
Mat matTemp2;
//把 CV_32F 转为 CV_8U
matTemp.convertTo(matTemp2, CV_8U);
// 注意 在转换过程中有可能数值上会出现一些变化