【Emgu CV教程】2.2、基本方法之图像容器Mat的常用成员函数

Emgu CV的Mat类有许多成员函数,我们可以利用这些成员函数实现Mat类对象的基本操作,下面就列举几个常用的成员函数,并做一些简单的演示。

1、Cols、Rows函数

Cols函数用于获取Mat元素的列数,也就是宽度。Rows函数用于获取Mat元素的行数,也就是高度。WPF里面的用法如下:

Image<Bgr, Byte> image = new Image<Bgr, byte>(AppDomain.CurrentDomain.BaseDirectory + "Images/Demo/lena.jpg");
Mat srcMat = image.Mat;
int width = srcMat.Cols;
int height = srcMat.Rows;
System.Windows.MessageBox.Show("当前图片宽度是:" + width + ",高度是:" + height, GlobalVariables.MessageBoxCaptionRemind);

代码运行效果如下:

在实际使用中,

                int width = srcMat.Cols;
                int height = srcMat.Rows;

还可以写成

                int width = srcMat.Width;
                int height = srcMat.Height; 

2、Size()函数

Size()函数可以同时返回Mat元素的宽度、高度,从它的名字就可以看出来。使用方式如下:

Image<Bgr, Byte> image = new Image<Bgr, byte>(AppDomain.CurrentDomain.BaseDirectory + "Images/Demo/lena.jpg");
Mat srcMat = image.Mat;
int width = srcMat.Size.Width;
int height = srcMat.Size.Height;
System.Windows.MessageBox.Show("Size()函数直接返回:" + srcMat.Size.ToString() + "\r\nlena.jpg宽度是:" + width + ",高度是:" + height, GlobalVariables.MessageBoxCaptionRemind);

代码运行效果如下:

在实际使用中,直接用image.Size.ToString() 也可以。

3、Dims()函数

矩阵的维度,一般图片都是长乘以宽的矩阵,就是二维。使用方式如下:

Image<Bgr, Byte> image = new Image<Bgr, byte>(AppDomain.CurrentDomain.BaseDirectory + "Images/Demo/lena.jpg");
srcMat = img.Mat;                
int dim = srcMat.Dims;
System.Windows.MessageBox.Show("图片是:" + dim + "维", GlobalVariables.MessageBoxCaptionRemind);

代码运行效果如下: 

4、NumberOfChannels()函数 

NumberOfChannels()函数的功能是返回图像的通道数,使用方式如下:

int channels = srcMat.NumberOfChannels;

注意,彩色图片的 NumberOfChannels值为3,灰度图的NumberOfChannels值为1。实际使用中可以利用这个来判断传入的图片是彩图 or 灰度图?

5、深拷贝的CopyTo()函数 

CopyTo()函数是从mat1复制数据到mat2,复制完成后,mat1和mat2的值完全相同,但是占用的内存地址不同,是两个不同的变量。这时候修改mat1,mat2的值不会改变,这就是深拷贝。使用方式如下:

Image<Bgr, Byte> image = new Image<Bgr, byte>(AppDomain.CurrentDomain.BaseDirectory + "Images/Demo/lena.jpg");
srcMat = img.Mat;
CvInvoke.DestroyAllWindows();
Mat m = new Mat();
srcMat.CopyTo(m);
CvInvoke.Imshow("CopyTo new Mat", m);

6、深拷贝的Clone()函数 

Clone()函数也是从mat1复制数据到mat2,复制完成后,mat1和mat2的值完全相同,但是占用的内存地址不同,是两个不同的变量。这时候修改mat1,mat2的值不会改变,和CopyTo()函数使用效果相同。使用方式如下:

Mat newMat = srcMat.Clone();

7、浅拷贝

先上代码看效果,如下:

Mat m1 = new Mat(new System.Drawing.Size(640, 360), Emgu.CV.CvEnum.DepthType.Cv8U, 3); // 图片宽度是640,高度是360,3个通道
m1.SetTo(new MCvScalar(0, 255, 0)); // BGR颜色空间,原始图像是纯绿色
CvInvoke.Imshow("Source image", m1);

Mat m2 = m1;
m2.SetTo(new MCvScalar(255, 0, 0)); // BGR颜色空间,目标图像改成纯蓝色
CvInvoke.Imshow("Destination image", m2);
CvInvoke.Imshow("Source image", m1);

创建的原始图像m1应该是纯绿色,让 m2=m1,然后将m2赋值为纯蓝色,再分别显示m2和m1,结果如下:

看到了,原始图像m1也变成了纯蓝色。这就是浅拷贝。总结如下:

  • 深拷贝:分配新内存的同时拷贝数据,当被赋值的容器被修改时,原始容器数据不会改变。
  • 浅拷贝:仅拷贝数据,当被赋值容器修改时,原始容器数据也会做同样改变。

程序开发时,特别要注意深拷贝、浅拷贝的使用,否则处理过程会出现严重错误。

8、Split()和Merge()函数

Split()函数是用于将一个多通道的图像分离成多个单通道图像的函数,Merge()用于将多个单通道图像合并成一个多通道图像。比如可以将BRG颜色空间的图像分解成蓝色通道、绿色通道、红色通道。假如我们有这样一张图片,

运行以下代码:

Image<Bgr, Byte> image = new Image<Bgr, byte>(AppDomain.CurrentDomain.BaseDirectory + "Images/Demo/BGR.jpg");
srcMat = img.Mat;
CvInvoke.DestroyAllWindows();
VectorOfMat channels = new VectorOfMat();
CvInvoke.Split(srcMat, channels);

CvInvoke.Imshow("Blue channel", channels[0]);
CvInvoke.Imshow("Green channel", channels[1]);
CvInvoke.Imshow("Red channel", channels[2]);

结果如下所示:

 

弹出的四个窗口,从左到右分别是蓝色通道、绿色通道、红色通道,和三个合并后的新图像,仔细想想,为什么是这种样式???

9、GetData()函数

GetData()函数将Mat变量转成数组,以彩色的lena.jpg为例,执行以下代码:

Image<Bgr, Byte> image = new Image<Bgr, byte>(AppDomain.CurrentDomain.BaseDirectory + "Images/Demo/lena.jpg");
srcMat = image.Mat;
byte[,,] arrayMat = (byte[,,])srcMat.GetData();

执行完结果如下:

仔细想想, GetData()函数有什么巨大的作用???一个图片变成了int[高度,宽度,通道数]这种规格的数组,是不是就可以获得任意一点,并且是任意一个通道的值。

小提示:后期的代码演示,很多都是以lena.jpg作为原始图像。lena.jpg已经成为图像处理领域使用最多的标准图片,包括各种学术研究、期刊论文、会议演讲都常常使用它。广大网友可以搜一搜lena.jpg的来龙去脉,给你一个大大的惊喜^_^

总结

这一篇里面的函数及其使用方法不复杂,读者只需要在VS中跑一遍基本上就掌握了,记住,要多跑代码。

原创不易,请勿抄袭。共同进步,相互学习。 

  • 28
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值