Pon*_*ono 8 python opencv numpy
我想向已经加载的半透明 PNG 添加一个填充纯色的半透明矩形。这是我正在使用的示例输入图像:
该图像加载了一个标准cv2.IMREAD_UNCHANGED标志,以便完美地保留 alpha 通道。该输入图像存储在image变量中。
这是我到目前为止的代码:
# get image dimensions
imgHeight, imgWidth = image.shape[:2]
# create empty overlay layer with 4 channels
overlay = np.zeros((imgHeight, imgWidth, 4), dtype = "uint8")
# draw semi-transparent red rectangle
overlay[200:300, 0:imgWidth] = (0, 0, 255, 200)
# extract alpha channel from overlay
alpha = cv2.split(overlay)[3]
# compute mask
mask = (np.multiply(alpha, 1.0 / 255))[:, :, np.newaxis]
# blend input image and overlay
output = cv2.convertScaleAbs(overlay * mask + image * (1 - mask))
Run Code Online (Sandbox Code Playgroud)
这是我得到的结果:
乍一看还可以接受。我们的输入图像中间有一个半透明的矩形。但是,经过仔细检查,我们可以观察到混合 alpha 通道(用箭头标记)时的奇怪行为:
似乎 alpha 根本没有混合,这导致原始图像像素仅完全不透明或完全透明。
也许我将透明 PNG 与半透明形状混合的方法远非理想。作为旁注,我确实尝试了该cv2.addWeighted方法,但结果更糟。
我希望解决方案仅限于 OpenCV 和/或 Numpy。任何帮助将不胜感激。
正如 unlut 指出的那样,这确实是重复的。以防万一有人偶然发现,Mark Setchell 的回答非常有效:
# get image dimensions
imgHeight, imgWidth = image.shape[:2]
# create empty overlay layer with 4 channels
overlay = np.zeros((imgHeight, imgWidth, 4), dtype = "uint8")
# draw semi-transparent red rectangle
overlay[200:300, 0:imgWidth] = (0, 0, 255, 200)
# Extract the RGB channels
srcRGB = image[...,:3]
dstRGB = overlay[...,:3]
# Extract the alpha channels and normalise to range 0..1
srcA = image[...,3]/255.0
dstA = overlay[...,3]/255.0
# Work out resultant alpha channel
outA = srcA + dstA*(1-srcA)
# Work out resultant RGB
outRGB = (srcRGB*srcA[...,np.newaxis] + dstRGB*dstA[...,np.newaxis]*(1-srcA[...,np.newaxis])) / outA[...,np.newaxis]
# Merge RGB and alpha (scaled back up to 0..255) back into single image
outRGBA = np.dstack((outRGB,outA*255)).astype(np.uint8)
plt.imshow(outRGBA)
Run Code Online (Sandbox Code Playgroud)