本文共总结了5种方式:
一. cv2.add
二. cv2.addWeighted
三. 按位运算(bitwise_not、bitwise_and、bitwise_or)
四. cv2.seamlessClone
五. 像素遍历
cv2.add(img1, img2) # 进行图片的加和
使用cv2.add()将两个图像相加,可以使用numpy中的矩阵加法来实现。但是在opencv中加法是饱和操作,也就是有上限值,numpy会对结果取模。
cv2.add将两个图片进行加和,大于255的使用255计数
需要合成的两个图片 大小必须一致
import numpy as np
import cv2
x = np.uint8([250])
y = np.uint8([10])
print(cv2.add(x, y)) # 250+10 = 260 => 255
print(x + y) # 250+10 = 260 % 256 = 4
当图片为二值化图片(只有0和255),两者结果是一样的(用numpy的方式更简便一些)。
import cv2
img1=cv2.imread(r'D:\360MoveData\Users\Administrator\Desktop\wo\zly.jpg')
img2=cv2.imread(r'D:\360MoveData\Users\Administrator\Desktop\wo\yx.jpg')
res = cv2.add(img1, img2)
# 保存此方式可保持中文路径
cv2.imencode('.jpg', res)[1].tofile(r'D:\360MoveData\Users\Administrator\Desktop\wo\add_img.jpg')
cv2.imshow('input_image', res)
cv2.waitKey(0)
cv2.addWeighted(img1, 0.6, img2, 0.4, 0) 表示将两个图片进行重叠操作,可以自行设置两张图片的权重
重叠后的像素表示: img10.6 + img20.4 + 0 ,0表示重叠的偏置项
i
import cv2
img1=cv2.imread(r'D:\360MoveData\Users\Administrator\Desktop\wo\zly.jpg')
img2=cv2.imread(r'D:\360MoveData\Users\Administrator\Desktop\wo\yx.jpg')
res = cv2.addWeighted(img1, 0.6, img2, 0.4, 0)
# 保存
cv2.imencode('.jpg', res)[1].tofile(r'D:\360MoveData\Users\Administrator\Desktop\wo\add_img.jpg')
cv2.imshow('input_image', res)
cv2.waitKey(0)
原图:img1 img2 依旧用上面的风景图片和张靓颖图片
合成效果:
问题:不管是cv2.add还是cv2.addWeighted在合成图片时都会改变原图片的样式,那么如何将一个图放到另一个图上去,不改变颜色,亮度等。那么位操作来了。。
首先来了解一下掩膜(mask)的概念:掩膜是用一副二值化图片对另外一幅图片进行局部的遮挡,看下图就一目了然了(借用网上图片):
cv2.add()用来叠加两幅图片,cv2.addWeighted()也是叠加两幅图片,但两幅图片的权重不一样
cv2.bitwise_and(), cv2.bitwise_not(), cv2.bitwise_or(), cv2.bitwise_xor()分别执行按位与/或/非/异或运算。掩膜就是用来对图片进行全局或局部的遮挡
import cv2
img1=cv2.imread(r'D:\360MoveData\Users\Administrator\Desktop\wo\zly.jpg')
img2=cv2.imread(r'D:\360MoveData\Users\Administrator\Desktop\wo\yx.jpg')
# 此处可以控制合成的位置(哪些位置进行改变)
# 这里两幅图一样大,不起作用
rows,cols,channels = img2.shape
roi = img1[0:rows, 0:cols ]
img2gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY) # 将图片灰度化
cv2.imshow('img2gray',img2gray)
# 灰度图 把 大于175(不感兴趣)的值改为 255 ,也就是变为白色
ret, mask = cv2.threshold(img2gray, 175, 255, cv2.THRESH_BINARY)
cv2.imshow('mask',mask)
# 把mask取反,兴趣区域-->白色 无兴趣区域-->黑色
mask_not = cv2.bitwise_not(mask)
cv2.imshow('mask_not',mask_not)
# 对张靓颖图片和mask进行取与操作,作用相当于把mask中为黑色的部分,
# 在张靓颖图片中也附黑,白色部分不变。
img1_bg = cv2.bitwise_and(roi,roi,mask = mask)
cv2.imshow('img1_bg',img1_bg)
# 对风景图片和mask_not进行取与操作,作用相当于把mask中为黑色的部分,
# 在风景图片中也附黑,白色部分不变。
img2_fg = cv2.bitwise_and(img2,img2,mask = mask_not)
cv2.imshow('img2_fg',img2_fg)
# 相加即可
dst = cv2.add(img1_bg,img2_fg)
img1[0:rows, 0:cols ] = dst
# 保存
cv2.imencode('.jpg', dst)[1].tofile(r'D:\360MoveData\Users\Administrator\Desktop\wo\add_img.jpg')
cv2.imshow('dst', dst)
cv2.waitKey(0)
无缝合成(Seamless Cloning)是opencv3的新特性。
利用这个新特性,我们可以从一个图像复制对象,将其粘贴到另一个图像中,同时使组合看起来无缝和自然。
import numpy as np
import cv2
# 把src 复制到 dst图片中去。dst为目标图片 src为 源图像
src=cv2.imread(r'D:\360MoveData\Users\Administrator\Desktop\wo\zly.jpg')
dst=cv2.imread(r'D:\360MoveData\Users\Administrator\Desktop\wo\yx.jpg')
cv2.imshow('dst', dst)
# 修改150的值,可以有不同的效果,这是为 一般可以设置为全白,也就是255
src_mask = 255 * np.ones(src.shape, src.dtype)
# 位置 此处图片不能偏移出去,大小控制好
center = (200,295)
# Clone seamlessly. 提供了两种方式 cv2.MIXED_CLONE 和 cv2.NORMAL_CLONE 结果不同的
output = cv2.seamlessClone(src, dst, src_mask, center, cv2.MIXED_CLONE)
# 保存
cv2.imencode('.jpg', output)[1].tofile(r'D:\360MoveData\Users\Administrator\Desktop\wo\add_img.jpg')
cv2.imshow('output', output)
cv2.waitKey(0)
像素遍历,就是指通过把所有的像素点遍历一遍,判断rgb的值,然后通过判断结果进行相对应操作。实际效果涉密不方便展示,就不放 图片了。
import cv2
img = cv2.imread(r'D:\360MoveData\Users\Administrator\Desktop\22\label457.png')
img1 = cv2.imread(r'D:\360MoveData\Users\Administrator\Desktop\33\19_19.tif')
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
h = img.shape[0]
w = img.shape[1]
for i in range(w):
for j in range(h):
if img[j][i][0] != 0 or img[j][i][1] != 0 or img[j][i][2] != 0:
img1[j][i] = (0, 0, 128)
cv2.imwrite(r'D:\360MoveData\Users\Administrator\Desktop\11\4.jpg', img1)
实际效果涉密不方便展示,就不放 图片了。