图像的算术运算
1.饱和加 cv2.add()
OpenCV中的add()
函数是饱和运算,也就是说,如果两个8位整数相加,超过了255,自动会截断成255.
>>> 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]
2. 图像混合 cv2.addWeighted()
图像混合的数学表达式如下,原理就是将两张图片按照一定的比例(透明度)进行融合,产生的图片也一般会存在一种“透明”的感觉。
在OpenCV中参数的表达与上式略有不同,有以下三个参数α、β,γ
。
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()
结果如下:
这里,我做了一个类似幻灯片淡入淡出效果的gif动图,由一张图动态过度到另一张,一定记得把颜色通道翻转一下!!! 代码如下:
def slide_view():
img1 = cv2.resize(cv2.imread('bear.jpg'), (500, 500))
img2 = cv2.imread('OpenCV-logo.jpg')
fps = 20
buff = []
for i in range(fps):
alpha = i / fps
beta = 1 - i / fps
dst = cv2.addWeighted(img1, alpha, img2, beta, 0)
cv2.imshow('dst', dst)
# 这里记得反转一下颜色通道,OpenCV中是BGR,imageio是RGB
buff.append(dst[:, :, ::-1])
cv2.waitKey(int(1000 / fps))
cv2.destroyAllWindows()
gif = imageio.mimsave('logo2bear.gif', buff, 'GIF', duration=0.1)
这里效果图是gif不太好上传,你可以自己运行一下上述代码。
3. 图像位操作
上述融合中有一个问题,就是会产生“透明”的效果,有时候我们又不想这样,而是直接把一个图片A放在图片B的上面,这时候位操作就发挥了作用,大致将一下思路(这里记待插入的前景图片为A,插入到的那个图片为B):
- 先取出图片B的ROI。
- 先将图片A灰度化(如果已经是灰度图当然就无需这步),记为grayA。
- 将grayA二值化(取一个阈值,比如说10),小于10的像素为0,其他为1,记二值化后的图片为mask,为了后续需要,将mask按位取反得到mask_inv。
- 利用
cv2.bitwise_and(roi, roi, mask=mask_inv)
将图片B的ROI区域变黑。注意:bitwise_and的运算机制如下:
- 利用
cv2.bitwise_and(imgA, imgA, mask=mask)
将图片A的前景取出。 - 把前景加到背景变黑的区域。
def bitwise_ops():
# cv2.namedWindow('123', cv2.WINDOW_NORMAL)
img = cv2.imread("man.jpg")
img_logo = cv2.imread("OpenCV-logo.jpg")
# ROI
rows, cols, channels = img_logo.shape
roi = img[0:rows, 0:cols]
# 新建一个logo的mask图片
img_logo_gray = cv2.cvtColor(img_logo, cv2.COLOR_BGR2GRAY)
cv2.imshow("123", img_logo_gray)
cv2.waitKey(0)
ret, mask = cv2.threshold(img_logo_gray, 10, 255, cv2.THRESH_BINARY)
cv2.imshow("123", mask)
cv2.waitKey(0)
mask_inv = cv2.bitwise_not(mask)
cv2.imshow("123", mask_inv)
cv2.waitKey(0)
# 先把背景的ROI区域变黑
img_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)
cv2.imshow("123", img_bg)
cv2.waitKey(0)
# 取出logo的前景
img_lg = cv2.bitwise_and(img_logo, img_logo, mask=mask)
cv2.imshow("123", img_lg)
cv2.waitKey(0)
# 把logo前景放到变黑的背景图区域
dst = cv2.add(img_bg, img_lg)
img[0:rows, 0:cols] = dst
cv2.imshow('123', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果如下: