本节目标:
- 学会一些图像的算术操作,如加、减、位操作等
- 将会使用函数
cv2.add() cv2.addWeighted()
原文地址:Arithmetic Operations on Images
图像加法
可以使用Opencv的函数cv2.add()
或者numpy的简单算术操作实现两幅图的相加.res = img1 + img2
,两幅图必须类型和通道数相同,或者第二幅图可以为一个标量(相当于第一幅图整体值得上下移动)。
Opencv得加法和Numpy的加法有所不同,Opencv加法会自动检测值域是否越界,进行修正,而numpy是一个模数的操作(即会发生溢出,如数据类型是int8,那么 250 + 10 = 260 % 256 = 4)。
比如,看下面的例子
>>> 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函数会得到一个更好的结果(相比numpy的加法)。所以最好使用OpenCV的函数。
图像融合
还是图像的加法,但是赋予图像不同的权重,所以能明显感觉到图像的融合或者透明度。公式如下
通过从0到1变化参数alpha,可以控制图像融合的透明度过渡。
下面我们将两幅图融合到一起,第一张图权重为0.7,第二张为0.3,用cv2.addWeighted()
函数实现,公式如下
这里第三个参数gamma为0
img1 = cv2.imread('ml.png')
img2 = cv2.imread('opencv_logo.jpg')
dst = cv2.addWeighted(img1,0.7,img2,0.3,0)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果如下
位运算
位运算包括与或非和异或(相异为真,相同为假)操作。在提取图像的部分的时候位运算极为有用,比如对于非矩形的ROI区域选择。下面我们会给出一个例子展示如何修改图像的某个具体的区域。
我像将OpenCV的logo融合到一副图像上,如果简单的将两幅图相加,他会改变颜色,如果是融合的化,会有透明度影响。但是我想要一个不透明的效果。如果它是一个矩形区域,可以使用ROI(上一节内容),但是OpenCV的logo不是一个矩形,所以你可以像下面一样使用位运算实现。
# Load two images
img1 = cv2.imread('messi5.jpg')
img2 = cv2.imread('opencv_logo.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
cv2.imshow('res',img1)
cv2.waitKey(0)
cv2.destroyAllWindows()
如下图所示,左边的图是我们创建的掩码(mask),右边的是最后的结果。为了加深理解,可以展示上述代码的所有中间结果,尤其是img1_bg
和img2_fg
。