在 Python 中将较小的图像叠加到较大的图像
Overlay smaller image to larger image in Python
我知道这个问题已经被问过好几次了,例如 this one,但我的问题是我需要用较大的 PNG 图像覆盖较小的 PNG 图像,其中 两者 图像需要在输出中保持透明度。
例如,较小的图像如下:
...大图是这样的:
(上图只有1个像素填充白色,透明度90%)
使用上一个问题(overlay a smaller image on a larger image python OpenCv)中给出的代码示例,较大的背景图像将是黑色的。
def overlay_image_alpha(img, img_overlay, x, y, alpha_mask):
"""Overlay `img_overlay` onto `img` at (x, y) and blend using `alpha_mask`.
`alpha_mask` must have same HxW as `img_overlay` and values in range [0, 1].
"""
# Image ranges
y1, y2 = max(0, y), min(img.shape[0], y + img_overlay.shape[0])
x1, x2 = max(0, x), min(img.shape[1], x + img_overlay.shape[1])
# Overlay ranges
y1o, y2o = max(0, -y), min(img_overlay.shape[0], img.shape[0] - y)
x1o, x2o = max(0, -x), min(img_overlay.shape[1], img.shape[1] - x)
# Exit if nothing to do
if y1 >= y2 or x1 >= x2 or y1o >= y2o or x1o >= x2o:
return
# Blend overlay within the determined ranges
img_crop = img[y1:y2, x1:x2]
img_overlay_crop = img_overlay[y1o:y2o, x1o:x2o]
alpha = alpha_mask[y1o:y2o, x1o:x2o, np.newaxis]
alpha_inv = 1.0 - alpha
img_crop[:] = alpha * img_overlay_crop + alpha_inv * img_crop
# Prepare inputs
x, y = 50, 0
img = np.array(Image.open("template.png"))
img_overlay_rgba = np.array(Image.open("../foo.png"))
# Perform blending
alpha_mask = img_overlay_rgba[:, :, 3] / 255.0
img_result = img[:, :, :3].copy()
img_overlay = img_overlay_rgba[:, :, :3]
overlay_image_alpha(img_result, img_overlay, x, y, alpha_mask)
# Save result
Image.fromarray(img_result).save("img_result.png")
结果:
我想要的结果是保持大图的透明度。
我可以知道怎么做吗?
这实际上是正确的输出。完全透明的图像(如您的模板图像)在表示黑色的空白区域的像素值为 0。如果您要使用 semi-transparent 模板(像素值大于 0,即使它们稍微透明)。你应该看到这个:
答案二:
您的输出图像是 24 位的。 (这意味着您在保存之前摆脱了 alpha 通道)。我查看了您的代码并看到了第 34 和 35 行;
img_result = img[:, :, :3].copy()
img_overlay = img_overlay_rgba[:, :, :3]
您正在将 RGB 图像发送到 overlay_image_alpha
函数。将其更改为;
img_result = img.copy()
img_overlay = img_overlay_rgba
保留 Alpha 通道信息。
新输出:
在 Photoshop 上:
我知道这个问题已经被问过好几次了,例如 this one,但我的问题是我需要用较大的 PNG 图像覆盖较小的 PNG 图像,其中 两者 图像需要在输出中保持透明度。
例如,较小的图像如下:
使用上一个问题(overlay a smaller image on a larger image python OpenCv)中给出的代码示例,较大的背景图像将是黑色的。
def overlay_image_alpha(img, img_overlay, x, y, alpha_mask):
"""Overlay `img_overlay` onto `img` at (x, y) and blend using `alpha_mask`.
`alpha_mask` must have same HxW as `img_overlay` and values in range [0, 1].
"""
# Image ranges
y1, y2 = max(0, y), min(img.shape[0], y + img_overlay.shape[0])
x1, x2 = max(0, x), min(img.shape[1], x + img_overlay.shape[1])
# Overlay ranges
y1o, y2o = max(0, -y), min(img_overlay.shape[0], img.shape[0] - y)
x1o, x2o = max(0, -x), min(img_overlay.shape[1], img.shape[1] - x)
# Exit if nothing to do
if y1 >= y2 or x1 >= x2 or y1o >= y2o or x1o >= x2o:
return
# Blend overlay within the determined ranges
img_crop = img[y1:y2, x1:x2]
img_overlay_crop = img_overlay[y1o:y2o, x1o:x2o]
alpha = alpha_mask[y1o:y2o, x1o:x2o, np.newaxis]
alpha_inv = 1.0 - alpha
img_crop[:] = alpha * img_overlay_crop + alpha_inv * img_crop
# Prepare inputs
x, y = 50, 0
img = np.array(Image.open("template.png"))
img_overlay_rgba = np.array(Image.open("../foo.png"))
# Perform blending
alpha_mask = img_overlay_rgba[:, :, 3] / 255.0
img_result = img[:, :, :3].copy()
img_overlay = img_overlay_rgba[:, :, :3]
overlay_image_alpha(img_result, img_overlay, x, y, alpha_mask)
# Save result
Image.fromarray(img_result).save("img_result.png")
结果:
我想要的结果是保持大图的透明度。
我可以知道怎么做吗?
这实际上是正确的输出。完全透明的图像(如您的模板图像)在表示黑色的空白区域的像素值为 0。如果您要使用 semi-transparent 模板(像素值大于 0,即使它们稍微透明)。你应该看到这个:
答案二:
您的输出图像是 24 位的。 (这意味着您在保存之前摆脱了 alpha 通道)。我查看了您的代码并看到了第 34 和 35 行;
img_result = img[:, :, :3].copy()
img_overlay = img_overlay_rgba[:, :, :3]
您正在将 RGB 图像发送到 overlay_image_alpha
函数。将其更改为;
img_result = img.copy()
img_overlay = img_overlay_rgba
保留 Alpha 通道信息。
新输出:
在 Photoshop 上: