• 图像的算术运算


    本次教程我们将概述图像的算数运算,众所周知,数学中有着加减乘除运算,同样的,图像也是如此,它的本质实际上就是一个矩阵,所以图像也存在着加法、减法、位运算等等算数运算。

    加法

    使用cv2.add()将两个图像相加,可以使用numpy中的矩阵加法来实现。但是在opencv中加法是饱和操作,也就是有上限值,numpy会对结果取模,综上,使用opencv的效果更好,我们来看函数实例:

    cv2.add(img1, img2)  # 进行图片的加和

    参数说明: cv2.add将两个图片进行加和,大于255的使用255计数.

    我们将使用以下两个图片作为实例:

    image.png

    image.png

    来看代码:

    import cv2
     
     img1 = cv2.imread("01.jpg")
     img2 = cv2.imread("02.jpg")
     res = cv2.add(img1,img2)
     
     cv2.imshow("res",res)
     cv2.waitKey(0)
     cv2.destroyAllWindows()

    image.png

    不难理解,第一幅图像白色部分像素部分为255,黑色部分像素为0,所以和第二幅图像加起来之后白色部分仍然是白色部分,因为加起来的值大于255时,默认取值255.

    减法

    减法运算就是两幅图像见对象像素的灰度值或彩色分量进行相减,它可以用于目标检测,需要用到函数cv2.subtract(),程序实现:

    import cv2
     
     img1 = cv2.imread("01.jpg")
     img2 = cv2.imread("02.jpg")
     res = cv2.subtract(img1,img2)
     
     cv2.imshow("res",res)
     cv2.waitKey(0)
     cv2.destroyAllWindows()

    image.png

    乘法

    图像的乘法运算就是将两幅图像对应的灰度值或彩色分量进行相乘。

    乘运算的主要作用是抑制图像的某些区域,掩膜值置为1,否则置为0。乘运算有时也被用来实现卷积或相关的运算,其相关函数为cv2.multiply()。

    以下为相关程序代码:

    import cv2
     
     img1 = cv2.imread("01.jpg")
     img2 = cv2.imread("02.jpg")
     res = cv2.multiply(img1,img2)
     
     cv2.imshow("res",res)
     cv2.waitKey(0)
     cv2.destroyAllWindows()

    image.png

    除法

    图像除运算就是两幅图像对应像素的灰度值或彩色分量进行相除。简单的出运算可以用于改变图像的灰度级。其相关函数为cv2.divide。

    以下为代码部分:

    import cv2
     
     img1 = cv2.imread("01.jpg")
     img2 = cv2.imread("02.jpg")
     res = cv2.divide(img1,img2)
     
     cv2.imshow("res",res)
     cv2.waitKey(0)
     cv2.destroyAllWindows()

    image.png

    图像融合

    它实际上本质也是一个加法运算,但是这个加法运算跟普通的并不一样,我们可以理解为是一种加权的运算。

    我们用函数来表示一个图像,前提是所有的图像尺寸是一样的,即图像矩阵的行列一样,通道数一样。

    我们用 f0(x) 和 f1(x) 来表示输入的图像,用 g(x) 来表示输出图像,α表示比例( 0≤α≤1 ,一般来说,α取0和1没有太大意义),那我们能得到如下图所示的一个公式:

    image.png

    所以图像混合就是将两个图像按照一定的比例转存到另一个图像中。

    首先需要看一下函数原型:

    cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst

    参数:

    src1 第一个输入数组。

    alpha 第一个数组元素的权重。

    src2 第二个输入数组,其大小和通道号与src1相同。

    beta 第二个数组元素的权重。

    gamma 标量加到每个和。

    dst    输出数组,其大小和通道数与输入数组相同。

    dtype 输出数组的可选深度;当两个输入数组的深度相同时,可以将dtype设置为-1,这等效于src1.depth()。

    此函数可以用以下矩阵表达式进行代替:

    dst = src1 * alpha + src2 * beta + gamma;

    注意:由参数说明可以看出,被叠加的两幅图像必须是尺寸相同、类型相同的;并且,当输出图像array的深度为CV_32S时,这个函数就不适用了,这时候就会内存溢出或者算出的结果压根不对。

    我们来看一下代码:

    import cv2
     
     img1 = cv2.imread("01.jpg")
     img = cv2.imread("02.jpg")
     h, w, _ = img1.shape
     img2 = cv2.resize(img, (w,h), interpolation=cv2.INTER_AREA)
     alpha = 0.7
     beta = 1-alpha
     gamma = 0
     img_add = cv2.addWeighted(img1, alpha, img2, beta, gamma)
     cv2.imshow('img_add',img_add)
     cv2.waitKey()
     cv2.destroyAllWindows()
    效果:

    image.png

    此函数最大的缺陷就是需要两张图片尺寸必须完全一样,所以在实验时必须要注意。

    按位运算

    我们在学习数电时想必都学过逻辑运算,OpenCV中也有相关的运算。与或非这些想必就不必再多讲了,我们可以通过代码实验来熟悉:

    与运算

    import cv2
     
     img1 = cv2.imread("01.jpg")
     img2 = cv2.imread("02.jpg")
     res = cv2.bitwise_and(img1,img2)
     cv2.imshow("res",res)
     cv2.waitKey()
     cv2.destroyAllWindows()

    image.png

    或运算:

    import cv2
     img1 = cv2.imread("01.jpg")
     img2 = cv2.imread("02.jpg")
     res = cv2.bitwise_or(img1,img2)
     cv2.imshow("res",res)
     cv2.waitKey()
     cv2.destroyAllWindows()

    image.png

    可以看到,跟加法运算基本上类似。

    非运算:

    import cv2
     
     img1 = cv2.imread("01.jpg")
     img2 = cv2.imread("02.jpg")
     res = cv2.bitwise_not(img1,img2)
     cv2.imshow("res",res)
     cv2.waitKey()
     cv2.destroyAllWindows()

    image.png

    非运算在之后的学习中是非常有帮助的,它的以用来对二值化图像进行取反,然后方便进行形态学操作。

    异或运算:

    import cv2
     
     img1 = cv2.imread("01.jpg")
     img2 = cv2.imread("02.jpg")
     res = cv2.bitwise_xor(img1,img2)
     cv2.imshow("res",res)
     cv2.waitKey()
     cv2.destroyAllWindows()

    image.png

    关于图像的所有的基本运算就介绍到这里。

    现在带大家做一个好玩的小项目,题目是:

    用OpenCV完成一个幻灯片演示一幅图转成另一幅图,并在图像之间进行平滑过渡。

    实际上,我们使用刚刚的线性加权函数就可以完成,我们只需要定义一个变量a,然后让其值小于一,变量的值依次递增。这样总体进行分析的话,第一幅图图像的加权值为a,第二幅图像的加权值为1-a,那么在一个循环里面它们会进行动态过渡,我们来看一下代码:

    import cv2 as cv
     
     img1 = cv.imread('01.jpg')
     img2 = cv.imread('02.jpg')
     l, h = img1.shape[0:2]
     img2_R = cv.resize(img2, (h, l))
     a=0
     cv.namedWindow('ppt',True)
     dst = cv.addWeighted(img1, a, img2_R, 1-a, -1)
     cv.imshow('ppt', dst)
     cv.waitKey(0)
     while a<1.0:
         dst = cv.addWeighted(img1, a, img2_R, 1-a, -1)
         cv.imshow('ppt', dst)
         cv.waitKey(100)
         a+=0.02
     
     cv.waitKey(0)
     cv.destroyAllWindows()

    image.png

    按下esc键开始幻灯片放映,由于效果为动态,此处不便展示,大家请自己实验,还是很有意思的。

  • 相关阅读:
    Mac下截图快捷键
    在Mac下显示所有文件
    Mac 下格式化U盘
    在Mac OS X系统下 用dd命令将iso镜像写入u盘
    微信公众号全局返回码说明和接口频率限制说明
    Mac Git 学习笔记
    vim编程配置方法
    解决“Xlib.h not found when building graphviz on Mac OS X 10.8”错误
    Java-Session服务器端会话技术
    Java-记住上一次访问时间案例
  • 原文地址:https://www.cnblogs.com/wuyuan2011woaini/p/15638643.html
Copyright © 2020-2023  润新知