1、Mat类型
为解决原C语言中IplImage内存管理问题,引入C++类Mat自动管理内存
Mat类由两个部分组成:
1)矩阵头matrix header(包含矩阵尺寸、存储方法、存储地址等等),矩阵头的尺寸是常数
2)一个指向存储所有像素值的矩阵(所选存储方法的不同可以是不同的维数)的指针matrix pointer,
引用计数制管理Mat对象的内存
每个Mat对象有自己的矩阵头(matrix header),但可能共享的相同图像矩阵(矩阵指针指向相同地址)
copy构造函数,只拷贝矩阵头和矩阵指针,不拷贝图像矩阵
如果要拷贝矩阵用clone或copyTo方法
//读取图像
using var lenaA = Cv2.ImRead(ImagePath.LenaColor, ImreadModes.Color);
if (lenaA.Empty()) return;
//共享图像矩阵
var lenaB = new Mat(lenaA, Range.All, Range.All);
using var lenaC = lenaA;
//获取指定区域图像
using var lenaD = new Mat(lenaA, new Rect(100, 250,370, 180));
using var lenaE = lenaA[new Range(100, 200), Range.All];
//复制图像矩阵
using var lenaF = lenaA.Clone();
using Mat lenaG = new Mat();
lenaA.CopyTo(lenaG);
//修改某个区域为绿
lenaA[new Rect(50, 100, 150, 200)] = new Mat(new Size(150, 200), MatType.CV_8UC3,Scalar.Green);
//显示所有图像
using (new Window("lenaA", lenaA))
using (new Window("lenaB", lenaB))
using (new Window("lenaC", lenaC))
using (new Window("lenaD", lenaD))
using (new Window("lenaE", lenaE))
using (new Window("lenaF", lenaF))
using (new Window("lenaG", lenaG))
{
Cv2.WaitKey();
}
显示结果如下:
可见对lenaA矩阵的修改,同时影响了lenaB、lenaC、lenaD和lenaE,
通过Clone()与CopyTo()方法的lenaF、lenaG未受影响。
2、存储方法
通过指定颜色空间和数据类型存储像素值。
常见的颜色空间:灰度空间Gray、RGB空间、HSV等等
数据类型
[typeof(byte)] = MatType.CV_8UC1,
[typeof(sbyte)] = MatType.CV_8SC1,
[typeof(short)] = MatType.CV_16SC1,
[typeof(char)] = MatType.CV_16UC1,
[typeof(ushort)] = MatType.CV_16UC1,
[typeof(int)] = MatType.CV_32SC1,
[typeof(float)] = MatType.CV_32FC1,
[typeof(double)] = MatType.CV_64FC1,
[typeof(Vec2b)] = MatType.CV_8UC2,
[typeof(Vec3b)] = MatType.CV_8UC3,
[typeof(Vec4b)] = MatType.CV_8UC4,
[typeof(Vec6b)] = MatType.CV_8UC(6),
[typeof(Vec2s)] = MatType.CV_16SC2,
[typeof(Vec3s)] = MatType.CV_16SC3,
[typeof(Vec4s)] = MatType.CV_16SC4,
[typeof(Vec6s)] = MatType.CV_16SC(6),
[typeof(Vec2w)] = MatType.CV_16UC2,
[typeof(Vec3w)] = MatType.CV_16UC3,
[typeof(Vec4w)] = MatType.CV_16UC4,
[typeof(Vec6w)] = MatType.CV_16UC(6),
[typeof(Vec2i)] = MatType.CV_32SC2,
[typeof(Vec3i)] = MatType.CV_32SC3,
[typeof(Vec4i)] = MatType.CV_32SC4,
[typeof(Vec6i)] = MatType.CV_32SC(6),
[typeof(Vec2f)] = MatType.CV_32FC2,
[typeof(Vec3f)] = MatType.CV_32FC3,
[typeof(Vec4f)] = MatType.CV_32FC4,
[typeof(Vec6f)] = MatType.CV_32FC(6),
[typeof(Vec2d)] = MatType.CV_64FC2,
[typeof(Vec3d)] = MatType.CV_64FC3,
[typeof(Vec4d)] = MatType.CV_64FC4,
[typeof(Vec6d)] = MatType.CV_64FC(6),
[typeof(Point)] = MatType.CV_32SC2,
[typeof(Point2f)] = MatType.CV_32FC2,
[typeof(Point2d)] = MatType.CV_64FC2,
[typeof(Point3i)] = MatType.CV_32SC3,
[typeof(Point3f)] = MatType.CV_32FC3,
[typeof(Point3d)] = MatType.CV_64FC3,
[typeof(Size)] = MatType.CV_32SC2,
[typeof(Size2f)] = MatType.CV_32FC2,
[typeof(Size2d)] = MatType.CV_64FC2,
[typeof(Rect)] = MatType.CV_32SC4,
[typeof(Rect2f)] = MatType.CV_32FC4,
[typeof(Rect2d)] = MatType.CV_64FC4,
[typeof(DMatch)] = MatType.CV_32FC4
MatType类型
格式:CV_[数据类型]C[通道数]
如:MatType.CV_8UC3 表示3通道8位无符号整型
MatType.CV_64FC4 表示4通道64位浮点型
3、创建Mat对象
//定义3x2,8位无符号整型3通道的矩阵
using var M = new Mat(3, 2, MatType.CV_8UC3, new Scalar(0, 0, 255));
Debug.WriteLine(M);
Debug.WriteLine("M=\n" + M.Dump());
//重新调整矩阵大小,内容随机
M.Create(4, 3, MatType.CV_8UC2);
Debug.WriteLine("after Create M=\n" + M.Dump());
//MATLAB形式的初始化方式
using var eye = (Mat)Mat.Eye(4, 4, MatType.CV_64F);
Debug.WriteLine("eye=\n" + eye.Dump());
using var ones = (Mat)Mat.Ones(new Size(2, 2), MatType.CV_32F);
Debug.WriteLine("ones=\n" + ones.Dump());
using var zeros = (Mat)Mat.Zeros(3, 3, MatType.CV_8UC1);
Debug.WriteLine("zeros=\n" + zeros.Dump());
//小矩阵赋予初始值
var C = new Mat<Double>(3, 3, new Double[] { 0, -1, 0, -1, 5, -1, 0, -1, 0 });
Debug.WriteLine("C=\n" + C.Dump());
4、格式化输出
//格式化输出
Debug.WriteLine("Default:\n" + C.Dump(FormatType.Default));
Debug.WriteLine("MATLAB:\n" + C.Dump(FormatType.MATLAB));
Debug.WriteLine("CSV:\n" + C.Dump(FormatType.CSV));
Debug.WriteLine("Python:\n" + C.Dump(FormatType.Python));
Debug.WriteLine("NumPy:\n" + C.Dump(FormatType.NumPy));
Debug.WriteLine("C:\n" + C.Dump(FormatType.C));
源码下载:LearnOpenCVSharp
参考链接: