首页 > 代码库 > OpenCV 中的三大数据类型:CvMat 类型

OpenCV 中的三大数据类型:CvMat 类型

前言

  本文将介绍 OpenCV 中的矩阵结构 CvMat 并提供几个很常用的矩阵使用方法。

  更多的矩阵处理函数还请参阅相关资料。

CvMat 的类型定义

 1 typedef struct CvMat
 2 {
 3     int type;    // 数据类型
 4     int step;    // 行长度
 5     int* refcount;    /* 内部使用 */
 6     int hdr_refcount;    /* 内部使用 */
 7     union    // 指向数据区的指针
 8     {
 9         uchar* ptr;
10         short* s;
11         int* i;
12         float* fl;
13         double* db;
14     } data;
15     union    // 行数
16     {
17         int rows;
18         int height;
19     };
20     union    // 列数
21     {
22         int cols;
23         int width;
24     };
25 } CvMat;

CvMat 的创建方法

  创建矩阵函数:

1 cvMat * cvCreateMat (int rows, int cols, int type);

  rows:行数

  cols:列数

  type:数据类型,其格式一般为 CV_<比特数>(S|U|F)C<通道数>,比如 CV_32FC3 就表示 32 位浮点类型的 3 通道矩阵。

CvMat 中单个元素的存取方法

  1. 可以使用宏 CV_MAT_ELEM () 来实现对矩阵某个元素的读取,如下代码访问矩阵中的第 3 行 2 列的元素:

1 float elem_3_2 = CV_MAT_ELEM (*mat, float, 3, 2);

  其中,mat是 CvMat * 类型,float 是类型说明,最后两个参数是元素的行和列,该宏返回指定的元素的值

  2. 可以使用宏 CV_MAT_ELEM_PTR () 来实现对矩阵某个元素的设置,该宏返回指向指定元素的指针,如下代码修改矩阵中的第 3 行 2 列的元素:

1 *((float *)CV_MAT_ELEM_PTR (*mat, 3, 2)) = elem_3_2;

  需要说明的是,获取到指向指定元素的指针后,还需要对这个指针进行强制转型方能正常使用

CvMat 的遍历方法

  如果遍历采用一个个取元素的方法,未免效率太慢。实际应用中,对矩阵的遍历常常采用指针遍历法,如下代码展示了对一个 CvMat 矩阵的遍历:

 1 // 此头文件包含图像IO函数的声明
 2 #include "highgui.h"
 3  // 此头文件包含基本的图像处理函数和高级计算机视觉算法
 4 #include "cv.h"
 5 #include <iostream>
 6 
 7 #define R 10    // 矩阵行
 8 #define C 10    // 矩阵列
 9 
10 using namespace std;
11 
12 int main (void) {
13     
14     // 创建 R 行 C 列 32位单通道浮点类型的矩阵
15     CvMat *m1 = cvCreateMat ( R, C, CV_32FC1 );
16     
17     // 赋值变量
18     float s = 1.0f;
19     // 遍历矩阵并赋值
20     for (int i=0; i<R; i++) {
21         // 获取矩阵每行的行首地址,下面的data成员必须先取其ptr成员计算完偏移地址后,再强制转化为目标数据类型。
22         float *ptr = (float *)(m1->data.ptr + i * m1->step);
23         // 遍历子一维数组
24         for (int j=0; j<C; j++) {
25             ptr[j] = s++;
26         }
27     }
28 
29     // 打印结果
30     for (int i=0; i<m1->rows; i++) {
31         float *ptr = (float *)(m1->data.ptr + i * m1->step);
32         for (int j=0; j<m1->cols; j++) {
33             printf("%7.2f", *ptr);
34             ptr++;
35         }
36         cout << endl;
37     }
38     cout << endl << endl;
39 
40     getchar();
41 
42     return 1;
43 }

  运行结果:

  

 说明

  1. 一般尽量创建浮点矩阵( F 型 ),别的类型值可以向上转型后存放进去。

  2. 如果要遍历的是字符型( U S 型 )矩阵,那么遍历指针一定要设定为字符型的,等到取出的时候再向上转型/存进的时候向下转型即可。