最近在学opencv, 初学者。
里面有提到如何将两张图合成一张图, 提供了两个方法
一种是直接通过图片透明度权重进行融合
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()
合成效果如下, 可以看到两张图片都损失了清晰度, 效果很不理想
同时还提供了另外一种方法, 就是通过掩码的方式, 对两张图片分别提取各自重叠的部分, 然后再进行按位叠加, 这样, 两张图片就完美的结合在一起了。
img1 = cv.imread('messi5.jpeg')
img1 = np.repeat(img1, repeats=2, axis=0) #图片高度不够, 我自行扩充了
# 扩充后shape为(560, 450, 3)
img2 = cv.imread('opencv-logo.png') #shape为(433, 328, 3)
# 因为要把img2叠加到img1上, 所以要保障img1的面积大于img2
rows,cols,channels = img2.shape
roi = img1[0:rows, 0:cols ]
# 现在创建logo的掩码,并同时创建其相反掩码
img2gray = cv.cvtColor(img2,cv.COLOR_BGR2GRAY)
img2gray[img2gray==0] = 255
ret, mask = cv.threshold(img2gray, 50, 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
plt.subplot(231), plt.title("mask. img1"), plt.axis('off')
plt.imshow(cv.cvtColor(mask, cv.COLOR_GRAY2RGB)) # 显示 img1(RGB)
plt.subplot(232), plt.title("mask_inv. img2"), plt.axis('off')
plt.imshow(cv.cvtColor(mask_inv, cv.COLOR_GRAY2RGB)) # 显示 img2(RGB)
plt.subplot(233), plt.title("img1_bg. img3"), plt.axis('off')
plt.imshow(cv.cvtColor(img1_bg, cv.COLOR_BGR2RGB)) # 显示 img2(RGB)
plt.subplot(234), plt.title("img2_fg. img4"), plt.axis('off')
plt.imshow(cv.cvtColor(img2_fg, cv.COLOR_BGR2RGB)) # 显示 img2(RGB)
plt.subplot(235), plt.title("dst. img5"), plt.axis('off')
plt.imshow(cv.cvtColor(dst, cv.COLOR_BGR2RGB)) # 显示 img2(RGB)
plt.subplot(236), plt.title("img1. img6"), plt.axis('off')
plt.imshow(cv.cvtColor(img1, cv.COLOR_BGR2RGB)) # 显示 img2(RGB)
plt.show()
原图如下:
最终叠加的效果如下参照img1.img6
可以看到logo完美叠加到了另一张图片上。
这里着重说一下mask, 了解ps的都知道蒙版, 通过蒙版, 能够把图层的部分留住, 其他部分都剔除, 而此处的mask就是黑色的部分会被留下, 白色的部分会被擦除, 所以只要设计一个取反的mask(mask.img1和mask_inv.img2), 分别对两张图片按位与, 之后再叠加起来, 就成了两张互相契合的图片img1_bg.img3和img2_fg.img5, 然后将两张图片再叠加起来, 就完成了最终的合成图dst.img5。所以里面的最关键的部分在于对掩码的理解,以及掩码阈值的设计。