(一)Mat矩阵中数据指针Mat.data是uchar类型指针,CV_8U系列可以通过计算指针位置快速地定位矩阵中的任意元素。
二维单通道元素可以用Mat::at(i, j)访问,i是行序号,j是列序号。
但对于多通道的非unsigned char类型矩阵来说,以上方法都不好(注:后来知道可以通过类型转换,用指针访问data数据,见后文)。可以用Mat::ptr()来获得指向某行元素的指针,在通过行数与通道数计算相应点的指针。
参照OpenCV的Mat::at()函数,写了一个访问二维Mat矩阵的两个简单的小函数,没有边界检查。
1 |
#include <opencv2/core/core.hpp> |
2 |
3 |
template < typename ItemType> |
4 |
ItemType* getMatPointPtr(cv::Mat & src, int i , int j , int c = 0) |
5 |
{ |
6 |
ItemType* curRow = src.ptr<ItemType>(i); |
7 |
return curRow + j * src.channels() + c; |
8 |
} |
9 |
template < typename ItemType> |
10 |
ItemType getMatPoint(cv::Mat & src, int i , int j , int c = 0) |
11 |
{ |
12 |
ItemType* curRow = src.ptr<ItemType>(i); |
13 |
return *(curRow + j * src.channels() + c); |
14 |
} |
OpenCV中的Mat::at()代码有严格的边界检测,Mat::ptr()也有边界检测,但代码中没有检测j是否越界。
以上为推荐使用的情况,下边的不推荐使用。
可以通过转换指针类型,访问非uchar类型的Mat元素。
例如图像是CV_64FC1格式,可以将Mat.data指针直接转换成double*类型:
1 |
// imgMat is a image. |
2 |
double * pimg = ( double *)(imgMat.data) |
也可以用C++中的显式转换符static_cast,不过要通过void*类型过渡:
1 |
void * pvoid = static_cast < void *>(imgMat.data); |
2 |
double * pimg = static_cast < double *>(pvoid); |
这种方式在Debug模式下速度提升非常显著,但没有任何的边界检查和异常处理,使用时必须十分小心。使用Mat::ptr的速度和直接使用这种方法差不多,多一层保护总比没有保护强。
(二)
9.现在改变 F 或者 G 就不会影响 Mat 信息头所指向的矩阵。总结一下,你需要记住的是
补充(空间存储):
10.对于 彩色 方式则有更多种类的颜色空间,但不论哪种方式都是把颜色分成三个或者四个基元素,通过组合基元素可以产生所有的颜色。然后,需要指定存储元素的数据类型以及每个矩阵点的通道数。为此,依据下面的规则有多种定义
15.在 C\C++ 中通过构造函数进行初始化
为已存在IplImage指针创建信息头:
Create() function: 函数
17.这个创建方法不能为矩阵设初值,它只是在改变尺寸时重新为矩阵数据开辟内存。
MATLAB形式的初始化方式: zeros(), ones(), :eyes() 。使用以下方式指定尺寸和数据类型:
*对于小矩阵你可以用逗号分隔的初始化函数:
*使用 clone() 或者 copyTo() 为一个存在的 Mat 对象创建一个新的信息头。