opencv入门系列教学(六)图像上的算术运算(加法、融合、按位运算)
0.序言
这一篇博客我们将学习图像的几种算术运算,例如加法,减法,按位运算等。
1.图像加法
我们可以通过OpenCV函数
1 | cv.add() |
或仅通过numpy操作
1 | res = img1 + img2 |
res = img1 + img2 将两个图像加起来。两个图像应具有相同的深度和类型,或者第二个图像可以只是一个标量值。
注意:OpenCV加法和Numpy加法之间有区别。OpenCV加法是饱和运算,而Numpy加法是模运算。
例如,考虑以下示例:
1 2 3 4 5 6 | >>> x = np.uint8([ 250 ]) >>> y = np.uint8([ 10 ]) >>> print ( cv.add(x,y) ) # 250+10 = 260 => 255 [[ 255 ]] >>> print ( x + y ) # 250+10 = 260 % 256 = 4 [ 4 ] |
2.图像融合
这是一种更为常用的图像加法操作,但是对图像赋予不同的权重,这个操作可以用来对两幅图像或两段视频产生时间上的 画面叠化 (cross-dissolve)效果,就像在幻灯片放映和电影制作中那样,以使其具有融合或透明的感觉。根据以下等式添加图像:
cv.addWeighted()
其数学表达式为G(x) = α · img1 + (1-α)img2 ,其中 α 取值0 - 1。
下面我们将两个图像并且融合在一起。第一幅图像的权重为0.7,第二幅图像的权重为0.3。
1 2 3 4 5 6 | img1 = cv.imread( 'ml.png' ) img2 = cv.imread( 'opencv-logo.png' ) dst = cv.addWeighted(img1, 0.7 ,img2, 0.3 , 0 ) cv.imshow( 'dst' ,dst) cv.waitKey( 0 ) cv.destroyAllWindows() |
结果如下所示:
3.按位运算
按位运算包括按位 AND 、 OR 、 NOT 和 XOR 操作。它们在提取图像的任何部分(我们将在后面的章节中看到)、定义和处理非矩形 ROI 等方面非常有用。 下面我们将看到一个例子,如何改变一个图像的特定区域。
考虑下面这种情况,我想把 OpenCV 的标志放在一个图像上面。如果我添加两个图像,它会改变颜色。如果我混合它,我得到一个透明的效果。但我希望它是不透明的。如果是一个矩形区域,我可以使用 ROI,就像我们在上一章中所做的那样。但是 OpenCV 的 logo 不是长方形的。所以我们可以使用如下的按位操作来实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # 加载两张图片 img1 = cv.imread( 'messi5.jpg' ) img2 = cv.imread( 'opencv-logo-white.png' ) # 我想把logo放在左上角,所以我创建了ROI rows,cols,channels = img2.shape roi = img1[ 0 :rows, 0 :cols ] # 现在创建logo的掩码,并同时创建其相反掩码 img2gray = cv.cvtColor(img2,cv.COLOR_BGR2GRAY) ret, mask = cv.threshold(img2gray, 10 , 255 , cv.THRESH_BINARY) mask_inv = cv.bitwise_not(mask) # 现在将ROI中logo的区域涂黑 img1_bg = cv.bitwise_and(roi,roi,mask = mask_inv) # 仅从logo图像中提取logo区域 img2_fg = cv.bitwise_and(img2,img2,mask = mask) # 将logo放入ROI并修改主图像 dst = cv.add(img1_bg,img2_fg) img1[ 0 :rows, 0 :cols ] = dst cv.imshow( 'res' ,img1) cv.waitKey( 0 ) cv.destroyAllWindows() |
请看下面的结果。左图显示了我们创建的掩膜mask。右图显示最终结果。