2.2. 图像的算术运算¶
2.2.1. 目标¶
学习一些图像上的算术运算,如加法、减法、按位运算等。
你将学习以下功能: cv2.add() , cv2.addWeighted() 等。
2.2.2. 图像加法¶
你可以通过OpenCV函数 cv2.add()``将两个图像相加, 或者仅仅通过这样的numpy操作,``res = img1 + img2
。 这要求两幅图像的深度和类型应该相同,或者第二幅图像只能是标量值。
Note
OpenCV加法和Numpy加法有区别。OpenCV加法是饱和运算,Numpy加法是模运算。
例如,考虑以下示例:
>>> import cv2
>>> import numpy as np
>>>
>>> x = np.uint8([250])
>>> y = np.uint8([10])
>>> cv2.add(x,y) # 250+10 = 260 => 255
array([[255]], dtype=uint8)
>>> x+y # 250+10 = 260 % 256 = 4
array([4], dtype=uint8)
当你做两个图像的加法时,这区别会更加明显。OpenCV函数将提供更好的结果。所以最好还是使用OpenCV函数。
2.2.3. 图像混合¶
这也是图像的加法,但是给图像赋予了不同的权重,从而给人一种混合或透明的感觉。图像按以下公式进行相加:
通过在 \(0 \rightarrow 1\) 范围内改变 :math:`alpha`的取值,可以实现一个图像到另一个图像的冷转换。
在这里我将两张图像混合在一起。第一个图像的权重为0.7,第二个图像的权重为0.3。 cv2.addWeighted()
应用以下公式于图像上。
在这里 \(\gamma\) 取为零。
>>> img1 = cv2.imread('/cvdata/ml.png')
>>> img2 = cv2.imread('/cvdata/opencv_logo.png')
>>> import cv2 as cv
>>> img1 = cv.imread('/cvdata/ml.png')
>>> img2 = cv.imread('/cvdata/opencv-logo.png')
>>> img1.shape
(380, 308, 3)
>>> img2.shape
(739, 600, 3)
>>> dst = cv.addWeighted(img1,0.3,img1,0.3,0)
>>> %matplotlib inline
>>>
>>> import matplotlib.pyplot as plt
>>> plt.imshow(dst)
<matplotlib.image.AxesImage at 0x7ff98cf73748>
>>> # dst = cv2.addWeighted(img1,0.3,img2,0.3,8)
>>> # plt.imshow(dst)
>>> # cv2.imshow('dst',dst)
>>> # cv2.waitKey(0)
>>> # cv2.destroyAllWindows()
检查以下结果:
2.2.4. 按位运算¶
这包括按位“AND”、“OR”、“NOT”和“XOR”操作。它们在提取图像的任何部分(我们将在接下来的章节中看到)、定义和使用非矩形ROI等时将非常有用。下面我们将看到一个关于如何更改图像特定区域的示例。
我想把OpenCV的标志放在图片上方。如果我添加两个图像,它将改变颜色。如果我混合它,我得到一个透明的效果。但我希望它是不透明的。如果是矩形区域,我可以像上一章那样使用ROI。但是OpenCV的标志不是矩形的。因此,你可以按如下方式执行按位操作:
>>> # 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 0x7ff98cf0fbe0>
>>> cv2.imwrite('xx_a.jpg', img1)
True
>>> from IPython.display import Image
>>> Image('/cvdata/opencv-logo-white.png')
>>> # cv2.imshow('res',img1)
>>> # cv2.waitKey(0)
>>> # cv2.destroyAllWindows()
见下面的结果。左图显示了我们创建的遮罩。右图显示了最终结果。为了更好的理解,请显示上面的代码中产生的所有中间图像,特别是 img1_bg
和 img2_fg
.
2.2.5. 额外资源¶
2.2.6. 练习¶
使用
cv2.addWeighted
函数在文件夹中创建图像的幻灯片放映