如何在opencv中合并一张RGBA和一张RGB图像
How to merge one RGBA and one RGB images in opencv
我有两张图片。在一幅图像中,通过在 RGBA
图像格式中编辑通道 A
将白色像素设置为透明(或无色)。假设这张图片名称是image_rgba.png
,另一张图片是image.jpg
。现在,我想使用以下 python 代码
将 image_rgba.png
图像放在 image.jpg
的特定位置
import cv2
import numpy as np
import matplotlib.pyplot as plt
image = cv2.imread('image.jpg')
label = cv2.imread('image_rgba.png')
label = cv2.cvtColor(label, cv2.COLOR_BGR2RGBA)
new_image = image.copy()
new_image = cv2.cvtColor(new_image, cv2.COLOR_BGR2RGBA)
new_image[200:290, 300:384, :] = label
当我写这个图像时,image_rgba.png
的边缘是无色的,在输出图像中被设置为白色(下图中绿色框的白色边缘)。
我不希望显示绿色框标签的白色边缘,而是显示该像素中的背景图像。我找到了 similar 问题,但它并不能帮助我解决问题。如果有人能帮助我,我将不胜感激。
以下是您的操作方法。我不是 OpenCV 专家,所以可能有更简单的方法。代码中的注释解释了它的作用。总体思路是:
- 从 PNG 中提取 alpha 通道
- 提取一块大小相同的背景
- Alpha 混合这些
- 将结果放回后台
import cv2
def alphaMerge(small_foreground, background, top, left):
"""
Puts a small BGRA picture in front of a larger BGR background.
:param small_foreground: The overlay image. Must have 4 channels.
:param background: The background. Must have 3 channels.
:param top: Y position where to put the overlay.
:param left: X position where to put the overlay.
:return: a copy of the background with the overlay added.
"""
result = background.copy()
# From everything I read so far, it seems we need the alpha channel separately
# so let's split the overlay image into its individual channels
fg_b, fg_g, fg_r, fg_a = cv2.split(small_foreground)
# Make the range 0...1 instead of 0...255
fg_a = fg_a / 255.0
# Multiply the RGB channels with the alpha channel
label_rgb = cv2.merge([fg_b * fg_a, fg_g * fg_a, fg_r * fg_a])
# Work on a part of the background only
height, width = small_foreground.shape[0], small_foreground.shape[1]
part_of_bg = result[top:top + height, left:left + width, :]
# Same procedure as before: split the individual channels
bg_b, bg_g, bg_r = cv2.split(part_of_bg)
# Merge them back with opposite of the alpha channel
part_of_bg = cv2.merge([bg_b * (1 - fg_a), bg_g * (1 - fg_a), bg_r * (1 - fg_a)])
# Add the label and the part of the background
cv2.add(label_rgb, part_of_bg, part_of_bg)
# Replace a part of the background
result[top:top + height, left:left + width, :] = part_of_bg
return result
background = cv2.imread('image.jpg')
# Read the image "unchanged" to get the alpha channel as well
label = cv2.imread('image_rgba.png', cv2.IMREAD_UNCHANGED)
result = alphaMerge(label, background, 100, 200)
cv2.imshow("result", result)
cv2.waitKey()
我测试了以下背景:
而这个前景:
结果如 Python 代码所示:
我有两张图片。在一幅图像中,通过在 RGBA
图像格式中编辑通道 A
将白色像素设置为透明(或无色)。假设这张图片名称是image_rgba.png
,另一张图片是image.jpg
。现在,我想使用以下 python 代码
image_rgba.png
图像放在 image.jpg
的特定位置
import cv2
import numpy as np
import matplotlib.pyplot as plt
image = cv2.imread('image.jpg')
label = cv2.imread('image_rgba.png')
label = cv2.cvtColor(label, cv2.COLOR_BGR2RGBA)
new_image = image.copy()
new_image = cv2.cvtColor(new_image, cv2.COLOR_BGR2RGBA)
new_image[200:290, 300:384, :] = label
当我写这个图像时,image_rgba.png
的边缘是无色的,在输出图像中被设置为白色(下图中绿色框的白色边缘)。
我不希望显示绿色框标签的白色边缘,而是显示该像素中的背景图像。我找到了 similar 问题,但它并不能帮助我解决问题。如果有人能帮助我,我将不胜感激。
以下是您的操作方法。我不是 OpenCV 专家,所以可能有更简单的方法。代码中的注释解释了它的作用。总体思路是:
- 从 PNG 中提取 alpha 通道
- 提取一块大小相同的背景
- Alpha 混合这些
- 将结果放回后台
import cv2
def alphaMerge(small_foreground, background, top, left):
"""
Puts a small BGRA picture in front of a larger BGR background.
:param small_foreground: The overlay image. Must have 4 channels.
:param background: The background. Must have 3 channels.
:param top: Y position where to put the overlay.
:param left: X position where to put the overlay.
:return: a copy of the background with the overlay added.
"""
result = background.copy()
# From everything I read so far, it seems we need the alpha channel separately
# so let's split the overlay image into its individual channels
fg_b, fg_g, fg_r, fg_a = cv2.split(small_foreground)
# Make the range 0...1 instead of 0...255
fg_a = fg_a / 255.0
# Multiply the RGB channels with the alpha channel
label_rgb = cv2.merge([fg_b * fg_a, fg_g * fg_a, fg_r * fg_a])
# Work on a part of the background only
height, width = small_foreground.shape[0], small_foreground.shape[1]
part_of_bg = result[top:top + height, left:left + width, :]
# Same procedure as before: split the individual channels
bg_b, bg_g, bg_r = cv2.split(part_of_bg)
# Merge them back with opposite of the alpha channel
part_of_bg = cv2.merge([bg_b * (1 - fg_a), bg_g * (1 - fg_a), bg_r * (1 - fg_a)])
# Add the label and the part of the background
cv2.add(label_rgb, part_of_bg, part_of_bg)
# Replace a part of the background
result[top:top + height, left:left + width, :] = part_of_bg
return result
background = cv2.imread('image.jpg')
# Read the image "unchanged" to get the alpha channel as well
label = cv2.imread('image_rgba.png', cv2.IMREAD_UNCHANGED)
result = alphaMerge(label, background, 100, 200)
cv2.imshow("result", result)
cv2.waitKey()
我测试了以下背景:
而这个前景:
结果如 Python 代码所示: