【Emgu CV教程】2.6、基本方法之图像的加减乘除操作

读者们从小都应该学过数字的加减乘除运算,比如3+5、16 * 38等等。其实图像也是可以进行加减乘除运算的??什么,图像也可以进行加减乘除运算,why???其实原理很简单,以一张640 *360的单通道的灰度图为例,他就是一个640列360行的矩阵,当然可以和另外一个640列360行的矩阵进行加减乘除运算了。

还不明白,别着急,咱们会有详细的举例说明。这篇文章干货满满啊... ...

1、Add()加法函数

Add()函数就是将两个已知的图像相加,并输出一个新的函数。这种加法使用时,当两个像素点的像素值之和大于255时,就将结果值等于255(就是最大值了)。代码如下:

Mat dstMat = new Mat();
CvInvoke.Add(srcMat1, srcMat2, dstMat);
CvInvoke.Imshow("Add image, " + dstMat.Size.ToString(), dstMat);

其中srcMat1和srcMat2就是两个输入的原始图像,dstMat就是输出图像。使用这个函数时要注意:

  • srcMat1和srcMat2的尺寸要相同。
  • srcMat1和srcMat2的通道数要相同,或者都是三通道,或者都是单通道的灰度图。

比如下图,图片1是 黑夜.jpg,图片2是 黑猪.jpg,两个一相加,就合成了下面黑夜中母猪飞上天的照片,这感觉是不是一下就来了。【Emgu CV教程】2.6、基本方法之图像的加减乘除操作_第1张图片

再看看下面,街景.jpg+沙滩.jpg的效果。

2、AddWeighted()带权重加法 

这个函数是计算两个图像的加权和。Weighted就是权重的意思,怎么理解呢,先看官方说明:

public static void AddWeighted(
    IInputArray src1, // 输入图像1
    double alpha,  // 图像1的权重
    IInputArray src2,  // 输入图像2
    double beta, // 图像2的权重
    double gamma, // 一个加到权重总和上的标量值,干什么用的不知道,我一般都是写成 0 
    IOutputArray dst, // 输出图像
    DepthType dtype = DepthType.Default // 输出图像的可选深度,干什么用的不知道,我一般都不指明
)

使用时代码如下: 

Mat dstMat = new Mat();
CvInvoke.AddWeighted(srcMat1, 0.8, srcMat2, 0.2, 0, dstMat);
CvInvoke.Imshow("AddWeighted image, " + dstMat.Size.ToString(), dstMat);

简单的理解就是以图像1的百分比加上图像2的百分比,合成一个新图像。街景.jpg * 0.8 +沙滩.jpg * 0.2,输出结果如下:

街景.jpg * 0.2 +沙滩.jpg * 0.8,输出结果如下: 

使用时要注意两幅图片尺寸必须相同。 

3、Subtract直接相减

Subtract()的功能就是将两张图像的每个像素的值相减,并且将结果输出到新图像。官方对该函数定义如下:

public static void Subtract(
    IInputArray src1, // 输入图像1,被减数
    IInputArray src2, // 输入图像2,减数
    IOutputArray dst,  //目标图像
    IInputArray mask = null, // 掩码,属于可选参数
    DepthType dtype = DepthType.Default // 输出图像深度,可以不写
)

代码使用如下:

Mat dstMat = new Mat();
CvInvoke.Subtract(srcMat1, srcMat2, dstMat); // 相减后,小于0则自动改成0
CvInvoke.Imshow("Subtract image, " + dstMat.Size.ToString(), dstMat);

Subtract()使用时,两个点像素值相减,如果值小于0,则结果就是0。街景.jpg减去沙滩.jpg,效果如下: 

4、AbsDiff()相减后取绝对值

相比Subtract(),AbsDiff()函数再相减时,结果小于0,会取其绝对值。其函数主要作用是计算两张图片的不同之处。这个用出非常大,读者可以仔细想想。代码使用方法如下:

Mat dstMat = new Mat();
CvInvoke.AbsDiff(srcMat1, srcMat2, dstMat); // 相减后,小于0则取绝对值
CvInvoke.Imshow("AbsDiff image, " + dstMat.Size.ToString(), dstMat);

比如一张全黑图片减去沙滩.jpg,结果如下:

  • 对Subtract()函数来说,10 - 230 = 0
  • 对 AbsDiff()函数来说,10 - 230 = 220

这样好理解了吗????

5、Multipy()图像相乘

Multipy()函数的作用是将两个输入图像的对应像素点相乘,并将结果输出到新图像。官方定义如下:

public static void Multiply(
    IInputArray src1, // 输入图像1,作为被乘数
    IInputArray src2, // 输入图像2,作为乘数
    IOutputArray dst, // 输出图像
    double scale = 1.0, // 缩放因子,可以在最终结果基础上再乘以一个系数
    DepthType dtype = DepthType.Default // // 输出图像深度,可以不写
)

具体来说,对于每个像素点(x,y),输出图像的像素值为:

  • dstPoint.X= P1.X * P2.X * scale;
  • dstPoint.Y= P1.Y * P2.Y * scale;

要注意,相乘的两张照片尺寸要相同。相乘后结果最大值是255,最小值是0,代码如下:

Mat dstMat = new Mat();
CvInvoke.Multiply(srcMat1, srcMat2, dstMat, 1); // 相乘后,最大值255,最小值0
CvInvoke.Imshow("Multiply image, " + dstMat.Size.ToString(), dstMat);

街景.jpg乘以沙滩.jpg,效果如下:  

6、Multipy()图像相乘之指定通道数值放大

上面演示的是利用Multipy()函数对两张尺寸相同的照片相乘。在实际使用过程中,还有一种情况是:某张图片,希望蓝色、绿色通道保持不变,而红色通道放大5倍。这种情况下也可以用Multipy()函数来实现,代码如下:

Mat dstMat = new Mat();
Mat tempMat = new Mat(new System.Drawing.Size(srcMat1.Cols, srcMat1.Rows), DepthType.Cv8U, 3);
tempMat.SetTo(new MCvScalar(1, 1, 5));
CvInvoke.Multiply(srcMat1, tempMat, dstMat, 1); // 相乘后,最大值255,最小值0
CvInvoke.Imshow("Multiply image, " + dstMat.Size.ToString(), dstMat);

这时候就是srcMat1乘以值为(1,1,5)的Mat变量,以街景照片为例,只把红色通道放大5倍效果如下:

7、Divide()图像相除

对比Multipy()函数,Divide()函数的定义与其完全相同。在Emgu CV中,两张图片相除,必须是尺寸和类型必须相同,相除后,最大值255,最小值0,代码如下:

Mat dstMat = new Mat();
CvInvoke.Divide(srcMat1, srcMat2, dstMat, 1); // 相除后,最大值255,最小值0
CvInvoke.Imshow("Divide image, " + dstMat.Size.ToString(), dstMat);

街景.jpg除以沙滩.jpg,效果如下:   

8、Divide()图像相除之指定通道数值缩小

参考第六小节,如果是让街景.jpg的蓝色通道缩小5倍,绿色、红色通道数值不变,可以这样写:

Mat tempMat = new Mat(new System.Drawing.Size(srcMat1.Cols, srcMat1.Rows), DepthType.Cv8U, 3);
tempMat.SetTo(new MCvScalar(5, 1, 1));
Mat dstMat = new Mat();
CvInvoke.Divide(srcMat1, tempMat, dstMat, 1); // 相除后,最大值255,最小值0
CvInvoke.Imshow("Divide image, " + dstMat.Size.ToString(), dstMat);

街景.jpg 的蓝色通道缩小5倍,实际效果如下:

9、图像直接加减乘除数字

在Emgu CV中,图像还可以直接与数字进行最简单的四则运算,分别如下:

Mat dstMat = srcMat1.Clone();
dstMat += 50.00; // 加法
dstMat -= 50.00; // 加法
dstMat *= 2.00; // 乘法
dstMat /= 5.00; // 乘法

街景.jpg + 50 的效果如下: 

【Emgu CV教程】2.6、基本方法之图像的加减乘除操作_第2张图片

街景.jpg / 2.45 的效果如下: 

【Emgu CV教程】2.6、基本方法之图像的加减乘除操作_第3张图片

下一篇介绍Emgu CV中图像的按位运算方法。

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

你可能感兴趣的:(Emgu,CV使用教程,c#,图像处理,计算机视觉,Emgu,CV)