一般来说,灰度图像用2维矩阵表示,彩色(多通道)图像用3维矩阵(M X N X 3)表示。对于图像显示来说,目前大部分设备都是用无符号8位整数(类型为CV_8U)表示像素亮度。
图像数据在计算机内存中的存储顺序一图像最左上点(也可能是最左下点)开始,如图所示:
I ij 表示第 i 行 j 列的像素值。如果是多通道图像,比如 RGB 图像,则每个像素用三个字节表示。在 OpenCV 中,RGB 图像的通道顺序为 BGR:
Mat类
lplImage和CvMat都是C语言的结构被用来表示图像。使用这两个结构的问题是内存需要手动管理,开发者必须清楚的明白何时申请内存,何时释放内存。
新的Mat类能够自动管理内存。在新的OpenCV版本中,依旧可以使用IpIImage和CvMat,但是一些新增加的函数只提供Mat接口。
Mat类的定义:
class CV_EXPORTS Mat
{
public:
//一系列函数
...
/* flag 参数中包含许多关于矩阵的信息,如:
-Mat 的标识
-数据是否连续
-深度
-通道数目
*/
int flags;
//矩阵的维数,取值应该大于或等于 2
int dims;
//矩阵的行数和列数,如果矩阵超过 2 维,这两个变量的值都为-1
int rows, cols;
//指向数据的指针
uchar* data;
//指向引用计数的指针
//如果数据是由用户分配的,则为 NULL
int* refcount;
//其他成员变量和成员函数
...
};
创建Mat对象
常用的构造函数有:
Mat::Mat() 无参数构造方法;
Mat::Mat(int rows, int cols, int type) 创建行数为 rows,列数为 col,类型为 type 的图像;
Mat::Mat(Size size, int type) 创建大小为 size,类型为 type 的图像;
Mat::Mat(int rows, int cols, int type, const Scalar& s) 创建行数为 rows,列数为 col,类型为 type 的图像,并将所有元素初始化为值 s;
Mat::Mat(Size size, int type, const Scalar& s) 创建大小为 size,类型为 type 的图像,并将所有元素初始化为值 s;
Mat::Mat(const Mat& m) 将 m 赋值给新创建的对象, 此处不会对图像数据进行复制, m 和新对象共用图像数据;
Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP) 创建行数为 rows,列数为 col,类型为 type 的图像,此构造函数不创建图像数据所需内存, 而是直接使用 data 所指内存, 图像的行步长由 step指定。
Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP) 创建大小为 size,类型为 type 的图像,此构造函数不创建图像数据所需内存,而是直接使用 data 所指内存,图像的行步长由 step 指定。
Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange) 创建的新图像为 m 的一部分,具体的范围由 rowRange 和 colRange 指定, 此构造函数也不进行图像数据的复制操作, 新图像与 m 共用图像数据;
Mat::Mat(const Mat& m, const Rect& roi) 创建的新图像为 m 的一部分,具体的范围 roi 指定,此构造函数也不进行图像数据的复制操作,新图像与 m 共用图像数据。
矩阵的基本元素表达
对于单通道图像,其元素类型一般为 8U(即 8 位无符号整数) ,当然也可以是 16S、32F 等;这些类型可以直接用 uchar、short、float 等 C/C++语言中的基本数据类型表达。如果多通道图像,如 RGB 彩色图像,需要用三个通道来表示。
OpenCV 中有模板类 Vec,可以表示一个向量。OpenCV 中使用 Vec 类预定义了一些小向量,可以将之用于矩阵元素的表达。
typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;
typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;
typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<float, 2> Vec2f;
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;
typedef Vec<double, 2> Vec2d;
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;