前面博客中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结构详解的更多相关文章

  1. [OpenCV]Mat类详解

    http://blog.csdn.net/yang_xian521/article/details/7107786 Preface Mat:Matrix Mat类可以被看做是opencv中C++版本的 ...

  2. opencv数据结构-MAT结构详解

    1.定义 OpenCV中的C结构体有 CvMat 和 CvMatND,但后续的应用中指出 CvMat 和 CvMatND 弃用了,在C++封装中用 Mat 代替,另外旧版还有一个 IplImage,同 ...

  3. OpenCV参考手册之Mat类详解

    OpenCV参考手册之Mat类详解(一) OpenCV参考手册之Mat类详解(二) OpenCV参考手册之Mat类详解(三)

  4. Mat的详解

    [转]OpenCV中Mat的详解 每次碰到Mat都得反复查具体的用法,网上的基础讲解不多,难得看到一篇,赶快转来收藏~ 原文地址:http://www.opencvchina.com/thread-1 ...

  5. BS模式的模型结构详解

    编号:1004时间:2016年4月12日16:59:17功能:BS模式的模型结构详解 URL:http://blog.csdn.net/icerock2000/article/details/4000 ...

  6. Linux下的文件目录结构详解

    Linux下的文件目录结构详解 / Linux文件系统的上层根目录 /bin 存放用户可执行的程序 /boot 操作系统启动时所需要的文件 /dev 接口设备文件目录,例如:had表示硬盘 /etc ...

  7. PHP扩展代码结构详解

    PHP扩展代码结构详解: 这个是继:使用ext_skel和phpize构建php5扩展  内容 (拆分出来) Zend_API:深入_PHP_内核:http://cn2.php.net/manual/ ...

  8. Android系统目录结构详解

    Android系统基于linux内核.JAVA应用,算是一个小巧精致的系统.虽是开源,但不像Linux一般庞大,娇小可亲,于是国内厂商纷纷开发出自己基于Android的操作系统.在此呼吁各大厂商眼光放 ...

  9. Linux文件系统的目录结构详解

    Linux文件系统的目录结构详解   一.前 言 文章对Linux下所有目录一一说明,对比较重要的目录加以重点解说,以帮助初学者熟练掌握Linux的目录结构. 二.目 录 1.什么是文件系统 2.文件 ...

随机推荐

  1. .NET Core DI简单介绍

    依赖注入的基础 我们都知道DI,,他是一种开发模式.他是将服务可被应用程序任何位置的代码使用,当某个代码组件(如一个类)需要引用某些外部代码(一个服务)时.都有两种选择 1:直接在调用代码种创建服务组 ...

  2. P4939 Agent2

    链接:P4939 ------------------------------------------------ 这道题肯定是数据结构题. ----------------------------- ...

  3. BZOJ #2989. 数列 [树套树]

    考虑转化问题模型,这个没必要可持久化,直接加点就可以了,还不用删点 每次的问题是求 曼哈顿距离,变成切比雪夫距离然后求解 然后我们考虑将这玩意旋转 45度, 然后原坐标的 \((x,y)\) 会变成 ...

  4. swiper滑动失效问题

    最近在写移动端的项目,页面有用的是swiper滑动的. 但是会发现在滑动时,不灵活,就是滑动时隐藏的数据会显示,但是不滑动数据又在初始那,隐藏的数据还是看不到. 于是各种排除问题,终于在pc端+移动端 ...

  5. 清北学堂—2020.1提高储备营—Day 1 morning(模拟、枚举、搜索)

    qbxt Day 1 morning --2020.1.17 济南 主讲:李佳实 目录一览 1.模拟和枚举 2.基础搜索算法(DFS.BFS.记忆化搜索)以及进阶搜索算法(纯靠自学) 总知识点:基础算 ...

  6. 方法重载(method overloading)

    为什么需要方法重载? 在编程语言中,名字的使用很重要.创建对象的时候,我们给一块内存区域起一个名字,然后这个名字就是我们创建的对象的引用,只要我们"叫"这个名字,计算机就知道我们在 ...

  7. Java自学-Lambda 方法引用

    Lambda 方法引用 步骤 1 : 引用静态方法 首先为TestLambda添加一个静态方法: public static boolean testHero(Hero h) { return h.h ...

  8. NOI Online能力测试游记:退役选手的自娱自乐

    2020年2月17日早上8点,CCF发布了关于举办NOI Online能力测试的通知. 为给选手提供一个锻炼的机会,CCF拟举办一场NOI Online能力测试.测试分为入门组和提高组,每组限额报名3 ...

  9. linux100讲——80 系统函数库介绍

    1.系统自建了函数库,可以在脚本中引用 /etc/init.d/functions 2.自建函数库 使用 source 函数脚本文件 “导入”函数 3. vim /etc/init.d/functio ...

  10. [CF1303E] Erase Subsequences - dp

    Solution 不由分说地枚举分割点 令 \(f[i][j]\) 表示原串处理到 \(i\) ,\(s_1\) 处理到 \(j\),\(s_2\) 最多能处理到哪里 采用主动转移 任意情况, \(f ...