4.2. 10 图像上的算术运算

目标

  • 学习图像上的算术运算,加法,减法,位运算等。

  • 我们将要学习的函数与有:cv2.add(),cv2.addWeighted() 等。

4.2.1. 10.1 图像加法

你可以使用函数 cv2.add() 将两幅图像进行加法运算,当然也可以直接使用 numpy,res=img1+img。两幅图像的大小,类型必须一致,或者第二个图像可以使一个简单的标量值。

注意:OpenCV 中的加法与 Numpy 的加法是有所不同的。OpenCV 的加法是一种饱和操作,而 Numpy 的加法是一种模操作。

例如下面的两个例子:

>>> import numpy as np
>>> import cv2
>>> import  matplotlib.pyplot as plt
>>>
>>> x = np.uint8([250])
>>>
>>> y = np.uint8([10])
>>>
>>> print (cv2.add(x,y)) # 250+10 = 260 => 255[[255]]
>>>
>>> print (x+y) # 250+10 = 260 % 256 = 4[4]
>>>
>>> #这种差别在你对两幅图像进行加法时会更加明显。
>>> #OpenCV 的结果会更好一点。所以我们尽量使用 OpenCV 中的函数。
>>>
[[255]]
[4]

4.2.2. 10.2 图像混合

这其实也是加法,但是不同的是两幅图像的权重不同,这就会给人一种混合或者透明的感觉。图像混合的计算公式如下:

g (x) = (1−α)f 0 (x) + αf 1 (x)

通过修改 α 的值(0 → 1),可以实现非常酷的混合。

现在我们把两幅图混合在一起。第一幅图的权重是 0.7,第二幅图的权重是 0.3。函数 cv2.addWeighted() 可以按下面的公式对图片进行混合操作。

dst = α · img1 + β · img2 + γ

这里 γ 的取值为 0。

img1 = cv2.imread(‘img/1000000000000028000000344EA57DF07F938B22.jpg.png’)

img2 = cv2.imread(‘img/10000000000000700000009632A77B08D34C4DC1.png’)

dst = cv2.addWeighted(img1,0.7,img2,0.3,0)

cv2.imshow(‘dst’,dst)

cv2.waitKey(0)

cv2.destroyAllWindows()

dst = cv2.addWeighted(img1,0.7,img2,0.3,0)

下面就是结果:#这个运行有问题

error: C::raw-latex:`\projects`:raw-latex:`\opencv`-python:raw-latex:opencv:raw-latex:`\modules`:raw-latex:`\core`:raw-latex:`\src`:raw-latex:`\arithm`.cpp:659:

error: (-209) The operation is neither ‘array op array’ (where arrays have

the same size and the same number of channels), nor ‘array op scalar’,

nor ‘scalar op array’ in function cv::arithm_op

4.2.3. 10.3 按位运算

这里包括的按位操作有:AND,OR,NOT,XOR 等。当我们提取图像的一部分,选择非矩形 ROI 时这些操作会很有用(下一章你就会明白)。下面的例子就是教给我们如何改变一幅图的特定区域。我想把 OpenCV 的标志放到另一幅图像上。如果我使用加法,颜色会改变,如果使用混合,会得到透明效果,但是我不想要透明。如果他是矩形我可以象上一章那样使用 ROI。但是他不是矩形。但是我们可以通过下面的按位运算实现:

>>> # Load two images
>>> >>>
>>> # img1 = cv.imread('messi5.jpg')
>>> # img2 = cv.imread('opencv-logo-white.png')
>>> >>>
>>> img1 = cv2.imread('/cvdata/messi5.jpg')
>>> img2 = cv2.imread('/cvdata/opencv-logo-white.png')
>>> >>>
>>> >>>
>>> # I want to put logo on top-left corner, So I create a ROI
>>> rows,cols,channels = img2.shape
>>> roi = img1[0:rows, 0:cols ]
>>> >>>
>>> # Now create a mask of logo and create its inverse mask also
>>> img2gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
>>> ret, mask = cv2.threshold(img2gray, 10, 255, cv2.THRESH_BINARY)
>>> mask_inv = cv2.bitwise_not(mask)
>>> >>>
>>> # Now black-out the area of logo in ROI
>>> img1_bg = cv2.bitwise_and(roi,roi,mask = mask_inv)
>>> >>>
>>> # Take only region of logo from logo image.
>>> img2_fg = cv2.bitwise_and(img2,img2,mask = mask)
>>> >>>
>>> # Put logo in ROI and modify the main image
>>> dst = cv2.add(img1_bg,img2_fg)
>>> img1[0:rows, 0:cols ] = dst
>>> plt.imshow(img1)
<matplotlib.image.AxesImage at 0x7f8145addc90>
_images/sec2_algbra_5_1.png

结果如下。左面的图像是我们创建的掩码。右边的是最终结果。为了帮助大家理解我把上面程序的中间结果也显示了出来,特别是 img1_bg 和 img2_fg。

练习

  1. 创建一个幻灯片用来演示一幅图如何平滑的转换成另一幅图(使用函数cv2.addWeighted)