zoukankan      html  css  js  c++  java
  • 图像的算术运算

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

    加法

    使用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键开始幻灯片放映,由于效果为动态,此处不便展示,大家请自己实验,还是很有意思的。

  • 相关阅读:
    Android开发 使用 adb logcat 显示 Android 日志
    【嵌入式开发】向开发板中烧写Linux系统-型号S3C6410
    C语言 结构体相关 函数 指针 数组
    C语言 命令行参数 函数指针 gdb调试
    C语言 指针数组 多维数组
    Ubuntu 基础操作 基础命令 热键 man手册使用 关机 重启等命令使用
    C语言 内存分配 地址 指针 数组 参数 实例解析
    CRT 环境变量注意事项
    hadoop 输出文件 key val 分隔符
    com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Too many connections
  • 原文地址:https://www.cnblogs.com/wuyuan2011woaini/p/15638643.html
Copyright © 2011-2022 走看看