1、初识Mat
构造Mat对象相当于构造了一个矩阵(数组),需要四个基本要素:行数
列数、通道数以及数据类型,所以Mat类的构造函数如下:
Mat(int rows, int cols, int type)
Mat(Size(int cols, int rows), int type)// Size 第一个元素是矩阵的列数(宽)
2、构造单通道Mat对象
int main()
{
//构造2行3列的矩阵
Mat m = Mat(2, 3, CV_32FC1);
Mat o = Mat::ones(2, 3, CV_32FC1); //2行3列全是1的float 类型单通道矩阵
Mat m = Mat::zeros(Size(3, 2), CV_32FC1); //2行3列全是0的float 类型单通道矩阵
Mat m1 = Mat::zeros(Size(2, 3), CV_32FC1); //3行2列全是0的float 类型单通道矩阵
return 0;
}
3、获得单通道Mat的基本信息
int main()
{
//构造2行3列的矩阵
Mat m = Mat(2, 3, CV_32FC1);
cout << "行数:" << m.rows << endl;
cout << "列数:" << m.cols << endl;
Mat m1 = (Mat_<int>(3, 2) << 11, 22, 33, 44, 55, 66); //3行2列
Size size = m1.size();
cout << "尺寸:" << size << endl;
cout << "通道数:" << m1.channels() << endl;
cout << "面积:" << m1.total() << endl;
cout <<"维数:"<<m1.dims << endl;
return 0;
}
程序打印结果为:
行数:2
列数:3
尺寸:[3 x 2]
通道数:1
面积:6
维数:2
4、访问单通道Mat对象中的值(利用成员函数)
1、利用at成员函数
int main()
{
Mat m = (Mat_<int>(3, 2) << 11, 22, 33, 44, 55, 66); //3行2列
for (int r = 0; r < m.rows; r++)
{
for (int c = 0; c < m.cols; c++)
{
cout << m.at<int>(r, c) << ","; //r行c列的值
}
cout << endl;
}
}
程序打印结果为:
11,22,
33,44,
55,66,
2、利用ptr成员函数
int main()
{
Mat m = (Mat_<int>(3, 2) << 11, 22, 33, 44, 55, 66); //3行2列
for (int r = 0; r < m.rows; r++)
{
//得到矩阵m的第r行行首地址
const int *ptr = m.ptr<int>(r);
//打印第r行的所有值
for (int c = 0; c < m.cols; c++)
{
cout << ptr[c] << ",";
}
cout << endl;
}
}
程序打印结果为:
11,22,
33,44,
55,66,
3、利用isContinuous和ptr成员函数
int main()
{
// 函数 isContinuous 实例
Mat m = (Mat_<int>(3, 2) << 11, 22, 33, 44, 55, 66); //3行2列
//isContinuous含义,每一行的所有值存储在连续的内存区域中,行与行之间可能有间隔
//如果isContinuous返回值为true,则代表行与行之间也是连续存储,即所有的值是连续存储
if (m.isContinuous())
{
//得到矩阵m的第r行行首地址
const int *ptr = m.ptr<int>(0);
//打印第r行的所有值
for (int c = 0; c < m.cols *m.rows; c++)
{
cout << ptr[c] << ",";
}
cout << endl;
}
}
程序打印结果为:
11,22,33,44,55,66,
4、利用data和step成员变量
int main()
{
//函数 data 和 step 实例
Mat m = (Mat_<int>(3, 2) << 11, 22, 33, 44, 55, 66); //3行2列
for (int r = 0; r < m.rows; r++)
{
for (int c = 0; c < m.cols; c++)
{
//step[0]代表每一行所占的字节数,如果有间隔,间隔也作为字节数的一部分计算在内
//step[1]代表每一个数值所占的字节数,data是指向第一个数值的指针,类型为uchar
//int类型的单通道矩阵的第r行第c列的指
cout << *((int *)(m.data + m.step[0] * r + c * m.step[1])) << ",";
}
}
}
程序打印结果为:
11,22,33,44,55,66,
5、向量类Vec
OpenCV为向量类的声明取了一个别名
typedef Vec<uchar, 3> Vec3b;
typedef Vec<int, 2> Vec2i;
typedef Vec<float, 4> Vec4f;
typedef Vec<double, 3> Vec3d;
int main()
{
//向量类 Vec
//格式如:Vec<Typename _Tp, int _cn> 数据类型为_Tp;
//构造一个长度为3,数据类型为int
Vec<int, 3> vi(21, 32, 14);
cout << "向量的行数:" << vi.rows << endl;
cout << "向量的列数:" << vi.cols << endl;
cout << "访问第0个元素:" << vi[0] << endl;
cout << "访问第1个元素:" << vi(1) << endl;
}
程序打印结果为:
向量的行数:3
向量的列数:1
访问第0个元素:21
访问第1个元素:32
int main()
{
//向量类 Vec
Mat m = (Mat_<Vec3f>(2, 2) << Vec3f(1, 11, 21), Vec3f(2, 12, 32),
Vec3f(3, 13, 23), Vec3f(4, 14, 24));
for (int r = 0; r < m.rows; r++)
{
for (int c = 0; c < m.cols; c++)
{ //使用at函数
cout << m.at<Vec3f>(r, c) << ",";
}
cout << endl;
}
for (int r = 0; r < m.rows; r++)
{ //使用ptr函数
//每行首元素地址
Vec3f *ptr = m.ptr<Vec3f>(r);
for (int c = 0; c < m.cols; c++)
{
cout << ptr[c] << ",";
}
cout << endl;
}
for (int r = 0; r < m.rows; r++)
{
for (int c = 0; c < m.cols; c++)
{
Vec3f *ptr = (Vec3f *)(m.data + r * m.step[0] + c * m.step[1]);
cout << *ptr<< ",";
}
cout << endl;
}
}
程序打印结果相同都为:
[1,11,21],[2,12,32],
[3,13,23],[4,24,34]
6、分离通道和合并通道
多通道矩阵分离为多个单通道矩阵的时候,这些单通道矩阵都存放在vector中
vector<Mat> planes;
split(m, planes);
利用merge函数可以将多个单通道矩阵合并为一个三维矩阵
Mat plane0 = (Mat_<int>(2, 2) << 1, 2, 3, 4);
Mat plane1 = (Mat_<int>(2, 2) << 5, 6, 7, 8);
Mat plane2 = (Mat_<int>(2, 2) << 9, 10, 11, 12);
Mat plane[] = { plane0, plane1, plane2 };
Mat mat;
merge(plane, 3, mat);
//利用merge重载函数
vector<Mat> plane;
plane.push_back(plane0);
plane.push_back(plane1);
plane.push_back(plane2);
Mat mat;
merge(plane, mat);
}
7、获得Mat 中某一个区域的值
//使用成员函数row和col得到矩阵的i行j列 对于单通道如下
int r = 1;
int c = 0;
//矩阵的第r行
Mat mr = m.row(r);
//矩阵的第c列
Mat mc = m.col(c);
//获取到的返回值仍然是一个单通道的Mat类型
int main()
{
//使用成员函数rowRange和colRange得到矩阵的连续行或者连续列
//使用Mat构造函数构造matrix
Mat matrix = (Mat_<int>(5, 5) << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25);
Mat r_range = matrix.rowRange(Range(2, 4));
for (int r = 0; r < r_range.rows; r++)
{
for (int c = 0; c < r_range.cols; c++)
{
cout << r_range.at<int>(r, c) << ",";
}
cout << endl;
}
}
程序打印结果为:
11,12,13,14,15,
16,17,18,19,20,
colRange的使用方法类似。