我们有多种方式从现实世界中获取数字图像:数码相机,扫描仪,计算机断层扫描和磁共振成像等等。在任何情况下,我们(人类)看到的都是图像。然而,当将其转换为数字设备时,我们记录的是图像中每个点的数值。
Mat A, C; // creates just the header parts
A = imread(argv[1], IMREAD_COLOR); // here we'll know the method used (allocate matrix)
Mat B(A); // Use the copy constructor
C = A; // Assignment operator
这是关于如何存储像素值。您可以选择使用的颜色空间和数据类型。颜色空间是指我们如何组合颜色分量以编码给定的颜色。最简单的一个是灰色,我们可以使用的颜色是黑色和白色。这些组合使我们能够创建许多灰色阴影。
对于丰富多彩的方式,我们有更多的选择方法。他们每个人都将它们分解成三到四个基本组件,我们可以使用这些组合来创建其他组件。最流行的是RGB,主要是因为这也是我们的眼睛如何建立颜色。其基色为红,绿,蓝。为了编码颜色的透明度有时是第四个元素:添加了α(A)。
然而,还有许多其他颜色系统都有自己的优势:
每个建筑组件都有自己的有效域。这导致使用的数据类型。我们如何存储组件定义了我们在其域中的控件。可能的最小数据类型是char,这意味着一个字节或8位。这可能是无符号的(因此可以存储从0到255的值)或带符号(从-127到+127的值)。尽管在三个组件的情况下,这已经提供了1600万个可能的颜色来表示(像在RGB情况下),我们可以通过使用浮点数(4字节= 32位)或双(8字节= 64位)数据来获得更精细的控制每个组件的类型。然而,请记住,增加组件的大小也会增加内存中整个画面的大小。
在加载,修改和保存图像教程中,您已经学习了如何使用cv :: imwrite()函数将矩阵写入图像文件。但是,为了调试目的,查看实际值更为方便。您可以使用Mat的“操作符”来执行此操作。请注意,这仅适用于二维矩阵。
虽然Mat作为一个图像容器非常好,但它也是一个通用的矩阵类。因此,可以创建和操纵多维矩阵。您可以通过多种方式创建Mat对象:#
#include "opencv2/core.hpp"
#include
using namespace std;
using namespace cv;
int main(int, char**)
{
//构造函数构建
Mat M(2, 2, CV_8UC3, Scalar(0, 0, 255));
cout << " M = " << endl << "" << M << endl << endl;
return 0;
}
执行结果:
M =
[ 0, 0, 255, 0, 0, 255;
0, 0, 255, 0, 0, 255]
对于二维和多通道图像,我们首先定义它们的大小:行和列数明智。
然后,我们需要指定用于存储元素的数据类型和每个矩阵点的通道数。为此,我们根据以下约定构造了多个定义:
CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]
例如,CV_8UC3意味着我们使用8位长的无符号字符类型,每个像素有三个形成三个通道。这是最多四个通道号预定义的。该CV ::标量是四个元件短矢量。指定这一点,您可以使用自定义值初始化所有矩阵点。如果您需要更多功能,您可以使用上部宏来创建类型,在括号中设置通道号,如下所示。
int sz[3] = {2,2,2};
Mat L(3,sz, CV_8UC(1), Scalar::all(0));
上面的例子显示了如何创建一个具有两维以上的矩阵。指定其维度,然后传递一个包含每个维的大小的指针,其余的保持不变。
#include "opencv2/core.hpp"
#include
using namespace std;
using namespace cv;
int main(int, char**)
{
//Create函数构建
Mat M;
M.create(4, 4, CV_8UC(2));
cout << " M = " << endl << "" << M << endl << endl;
return 0;
}
执行结果:
M =
[116, 0, 46, 0, 79, 0, 102, 0;
102, 0, 105, 0, 99, 0, 101, 0;
46, 0, 68, 0, 101, 0, 115, 0;
107, 0, 116, 0, 111, 0, 112, 0]
您无法使用此结构初始化矩阵值。如果新的大小不适合旧的,它将仅重新分配其矩阵数据存储器。
#include "opencv2/core.hpp"
#include
using namespace std;
using namespace cv;
int main(int, char**)
{
//用matlab创建 1或0矩阵
Mat E = Mat::eye(4, 4, CV_64F);
cout << "E = " << endl << "" << E << endl << endl;
Mat O = Mat::ones(2, 2, CV_32F);
cout << "O = " << endl << "" << O << endl << endl;
Mat Z = Mat::zeros(3, 3, CV_8UC1);
cout << "Z = " << endl << "" << Z << endl << endl;
return 0;
}
执行结果:
E =
[1, 0, 0, 0;
0, 1, 0, 0;
0, 0, 1, 0;
0, 0, 0, 1]
O =
[1, 1;
1, 1]
Z =
[ 0, 0, 0;
0, 0, 0;
0, 0, 0]
#include "opencv2/core.hpp"
#include
using namespace std;
using namespace cv;
int main(int, char**)
{
//创建一个3x3双精度单位矩阵
Mat C = (Mat_<double>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
cout << "C = " << endl << "" << C << endl << endl;
return 0;
}
C =(Mat_ <double>({0,-1,0,-1,5,-1,0,-1,0}))。reshape(3);
cout << “C =” << endl << “”“ << C << endl << endl;
执行结果:
C =
[0, -1, 0;
-1, 5, -1;
0, -1, 0]
#include "opencv2/core.hpp"
#include
using namespace std;
using namespace cv;
int main(int, char**)
{
#ifdef CV_CXX11
//! [list]
Mat C;
C = (Mat_<double>({ 0, -1, 0, -1, 5, -1, 0, -1, 0 })).reshape(3);
cout << "C = " << endl << "" << C << endl << endl;
//! [list]
#endif
//! [clone]
Mat RowClone = C.row(1).clone();
cout << "RowClone = " << endl << " " << RowClone << endl << endl;
//! [clone]
return 0;
}
执行结果:
C =
[0, -1, 0;
-1, 5, -1;
0, -1, 0]
RowClone =
[-1, 5, -1]
使用cv :: randu()函数填入随机值的矩阵。您需要给出随机值的较低和较高值:
您可以看到默认的格式化选项。然而,OpenCV允许您格式化矩阵输出:
#include "opencv2/core.hpp"
#include
using namespace std;
using namespace cv;
int main(int, char**)
{
//用随机值填充一个矩阵
Mat R = Mat(3, 2, CV_8UC3);
randu(R, Scalar::all(0), Scalar::all(255));
//演示输出格式化选项
cout << "R (default) = " << endl << R << endl << endl;
return 0;
}
执行结果:
R (default) =
[ 91, 2, 79, 179, 52, 205;
236, 8, 181, 239, 26, 248;
207, 218, 45, 183, 158, 101]
cout << "R (python) = " << endl << format(R, Formatter::FMT_PYTHON) << endl << endl;
执行结果:
R (python) =
[[[ 91, 2, 79], [179, 52, 205]],
[[236, 8, 181], [239, 26, 248]],
[[207, 218, 45], [183, 158, 101]]]
cout << "R (csv) = " << endl << format(R, Formatter::FMT_CSV) << endl << endl;
执行结果:
R (csv) =
91, 2, 79, 179, 52, 205
236, 8, 181, 239, 26, 248
207, 218, 45, 183, 158, 101
cout << "R (numpy) = " << endl << format(R, Formatter::FMT_NUMPY) << endl << endl;
执行结果:
R (numpy) =
array([[[ 91, 2, 79], [179, 52, 205]],
[[236, 8, 181], [239, 26, 248]],
[[207, 218, 45], [183, 158, 101]]], dtype='uint8')
cout << "R (c) = " << endl << format(R, Formatter::FMT_C) << endl << endl;
执行结果:
R (c) =
{ 91, 2, 79, 179, 52, 205,
236, 8, 181, 239, 26, 248,
207, 218, 45, 183, 158, 101}
OpenCV还通过<<运算符来支持其他常见OpenCV数据结构的输出:
#include "opencv2/core.hpp"
#include
using namespace std;
using namespace cv;
int main(int, char**)
{
Point2f P(5, 1);
cout << "Point (2D) = " << P << endl << endl;
return 0;
}
执行结果:
Point (2D) = [5, 1]
Point3f P3f(2, 6, 7);
cout << "Point (3D) = " << P3f << endl << endl;
执行结果:
Point (3D) = [2, 6, 7]
vector<float> v;
v.push_back((float)CV_PI); v.push_back(2); v.push_back(3.01f);
cout << "Vector of floats via Mat = " << Mat(v) << endl << endl;
执行结果:
Vector of floats via Mat = [3.1415927;
2;
3.01]
vector<Point2f> vPoints(20);
for (size_t i = 0; i < vPoints.size(); ++i)
vPoints[i] = Point2f((float)(i * 5), (float)(i % 7));
cout << "A vector of 2D Points = " << vPoints << endl << endl;
执行结果:
A vector of 2D Points = [0, 0;
5, 1;
10, 2;
15, 3;
20, 4;
25, 5;
30, 6;
35, 0;
40, 1;
45, 2;
50, 3;
55, 4;
60, 5;
65, 6;
70, 0;
75, 1;
80, 2;
85, 3;
90, 4;
95, 5]
完整的源代码:
#include "opencv2/core.hpp"
#include
using namespace std;
using namespace cv;
static void help()
{
cout
<< "\n---------------------------------------------------------------------------" << endl
<< "This program shows how to create matrices(cv::Mat) in OpenCV and its serial"
<< " out capabilities" << endl
<< "That is, cv::Mat M(...); M.create and cout << M. " << endl
<< "Shows how output can be formatted to OpenCV, python, numpy, csv and C styles." << endl
<< "Usage:" << endl
<< "./mat_the_basic_image_container" << endl
<< "-----------------------------------------------------------------------------" << endl
<< endl;
}
int image(int, char**)
{
help();
//构造函数构建
Mat M(2, 2, CV_8UC3, Scalar(0, 0, 255));
cout << "M = " << endl << " " << M << endl << endl;
//Create函数构建
M.create(4, 4, CV_8UC(2));
cout << "M = " << endl << " " << M << endl << endl;
//创建多维矩阵
int sz[3] = { 2,2,2 };
Mat L(3, sz, CV_8UC(1), Scalar::all(0));
//用matlab创建 1或0矩阵
Mat E = Mat::eye(4, 4, CV_64F);
cout << "E = " << endl << " " << E << endl << endl;
Mat O = Mat::ones(2, 2, CV_32F);
cout << "O = " << endl << " " << O << endl << endl;
Mat Z = Mat::zeros(3, 3, CV_8UC1);
cout << "Z = " << endl << " " << Z << endl << endl;
//创建一个3x3双精度单位矩阵
Mat C = (Mat_<double>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
cout << "C = " << endl << " " << C << endl << endl;
//对初始化列表做同样的事吗
#ifdef CV_CXX11
C = (Mat_<double>({ 0, -1, 0, -1, 5, -1, 0, -1, 0 })).reshape(3);
cout << "C = " << endl << " " << C << endl << endl;
#endif
Mat RowClone = C.row(1).clone();
cout << "RowClone = " << endl << " " << RowClone << endl << endl;
//用随机值填充一个矩阵
Mat R = Mat(3, 2, CV_8UC3);
randu(R, Scalar::all(0), Scalar::all(255));
//演示输出格式化选项
cout << "R (default) = " << endl << R << endl << endl;
cout << "R (python) = " << endl << format(R, Formatter::FMT_PYTHON) << endl << endl;
cout << "R (numpy) = " << endl << format(R, Formatter::FMT_NUMPY) << endl << endl;
cout << "R (csv) = " << endl << format(R, Formatter::FMT_CSV) << endl << endl;
cout << "R (c) = " << endl << format(R, Formatter::FMT_C) << endl << endl;
// 其他常用项目的输出
Point2f P(5, 1);
cout << "Point (2D) = " << P << endl << endl;
Point3f P3f(2, 6, 7);
cout << "Point (3D) = " << P3f << endl << endl;
vector<float> v;
v.push_back((float)CV_PI); v.push_back(2); v.push_back(3.01f);
cout << "Vector of floats via Mat = " << Mat(v) << endl << endl;
vector<Point2f> vPoints(20);
for (size_t i = 0; i < vPoints.size(); ++i)
vPoints[i] = Point2f((float)(i * 5), (float)(i % 7));
cout << "A vector of 2D Points = " << vPoints << endl << endl;
return 0;
}
#include "opencv2\opencv.hpp"
#include
using namespace std;
using namespace cv;
int main(int argc, char argv)
{
Mat A(3, 2, CV_8UC1);//一通道
Mat B(3, 2, CV_32FC3);//三通道
cout << “A=” << endl << “” << A << endl;
cout << “B=” << endl << “” << B << endl;
}
执行结果:
A=
[144, 148;
151, 34;
249, 127]
B=
[0.00094728079, 8.1135181e-43, 0.00094956905, 8.1135181e-43, 0.00094929244, 8.1135181e-43;
0.00094728079, 8.1135181e-43, 0.00094728079, 8.1135181e-43, 0.00094728079, 8.1135181e-43;
0.00094709825, 8.1135181e-43, 0.00094728079, 8.1135181e-43, 0.00094728079, 8.1135181e-43]
#include "opencv2\opencv.hpp"
#include
using namespace std;
using namespace cv;
int main(int argc, char argv)
{
Mat A(3, 2, CV_8UC1);//一通道
Mat B(A.size(), CV_32FC3); //以A的大小定义
cout << “B=” << endl << “” << B << endl;
}
执行结果:
B=
[8.4436516e-24, 8.8141673e-43, 8.4758624e-24, 8.8141673e-43, 8.4709146e-24, 8.8141673e-43;
8.4436516e-24, 8.8141673e-43, 8.4436516e-24, 8.8141673e-43, 8.4436516e-24, 8.8141673e-43;
8.4411777e-24, 8.8141673e-43, 8.4436516e-24, 8.8141673e-43, 8.4436516e-24, 8.8141673e-43]
#include "opencv2\opencv.hpp"
#include
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
float num1 = 2;
float num2 = 4;
Mat sampleMat = (Mat_<float>(1, 2) << num1, num2);
cout << "sampleMat=" << endl << "" << sampleMat << endl;
}
执行结果:
sampleMat=
[2, 4]
#include "opencv2\opencv.hpp"
#include
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat A = Mat::zeros(5, 5, CV_8UC1);
cout << "A=" << endl << "" << A << endl;
}
执行结果:
A=
[ 0, 0, 0, 0, 0;
0, 0, 0, 0, 0;
0, 0, 0, 0, 0;
0, 0, 0, 0, 0;
0, 0, 0, 0, 0]
#include "opencv2\opencv.hpp"
#include
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat B = Mat::ones(5, 5, CV_8UC1);
cout << "B=" << endl << "" << B << endl;
}
执行结果:
B=
[ 1, 1, 1, 1, 1;
1, 1, 1, 1, 1;
1, 1, 1, 1, 1;
1, 1, 1, 1, 1;
1, 1, 1, 1, 1]
#include "opencv2\opencv.hpp"
#include
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat C = Mat::eye(5, 5, CV_8UC1);
cout << "C=" << endl << "" << C << endl;
}
执行结果:
C=
[ 1, 0, 0, 0, 0;
0, 1, 0, 0, 0;
0, 0, 1, 0, 0;
0, 0, 0, 1, 0;
0, 0, 0, 0, 1]
#include "opencv2\opencv.hpp"
#include
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat B = Mat::ones(5, 5, CV_8UC1);
Mat A = Mat::eye(5, 5, CV_8UC1);
cout << "B的第一行" << endl << "" << B.row(1) << endl;
cout << "A的第一列" << endl << "" << A.col(1) << endl;
}
执行结果:
B的第一行
[ 1, 1, 1, 1, 1]
A的第一列
[ 0;
1;
0;
0;
0]