OpenCV图像叠加时如何将目标轮廓外区域设置为透明消除黑边
解决方案
你需要为提取的目标生成对应轮廓掩码,叠加时仅将掩码覆盖的目标区域替换到背景上,即可完全消除轮廓外的黑边问题,具体修改后的代码如下:
import cv2 import numpy as np from matplotlib import pyplot as plt from skimage import io # 导入卡片和背景图 card = io.imread('https://i.ebayimg.com/thumbs/images/g/BZoAAOSwj0RfkZuD/s-l225.jpg') background = io.imread('https://www.robots.ox.ac.uk/~vgg/data/dtd/images/cracked/cracked_0049.jpg') # 检测卡片轮廓 edged=cv2.Canny(card,30,200) contours, hierarchy=cv2.findContours(edged,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) contour = [c for c in contours if c.size >=1300][0] # 裁剪卡片区域 x,y,w,h = cv2.boundingRect(contour) card_cropped = card[y:y+h, x:x+w] # 生成裁剪区域对应的轮廓掩码 mask = np.zeros(card_cropped.shape[:2], dtype=np.uint8) # 将原轮廓坐标转换为裁剪区域的相对坐标 relative_contour = contour - [x, y] cv2.fillPoly(mask, [relative_contour], 255) # 同时缩放卡片和掩码 card_cropped_resized = cv2.resize(card_cropped, (int(card_cropped.shape[1]/0.8), int(card_cropped.shape[0]/0.8))) mask_resized = cv2.resize(mask, (int(card_cropped.shape[1]/0.8), int(card_cropped.shape[0]/0.8))) # 灰度转换 card_cropped_resized_grayscale = cv2.cvtColor(card_cropped_resized, cv2.COLOR_RGB2GRAY) background_grayscale = cv2.cvtColor(background, cv2.COLOR_RGB2GRAY) h, w = card_cropped_resized_grayscale.shape[:2] hh, ww = background_grayscale.shape[:2] yoff = round(hh/4) xoff = round(ww/4) xMin = xoff yMin = yoff xMax = xoff+w yMax = yoff+h scene = background_grayscale.copy() # 仅替换掩码覆盖的目标区域,保留背景其他区域不变 scene[yMin:yMax, xMin:xMax][mask_resized > 0] = card_cropped_resized_grayscale[mask_resized > 0] plt.imshow(cv2.cvtColor(scene,cv2.COLOR_GRAY2RGB)) plt.show()
扩展适配说明
如果后续需要对目标做旋转、滤波等变换,只要对掩码做完全相同的变换操作,保证掩码和目标物体始终对齐,该方案就可以正常生效。
内容的提问来源于stack exchange,提问作者h7681
相关产品推荐
相关产品推荐

