通道和维度
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
首先说一下对矩阵维度和通道的理解:
维:体现为坐标。
通道:
对于这样一个数组矩阵:
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
单通道显示的话,就是这样:
所以,单通道:可以理解为:一个元素中含有1个数字。
双通道就是把数组中每两个数(如30和60)结合在一起,如:
双通道可以
所以,双通道:可以理解为:一个元素中含有2个数字。
以此类推:三通道可以;理解为一个元素中有3分数字。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
打印双通道矩阵实例:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
实例解释:
cvInitMatHeader()函数:用来初始化Mat结构体;
cvInitMatHeader( CvMat* arr, int rows, int cols,int type, void* data, int step )
参数解释:
arr:CvMat结构体;
rows: 行数;
cols:列数;
type: 矩阵元素类型(可以是32位浮点型(CV_32FC1)或者是无符号的8位三元组的整形数据(CV_8UC3)或者其他类型);
这个也是改通道数的参数:如单通道(CV_32FC1),双通道(CV_32FC2),三通道(CV_32FC3);
data:矩阵数组;
step: 步长,默认是: 一行数据所占的字节数(int min_step = arr->cols*pix_size)。
cvGet2D()函数:对多通道二维矩阵访问。(多通道三维:cvGet3D(),多通道多维:cvGetND()等一系列:cvGet*D函数);
cvGetReal1D():对单通道一维矩阵访问,(单通道三维:cvGetReal3D(),单通道多维:cvGetRealND()等一系列:cvGetReal*D函数);*
这种访问方式比较慢因为涉及到压栈和出栈,如果矩阵较大的话耗费的时间也很多。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
下面介绍一种更有效率的访问方式,用指针访问矩阵元素:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CvMat矩阵结构
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
此类信息通常被称作为矩阵头。很多程序是区分矩阵头和数据体的,后者是各个data成员所指向的内存位置。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
矩阵的创建和释放:
创建一个新的矩阵,分配矩阵空间::
CvMat* cvCreateMat(int rows, int cols,int type);
例程:
CvMat* M = cvCreateMat(4,4,CV_32FC1);
创建一个矩阵头,,不分配空间:
CvMat* cvCreateMatHeader(int rows,int cols,int type);
初始化已存在的CvMat结构体:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
初始化一个矩阵,但是不分配空间:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
用一个矩阵初始化另外一个矩阵,也就是将一个矩阵的复制到另外一个矩阵上去:
CvMat* cvCloneMat(const cvMat* mat);
例:
CvMat* M1 = cvCreateMat(4,4,CV_32FC1);
CvMat* M2;
M2=cvCloneMat(M1);
释放矩阵空间:
例:
CvMat* M = cvCreateMat(4,4,CV_32FC1);
cvReleaseMat(&M);
上面我们用介绍通道和维所用到的矩阵就是通过:
用固定数据创建一个Opencv矩阵。
矩阵数据的存取
1,这是一个简单的方法:利用宏CV_MAT_ELSEM(),这个宏(传入矩阵,待提取的元素类型,行,列4个参数)(注意:行列是从0开始算的)
利用宏读取矩阵的值(简单但慢):
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
利用宏写矩阵的值:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
但是这种使用宏的方法有个缺点,在每次调用宏的时候都要重新计算指针,即使宏使用起来容易,但是慢,所以不是存取矩阵的最好方法。
指针访问矩阵结构(麻烦):
利用宏只能访问1维和2维的数组,下面列举cvPtr*D和cvGet*D等函数。
cvPtr*D可以是:cvPtr1D(一维),cvPtr2D(二维),cvPtr3D(三维),cvPtrND(多维),
cvGet*D也类似有这系列函数。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
实例:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
建立自己的指针访问(恰当的方法):