还是要从Mat类型的变量创建开始。Emgu CV里面最重要的一个类就是Mat,因为视频处理、图像分析的每一步都离不开对图像元素的操作。Mat类就是图像的一个容器,包含了采用什么样的颜色空间、通道数量、尺寸大小等各种信息。

Mat的操作最基础,很重要、很重要、很重要

首先咱们从创建各种样式的Mat类开始讲起。

1、创建一个黑色的图像

简单的两句代码,就可以在你WPF的Image控件上显示一张黑色图片,宽640,高360,代码如下:

            Mat m = Mat.Zeros(360, 640, DepthType.Cv8U, 3);
            Image1.Source = m.ToBitmapSource();

官方对Mat.Zero()函数定义如下:

       public static Mat Zeros(int rows, int cols, DepthType type, int channels)

  • rows,行数,也就是图片高度。
  • cols,列数,也就是图片宽度。
  • type,图片深度,也就是每一个图片的位数。格式是Cv+深度值+符号类型。深度值是8163264,也就就是存储的二进制位数。符号类型有三个值:S,U,F。S:signed int 有符号整形;U:unsigned int 无符号整形;F:float 单精度浮点型。
  • channels,通道数量。

上面两行代码的意思就是创建一个宽640,高360,8位无符号整型的3通道图像,图像每个点的像素值都是0,是不是很拗口???补充知识:

  • 8位整型是指计算机编程中的一种数据类型,它占用存储空间的大小为8个比特(bit),无符号8位整型取值就是0 到 255。如果是DepthType.Cv8S,就是8位有符号整型,取值是-128 到 127。
  • ToBitmapSource()方法是来自于Emgu CV的一个官方文件,可以将Mat类型变量显示在WPF的Image控件上,下载路径如下:

emgucv/Emgu.CV.NativeImage/BitmapSourceExtension.cs at master · emgucv/emgucv · GitHub

2、创建一个全部值都为1的图像

刚才利用Emgu CV内部的Zero()函数,创建了一个全为0的黑色图片。接下来我们创建一个值全为1的3通道图片,代码如下:

            Mat m = Mat.Ones(360, 640, DepthType.Cv8U, 3);
            Image1.Source = m.ToBitmapSource();

Ones()的函数定义和Zeros()一样,运行结果如下图:

VS2022的调试结果显示,只有0通道的值是1,1通道和2通道的值都是0,为什么???? 因为OpenCV里面的Ones()函数就只适用于单通道Mat变量。对于多个通道的Mat变量,Ones()只将第一个通道设置为1。

如果我想创建一个纯白的图片,也就是3个通道的值都是255,那该怎么办,别着急,请往下看。

3、创建一个白色的图像

代码如下:

            // Mat m = new Mat(360, 640, DepthType.Cv8U, 3);
            Mat m = new Mat(new System.Drawing.Size(640, 360), DepthType.Cv8U, 3);
            m.SetTo(new MCvScalar(255, 255, 255));
            Image1.Source = m.ToBitmapSource();

基本思路还是先定义一个空白的Mat变量,这里有两种方式,要注意这两种方式宽、高的顺序不能颠倒。然后再给Mat变量赋值,用到SetTo()函数。这里要注意颜色值的写法:new MCvScalar(Blue, Green, Red) ,因此,要是创建红色图片,就是

       m.SetTo(new MCvScalar(0, 0, 255));

       创建蓝色图片是 m.SetTo(new MCvScalar(255, 0, 0));

       创建绿色图片是 m.SetTo(new MCvScalar(0, 255, 0));

4、Image控件显示从本地文件加载的图片

代码非常简单,如下:

            Image<Bgr, Byte> image = new Image<Bgr, byte>(AppDomain.CurrentDomain.BaseDirectory + "Images/Demo/lena.jpg");
            Image1.Source = image.ToBitmapSource();

先创建Emgu CV的Image类变量,然后按照实际路径读取图片文件,再赋值给WPF的Image控件就可以。 

5、CvInvoke.Imread从本地文件加载图片

官方对Imread()函数的作用描述是:

Loads an image from the specified file and returns the pointer to the loaded image. Currently the following file formats are supported: Windows bitmaps - BMP, DIB; JPEG files - JPEG, JPG, JPE; Portable Network Graphics - PNG; Portable image format - PBM, PGM, PPM; Sun rasters - SR, RAS; TIFF files - TIFF, TIF; OpenEXR HDR images - EXR; JPEG 2000 images - jp2.

用大白话来讲,就是Imread()可以读取本地计算机上的图片文件,并转换成Mat变量。图片文件的格式可以是.bmp、.jpg、.jpeg、.png等等。基本上就是常用的图片都可以读出来。其定义如下:

public static Mat Imread(
    string filename, // 图片文件路径
    ImreadModes loadType = ImreadModes.Color // 加载图像的类型
)

oadType默认值是ImreadModes.Color,代表彩色图像 。还有一个常用的是ImreadModes.Grayscale,在加载时把图像换成单通道的灰度图。

用起来很简单,代码如下:

Mat m = CvInvoke.Imread(AppDomain.CurrentDomain.BaseDirectory + "Images\\Demo\\lena.jpg");

默认值可以不写,加载完lena.jpg后,Mat变量是BGR格式的颜色空间,Cv8U的图像深度。如果logType = ImreadModes.Grayscale,那Mat变量就变成单通道的、Cv8U的图像深度的图片。请看下面的演示:

6、CvInvoke.Imshow弹窗显示图片 

刚才利用的是WPF的Image控件显示Mat变量或者Image变量,如果您希望用弹窗的方式,请参考以下代码:

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

       官方对Imshow()函数定义如下 

       public static void Imshow(string name, IInputArray image)

  • name,弹窗的名称。
  • image,需要显示的变量,Mat类型,Image类型都可以。

在使用Imshow()之前,代码其实是先执行了DestroyAllWindows()函数,它的作用是关闭所有已弹出的窗口,避免弹窗重复或累积。WPF执行效果如下:

总结

Mat类型变量的操作基本上是看一眼就会,没有一点复杂的。下面的文章会一步步介绍Emgu CV里面的各种图像处理函数,敬请期待。

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

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐