这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » OpenVINO生态社区 » 【原创】OpenCV+Python之图像的算术运算(十一)

共1条 1/1 1 跳转至

【原创】OpenCV+Python之图像的算术运算(十一)

高工
2020-06-26 10:40:11     打赏

图像的算术运算

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

加法

使用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 ,一般来说,α取01没有太大意义),那我们能得到如下图所示的一个公式:

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


对计算机视觉感兴趣?这个社区推荐给你~

>>点击了解OpenVINO生态开发社区



共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]