IplImage 与 Mat
IplImage是OpenCV1中的图像存储结构体,基于C接口创建。在退出之前必须release,否则就会造成内存泄露。在一些只能使用C语言的嵌入式系统中,不得不使用。
IplImage* img = cvLoadImage("imagename.jpg",);
Mat类内存分配是自动完成的,不必手动开辟空间(非必须),不必在不需要时释放空间。
Mat类的构成
Mat由矩阵头和一个指向存储图像矩阵的指针组成。为应该尽量避免图像的复制,加快程序运行速度,Mat的拷贝构造函数只复制信息头和矩阵指针,不复制矩阵。因此通过任何一个对象所做的改变也会影响其他对象。如果想要创建一个感兴趣的区域(Region of Interest (ROI))只需要创建包含边界信息的信息头:
Mat ROI1(matrix, Rect(x,y,width,height)); // use rectangle to set the boundary
Mat ROI2 = matrix(Range:all(), Range(,)); // use rows and cols
Mat通过对象计数机制来实现最后一个使用它的对象自动负责清理存储空间。如果想要复制矩阵本身,可以使用:
Mat duplicate1 = matrix.clone();
Mat duplicate2;
matrix.copyTo(duplicate2);
改变duplicate1和duplicate2不会影响matrix指向的矩阵。
构造函数
Mat()
Mat(int rows, int cols, int type, const Scalar & s)
- rows:矩阵行数
- cols:矩阵列数
- type:规定存储元素的数据类型和每个矩阵点的通道数
- CV_[the number of bits per item: 8/16/32/64] [Signed, Unsigned, or Float: S/U/F] C [The channel number: 1/2/3/4]
- CV_8UC3:三通道8位的unsigned char型
- s:可以省去,Scalar是short型的向量,用来初始化矩阵
Mat(Size size, int type, const Scalar & s)
- size: 二位矩阵尺寸,Size(cols, rows),注意维数尺寸跟前面的构造函数是相反的
- type和s:同上
Mat(int ndims, const int* sizes, type, const Scalar & s)
- ndims: 第二个参数,size矩阵,的维数
- sizes: 整型矩阵,规定Mat的尺寸
- type和s:同上
Mat (const Mat &m)
Mat (const Mat &m, const Range &rowRange, const Range &colRange=Range::all())
Mat (const Mat &m, const Rect &roi)
Mat (const Mat &m, const Range *ranges)
- m: 赋值矩阵,它的部分或者全部值将以指针传递给构造出的矩阵,注意数据不会被拷贝给新矩阵
- 其他参数:规定赋值部分的范围
Mat (int rows, int cols, int type, void *data, size_t step=AUTO_STEP)
Mat (Size size, int type, void *data, size_t step=AUTO_STEP)
Mat (int ndims, const int *sizes, int type, void *data, const size_t *steps=)
- data:指向用户数据的指针,构造的矩阵将指向这些用户数据,没有进行数据拷贝
- step:矩阵更新到下一行需要跨过的字节数,如果矩阵每行的尾部包含无用的填充数据,需要把这部分计算进去,自动计算时设为cols*elemSize()
- 其他参数:设置矩阵的大小和类型
Mat::Mat(const IplImage* img, bool copyData=false)
- img: IplImage类型的图,利用它来创建信息头
Mat (const std::vector< _Tp > &vec, bool copyData=false)
- vec:STL vector,矩阵行数等于vec的元素数,矩阵的数据类型与vec相同,因此vec必须为单一类型的数据结构。默认情况下,不会进行数据拷贝,这种情况下在矩阵被释放之前,不能再向vec内加入新数据(这样会造成存储空间重新分配,之前的指针可能会失效)或进行其他可能改变vec内存空间的操作。
其他构造函数可以参见OpenCV Documentation:
其他初始化方法
void create (int rows, int cols, int type)
void create (Size size, int type)
void create (int ndims, const int *sizes, int type)
分配新内存,但不能为矩阵设置初值。大部分需要分配空间的OpenCV函数都会从内部调用这个函数,所以在调用他们之前不用手动分配内存空间
- 如果现在矩阵的形状数据类型与目标相同,直接返回。否则释放原来的内存空间。
- 初始化新矩阵头
- 分配total()*elemSize()字节内存
- 设置新的对象计数值,并设为1
static MatExpr eye (int rows, int cols, int type)
static MatExpr eye (Size size, int type)
static MatExpr ones (int rows, int cols, int type)
static MatExpr ones (Size size, int type)
static MatExpr ones (int ndims, const int *sz, int type)
static MatExpr zeros (int rows, int cols, int type)
static MatExpr zeros (Size size, int type)
static MatExpr zeros (int ndims, const int *sz, int type)
Matlab形式的初始化方式。MatExpr是Matrix expression representation,可以进行各种矩阵运算操作。用法如下,
Mat E = Mat::eye(,,CV_64F);
Mat O = Mat::ones(,,CV_32F)*0.1;
逗号分隔式初始化
Mat C = (Mat_<double>(,) << ,-,, -,,-, ,-,);
Mat clone () const
void copyTo (OutputArray m) const
void copyTo (OutputArray m, InputArray mask) const
拷贝矩阵,回先调用create函数分配内存空间,
- mask:非零数据代表了需要拷贝的数据,如果传递了这个参数那么分配完内存空间后,矩阵先被初始化为0,mask是CV_8U类型可以包含一个或多个通道
格式化输出方法
5种输出风格:OpenCV默认,Python,逗号分隔,Numpy, C语言风格。事例程序和运行结果如下:
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
// main
int main( int argc, char** argv )
{
cv::Mat r = cv::Mat(,,CV_8UC3);
cv::randu(r, cv::Scalar::all(), cv::Scalar::all()); // [1] OpenCV default style
std::cout << "r (OpenCV default style) = \n" << r << ";" << std::endl << std::endl; // [2] Python style
// OpenCV2
// std::cout << "r (Python style) = " << format(r,"python") << ";" << std::endl << std::endl;
// OpenCV3
std::cout << "r (Python style) = \n" << format(r,cv::Formatter::FMT_PYTHON) << ";" << std::endl << std::endl; // [3] Comma separated values (CSV)
// OpenCV2
// std::cout << "r (CSV style) = " << format(r,"csv") << ";" << std::endl << std::endl;
// OpenCV3
std::cout << "r (CSV style) = \n" << format(r,cv::Formatter::FMT_CSV) << ";" << std::endl << std::endl; // [4] Numpy style
// OpenCV2
// std::cout << "r (Numpy style) = " << format(r,"numpy") << ";" << std::endl << std::endl;
// OpenCV3
std::cout << "r (Numpy style) = \n" << format(r,cv::Formatter::FMT_NUMPY) << ";" << std::endl << std::endl; // [3] C style
// OpenCV2
// std::cout << "r (C style) = " << format(r,"C") << ";" << std::endl << std::endl;
// OpenCV3
std::cout << "r (C style) = \n" << format(r,cv::Formatter::FMT_C) << ";" << std::endl << std::endl; return ;
}
r (OpenCV default style) =
[ , , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ;
, , , , , , , , ]; r (Python style) =
[[[ , , ], [, , ], [, , ]],
[[, , ], [, , ], [, , ]],
[[, , ], [ , , ], [, , ]],
[[, , ], [, , ], [ , , ]],
[[ , , ], [, , ], [, , ]],
[[ , , ], [, , ], [, , ]],
[[, , ], [ , , ], [ , , ]],
[[, , ], [, , ], [ , , ]],
[[, , ], [ , , ], [ , , ]],
[[, , ], [, , ], [ , , ]]]; r (CSV style) =
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
; r (Numpy style) =
array([[[ , , ], [, , ], [, , ]],
[[, , ], [, , ], [, , ]],
[[, , ], [ , , ], [, , ]],
[[, , ], [, , ], [ , , ]],
[[ , , ], [, , ], [, , ]],
[[ , , ], [, , ], [, , ]],
[[, , ], [ , , ], [ , , ]],
[[, , ], [, , ], [ , , ]],
[[, , ], [ , , ], [ , , ]],
[[, , ], [, , ], [ , , ]]], dtype='uint8'); r (C style) =
{ , , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , ,
, , , , , , , , };