OpenCV-Mat结构详解
Posted fcfc940503
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV-Mat结构详解相关的知识,希望对你有一定的参考价值。
前面博客中Mat函数谈到一些理解,但是理解的比较浅显,下面谈谈通道,行列等意义;
Mat的常见属性
opencv中type类型·
CV_<bit_depth>(S|U|F)C<number_of_channels>
1--bit_depth---比特数---代表8bite,16bites,32bites,64bites---举个例子吧--比如说,
如果你现在创建了一个存储--灰度图片的Mat对象,这个图像的大小为宽100,高100,那么,现在这张
灰度图片中有10000个像素点,它每一个像素点在内存空间所占的空间大小是8bite,8位--所以它对应的就是CV_8
depth:深度,即每一个像素的位数(bits),在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 ; 可见 0和1都代表8位, 2和3都代表16位,4和5代表32位,6代表64位;
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通道图像
如:CV_8UC1---则可以创建----8位无符号的单通道---灰度图片------grayImg
CV_8UC3---则可以创建----8位无符号的三通道---RGB彩色图像---colorImg
channels:通道,矩阵中的每一个矩阵元素拥有的值的个数,比如说 3 * 4 矩阵中一共 12 个元素,如果每个元素有三个值,那么就说这个矩阵是 3 通道的,即 channels = 3。常见的是一张彩色图片有红、绿、蓝三个通道。
上面是一个 3 X 4 的矩阵,假设其数据类型为 CV_8U,也就是单通道的 uchar 类型
CV_8U 得到 M.depth() == 0, M.channels() == 1
这是一个二维矩阵,那么维度为 2 (M.dims == 2);
M.rows == 3; M.cols == 4;
step:是一个数组,定义了矩阵的布局,具体见上面图片分析,另外注意 step1 (step / elemSize1),M.step[m-1] 总是等于 elemSize,M.step1(m-1)总是等于 channels;
因为是二维矩阵,那么 step 数组只有两个值, step[0] 和 step[1] 分别代表一行的数据大小和一个元素的数据大小,则 M.step[0] == 4, M.step[1] == 1;
M.step1(0) == M.cols = 4; M.step1(1) == 1;
elemSize : 矩阵中每一个元素的数据大小,如果Mat中的数据的数据类型是 CV_8U 那么 elemSize = 1,CV_8UC3 那么 elemSize = 3,
CV_16UC2那么 elemSize = 4;
记住另外有个 elemSize1 表示的是矩阵中数据类型的大小,即 elemSize / channels 的大小
sizeof(uchar) = 1,那么每一个数据元素大小为 1 (M.elemSize() == 1, M.elemSize1() == 1);
CV_8U 得到 M.depth() == 0, M.channels() == 1;
假设上面的矩阵数据类型是 CV_8UC3,也就是三通道
M.dims == 2; M.channels() == 3;M.depth() == 0;
M.elemSize() == 3 (每一个元素包含3个uchar值) M.elemSize1() == 1 (elemSize / channels)
M.step[0] == M.cols * M.elemSize() == 12, M.step[1] == M.channels() * M.elemSize1() == M.elemSize() == 3;
M.step(0) == M.cols * M.channels() == 12 ; M.step(1) == M.channels() == 3;
上面博文参考:opencv数据结构-MAT结构详解
写到这里,我也只了解了行,列,通道等概念,但是step,step(0),elemSize1,elemSize()我感到很困惑,看看下面的理解:
上图中: int matSize[] = 5,8,10;//每一维元素的个数:8:行,10:列
Mat mat1(3,matSize, CV_16UC3, Scalar::all(0);
对于mat1,3通道,一个像素点在内存空间大小是16bit;每一个像素的位数(bits)是2(深度);
三维矩阵,一共有三维,我们分别类比为
面:每个二维矩阵,表示第1维的元素
线:矩阵的每一行,表示第2维的元素
点:矩阵中每行的每个元素,表示第3维的元素
那么这样子就可以解释清楚每一维元素的含义了。
以step[i]为例
step[0]:面的大小,第1维的元素的大小,也就是二维矩阵的大小,一个二维矩阵有8行,所以step[0]=step[1]*8=480
step[1]:线的大小,第2维的元素的大小,也就是二维矩阵每一行的大小,由于每个元素大小为6,每行有10个元素,所以step[1]=10*6=60
step[2]:点的大小,第3维的元素的大小,这里矩阵的每个元素类型为CV_16UC3,所以step[2]=2*3=6个字节
这里注意:
1.step的大小是字节
2.注意下标与维数的对应关系:下标2对应点,1对应线,0对应面
3.矩阵有几维,step[]数组就有几个元素,如3维,则有3个元素,step[0],step[1],step[2].分别对应面,线,点
只要记住,最后一个总是表示点,然后依次向前为线,面…
4.第2,3 点 ,对于size和step1()也一样。
step1(i):每一维元素的通道数
step[i]:每一维元素的大小,单位字节;(包含所有通道)
size[i]:每一维元素的个数
elemSize():每个元素大小,单位字节
elemSize1():每个通道大小,单位字节
elemSize 表示每个元素的大小(单位字节),每个元素可能有多个通道,示例中,每个元素有三个通道,而每个通道类型为CV_16U,算3个通道的总数, 2*3=6
elemSize1 每个通道的大小(单位字节),CV_16=2字节
step1[i] = step.p[i]/elemSize1();
step1[0] = step[0]/elemSize1 = 240 bytes
step1[1] = step[1]/elemSize1 = 30 bytes
step1[2] = step[2]/elemSize1 = 3 bytes
代码如下:
#include"sift.h" #include<fstream> #include<iostream> #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <opencv2/core/core.hpp> #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) //////////////////Demo1(3维矩阵)/////////////////////////////////////////// printf("//////////////////////Demo1(3维矩阵)////////////////////////\\n"); //最后面的两个数:(行,列),确定了一个面 //是一个依次降维的过程 //8,10组成了面,5个面,组成了立方体 int matSize[] = 5,8,10 ;//每一维元素的个数:8:行,10:列 Mat mat1(3, matSize, CV_16UC3, Scalar::all(0)); //求step[i]的大小:每一维元素的大小(单位字节) printf("\\n///////step[i]的大小//////////\\n"); printf("step[0]:%d\\n", mat1.step[0]);//480=8*60:面的大小(第一维) printf("step[1]:%d\\n", mat1.step[1]);//60=6*10:线的大小(第二维) printf("step[2]:%d\\n", mat1.step[2]);//6=2*3:点的大小(第三维) //求size[i]:每一维元素的个数 printf("\\n///////size[i]的大小///////\\n"); printf("size[0]:%d\\n", mat1.size[0]);//5:面 printf("size[1]:%d\\n", mat1.size[1]);//8:线 printf("size[2]:%d\\n", mat1.size[2]);//10:点 //求step1(i):每一维元素的通道数 printf("\\n///////step1(i)的大小///////\\n"); printf("step1(0):%d\\n", mat1.step1(0));//240:面 printf("step1(1):%d\\n", mat1.step1(1));//30:线 printf("step1(2):%d\\n", mat1.step1(2));//3:点 //求elemSize:每个元素的大小(单位字节) printf("\\n///////elemSize的大小///////\\n"); printf("elemSize:%d\\n", mat1.elemSize());//6:每个元素的大小 //求elemSize1:每个通道的大小(单位字节) printf("\\n///////elemSize1的大小///////\\n"); printf("elemSize1:%d\\n", mat1.elemSize1());//2:每个通道的大小 system("pause"); return 0;
改成.jpg图片
/求step[i]的大小:每一维元素的大小(单位字节) //step[i] printf("\\n///////step[i]的大小///////\\n"); printf("step[0]:%d\\n", mat2.step[0]);//1200=3*400:线 printf("step[1]:%d\\n", mat2.step[1]);//3=1*3:点 //size[i] printf("\\n///////size[i]的大小///////\\n"); printf("size[0]:%d\\n", mat2.size[0]);//250:线 printf("size[1]:%d\\n", mat2.size[1]);//400:点 //step1(i) printf("\\n///////step1(i)的大小///////\\n"); printf("step1(0):%d\\n", mat2.step1(0));//1200:第一维的通道数 printf("step1(1):%d\\n", mat2.step1(1));//3:第二维的通道数 //elemSize printf("\\n///////elemSize的大小///////\\n"); printf("elemSize:%d\\n", mat2.elemSize());//3:每个元素的大小 //elemSize1 printf("\\n///////elemSize1的大小///////\\n"); printf("elemSize1:%d\\n", mat2.elemSize1());//1:每个通道的大小,也就是单通道数据类型 system("pause"); return 0;
以上是关于OpenCV-Mat结构详解的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV - Mat::convertTo() 断言错误。
opencv学习笔记详解基本图像容器Mat以及常用数据结构和函数
详解用OpenCV的轮廓检测函数findContours()得到的轮廓拓扑结构(hiararchy)矩阵的意义以及怎样用轮廓拓扑结构矩阵绘制轮廓拓扑结构图
详解OpenCV的Mat类(构造方法初始化方法常用属性常用成员函数常用操作)