在早期的OpenCV1.x版本中,图像的处理是通过IplImage(该名称源于Intel的另一个开源库Intel Image Processing Library ,缩写成IplImage)结构来实现的。早期的OpenCV是用C语言编写,因此提供的借口也是C语言接口,其源代码完全是C的编程风格。IplImage结构是OpenCV矩阵运算的基本数据结构。
到OpenCV2.x版本,OpenCV开源库引入了面向对象编程思想,大量源代码用C++重写,Mat类 (Matrix的缩写) 是OpenCV用于处理图像而引入的一个封装类。从功能上讲,Mat类在IplImage结构的基础上进一步增强,并且,由于引入C++高级编程特性,Mat类的扩展性大大提高,Mat类的内容在后期的版本中不断丰富,如果你查看Mat类的定义的话
该对象会自动分配内存、自动管理内存分配和释放,不存在内存泄漏的问题,OpenCV2.x版本以后,越来越多的函数实现了MatLab所具有的功能,甚至干脆连函数名都一模一样(如 imread, imshow,imwriter等), 这些属性和方法如果你学过Matlab掌握起来一定会很快。接下来介绍一下Mat对象的一些重要的属性和方法。
Mat的构造函数
Mat(); // 默认构造函数
Mat(int rows, int cols, int type); //指定行数、列数、类型的构造函数
Mat(Size size, int type); // 指定矩阵大小、类型的构造函数
Mat(int rows, int cols, int type, const Scalar& s); // 指定矩阵行列、类型、颜色的构造函数
Mat(Size size, int type, const Scalar& s);// 指定矩阵大小、类型、颜色的构造函数
Mat(int ndims, const int* sizes, int type);
Mat(int ndims, const int* sizes, int type, const Scalar& s);
Mat(const Mat& 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=0);
#include
#include
using namespace cv;
using namespace std;
const char *INPUT_WIN = "input";
const char *OUTPUT_WIN = "output";
int main(int argc, char **argv){
Mat src, dst;
src = imread("3.png");
if (!src.data){
cout << "can not load image" << endl;
return -1;
}
namedWindow(INPUT_WIN, CV_WINDOW_AUTOSIZE);
imshow(INPUT_WIN, src);
// start your code...
Mat m1; // m1为用默认拷贝构造创建的对象
Mat m2(500, 500, CV_8UC3);//指定行数、列数、类型的构造函数 CV_8UC3:8位无符号3通道图像
m2 = Scalar(10, 20, 30);
Mat m3(Size(300, 300), CV_8UC3); // 指定矩阵大小、类型的构造函数
m3 = Scalar(50, 10, 215);
Mat m4 = Mat(400, 400, CV_8UC3, Scalar(255, 0, 255)); // 指定矩阵行列、类型、颜色的构造函数 Scalar(255,0,0):颜色列表依次为b g r
Mat m5 = Mat(src.size(), src.type()); // 创建一个和原图大小类型相同的图像*************
//namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);
imshow("m2", m2);
imshow("m3", m3);
imshow("m4", m4);
imshow("m5", m5);
waitKey(0);
return 0;
}
属性:
/*! includes several bit-fields:
- the magic signature
- continuity flag
- depth
- number of channels
*/
int flags;
//! the matrix dimensionality, >= 2
int dims; // 矩阵的维度, >=2
//! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
int rows, cols; // 矩阵的行数和列数,不止二维用(-1,-1)
//! pointer to the data
uchar* data; // 指向数据的指针
//! helper fields used in locateROI and adjustROI
const uchar* datastart; // 在感兴趣区域(ROI)用到的
const uchar* dataend;
const uchar* datalimit;
在之前显示一张图片的基础上,可以很方便的显示这张图片的信息
【输入为彩色图像】
#include
#include
using namespace cv;
using namespace std;
const char *INPUT_WIN = "input";
const char *OUTPUT_WIN = "output";
int main(int argc, char **argv){
Mat src, dst;
src = imread("3.png");
if (!src.data){
cout << "can not load image" << endl;
return -1;
}
namedWindow(INPUT_WIN, CV_WINDOW_AUTOSIZE);
imshow(INPUT_WIN, src);
// start your code...
cout << "image Mat col: " << src.cols << endl;
cout << "image Mat row: " << src.rows << endl;
cout << "image dims: " << src.dims << endl;
//namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);
//imshow(OUTPUT_WIN, dst);
waitKey(0);
return 0;
}
常见方法
(1)用于拷贝图像
void copyTo( OutputArray m ) const;
void copyTo( OutputArray m, InputArray mask ) const;
Mat Mat::clone() const
(2)用于创建图像
void create(int rows, int cols, int type);
void create(Size size, int type);
void create(int ndims, const int* sizes, int type);
(3)基本方法
int type() const; // 返回矩阵的类型 列*行
bool empty() const; // 真:没有元素
int channels() const; //返回矩阵的通道数
size_t total() const; //返回总共的元素个数 num = cols*rows
int depth() const; //返回矩阵的深度 CV_8U CV_8S CV_16U CV_16SCV_32S CV_32F CV_64F
(4)指针方法
uchar* ptr(int i0, int i1); //返回指向指定矩阵行的指针。
(6)用于创建全0矩阵,全1矩阵,单位矩阵
zeros(Size size, int type);
zeros(int rows, int cols, int type);
zeros(int ndims, const int* sz, int type);
ones(int rows, int cols, int type);
ones(Size size, int type);
ones(int ndims, const int* sz, int type);
eye(int rows, int cols, int type);
eye(Size size, int type);
(7)不属于Mat的一种构造函数
Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);
用于给图像指定颜色 Scalar(b通道颜色,g通道颜色,r通道颜色)
Mat m1; // m1为用默认拷贝构造创建的对象
m1.create(300, 250, src.type()); // 创建图像 250*300 类型和原图一样
m1 = Scalar(0, 0, 0); // 黑色
m1 = Scalar(255, 0, 0); // blue
m1 = Scalar(0, 255, 0); // green
m1 = Scalar(0, 0, 255); // red
m1 = Scalar(255, 255, 255); // 白色
将数组转换为具有可选缩放的另一种数据类型
void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
求逆矩阵
inv(int method=DECOMP_LU) const;
计算两个向量的点积
double dot(InputArray m) const;
实验结果
#include
#include
using namespace cv;
using namespace std;
const char *INPUT_WIN = "input";
const char *OUTPUT_WIN = "output";
int main(int argc, char **argv){
Mat src, dst;
src = imread("3.png");
if (!src.data){
cout << "can not load image" << endl;
return -1;
}
namedWindow(INPUT_WIN, CV_WINDOW_AUTOSIZE);
imshow(INPUT_WIN, src);
// start your code...
Mat m1; // m1为用默认拷贝构造创建的对象
m1.create(300, 250, src.type()); // 创建图像 250*300 类型和原图一样
m1 = Scalar(0, 0, 0); // 黑色
//m1 = Scalar(255, 0, 0); // blue
//m1 = Scalar(0, 255, 0); // green
//m1 = Scalar(0, 0, 255); // red
//m1 = Scalar(255, 255, 255); // 白色
//copy
Mat m2, m3;
src.copyTo(m2); // m2和src是一样的图像
m3 = m2.clone(); // m3和m2是一样的图像
// 全0阵 全1阵
Mat m4;
m4.zeros(Size(100, 100), src.type()); // 100*100个元素全为0 类型CV_8UC3
Mat m5 = Mat::ones(10, 9, CV_8UC1);
// 基本方法
cout << "size(): " << m5.size() << endl; // 9*10
cout << "channels(): " << m5.channels() << endl; // 1通道
cout << "type(): " << m5.type() << endl; // 0
//namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);
imshow("m", m1);
// 打印矩阵
Mat m6(10, 10, CV_8UC3, Scalar(255, 0, 255));
cout << "m6 = " << endl << m6 << endl;
//创建小数组
Mat m7 = (Mat_(4, 4) << 0, 1, 22, 5, 2, 5, 0, 6, 2, 3, 6, 33, 50, 5, 22, 6);
cout << "m7 = " << m7 << endl;
cout << "channels = " << m7.channels() << endl;
cout << "size = " << m7.size() << endl;
waitKey(0);
return 0;
}