繁体   English   中英

结合前景png图像与jpg背景

[英]Combining foreground png image with jpg background

我有以下功能:

def alphaMerge(small_foreground, background, top, left):
    
    result = background.copy()
    
    fg_b, fg_g, fg_r, fg_a = cv.split(small_foreground)
    print(fg_b, fg_g, fg_r, fg_a)

    fg_a = fg_a / 255.0

    label_rgb = cv.merge([fg_b * fg_a, fg_g * fg_a, fg_r * fg_a])

    height, width = small_foreground.shape[0], small_foreground.shape[1]
    part_of_bg = result[top:top + height, left:left + width, :]

    bg_b, bg_g, bg_r = cv.split(part_of_bg)

    part_of_bg = cv.merge([bg_b * (1 - fg_a), bg_g * (1 - fg_a), bg_r * (1 - fg_a)])

    cv.add(label_rgb, part_of_bg, part_of_bg)
    result[top:top + height, left:left + width, :] = part_of_bg
    return result

if __name__ == '__main__':
   folder_dir = r"C:\photo_datasets\products_small"
   logo = cv.imread(r"C:\Users\PiotrSnella\photo_datasets\discount.png", cv.IMREAD_UNCHANGED)
   for images in os.listdir(folder_dir):
       input_path = os.path.join(folder_dir, images)
       image_size = os.stat(input_path).st_size
       if image_size < 8388608:
           img = cv.imread(input_path, cv.IMREAD_UNCHANGED)
           height, width, channels = img.shape
           if height > 500 and width > 500:
               result = alphaMerge(logo, img, 0, 0)
               cv.imwrite(r'C:\photo_datasets\products_small_output_cv\{}.png'.format(images), result)

我想合并两张图片,其中一张带有徽标,我想将其应用于文件夹 products_small 中的完整数据集。 我收到错误part_of_bg = cv.merge([bg_b * (1 - fg_a), bg_g * (1 - fg_a), bg_r * (1 - fg_a)]) ValueError: operands could not be broadcast together with shapes (720,540) (766,827)

我尝试了其他组合选项,但仍然收到有关形状问题的错误,照片可能有问题或代码有问题?

谢谢你们的帮助:) 背景 jpg - img

标志PNG

这是在 Python/OpenCV 中执行此操作的一种方法。 我将在右侧口袋坐标 660,660 处的裤子图像上放置一个 20% 大小调整后的徽标。

  • 阅读背景图片(裤子)
  • 读取未更改的前景图像(徽标)以保留 alpha 通道
  • 将前景(徽标)的大小调整为 20%
  • 创建背景图像大小的透明图像
  • 将调整后的前景(徽标)插入透明图像所需位置
  • 从插入的、调整大小的前景图像中提取 alpha 通道
  • 从插入的、调整大小的前景图像中提取基本 BGR 通道
  • 使用 np.where() 使用 alpha 通道作为掩码来混合背景图像和基础 BGR 图像。 请注意所有图像必须具有相同的尺寸和 3 个通道
  • 保存结果

背景图像:

在此处输入图像描述

前景图片:

在此处输入图像描述

import cv2
import numpy as np

# read background image
bimg = cv2.imread('pants.jpg')
hh, ww = bimg.shape[:2]

# read foreground image
fimg = cv2.imread('flashsale.png', cv2.IMREAD_UNCHANGED)

# resize foreground image
fimg_small = cv2.resize(fimg, (0,0), fx=0.2, fy=0.2)
ht, wd = fimg_small.shape[:2]

# create transparent image
fimg_new = np.full((hh,ww,4), (0,0,0,0), dtype=np.uint8)

# insert resized image into transparent image at desired coordinates
fimg_new[660:660+ht, 660:660+wd] = fimg_small

# extract alpha channel from foreground image as mask and make 3 channels
alpha = fimg_new[:,:,3]
alpha = cv2.merge([alpha,alpha,alpha])

# extract bgr channels from foreground image
base = fimg_new[:,:,0:3]

# blend the two images using the alpha channel as controlling mask
result = np.where(alpha==(0,0,0), bimg, base)

# save result
cv2.imwrite("pants_flashsale.png", result)

# show result
cv2.imshow("RESULT", result)
cv2.waitKey(0)

结果:

在此处输入图像描述

这只需要一些乘法和减法。

您的叠加层具有实际的 alpha 通道,而不仅仅是布尔掩码。 你应该使用它。 它使边缘看起来比硬布尔掩码更好。

我发现您的叠加层存在一个问题:它没有任何“阴影”来使白色文本与潜在的白色背景形成对比。

当您调整 RGBA 数据大小时,这不是微不足道的。 您最好首先以所需的分辨率从矢量图形程序中导出图形。 事后调整大小需要操作以确保部分透明像素(既不是 100% 不透明也不是 100% 透明)被正确计算,因此覆盖图像的完全透明区域的未定义“背景”不会混合到那些部分透明像素中。

base = cv.imread("U3hRd.jpg")
overlay = cv.imread("OBxGQ.png", cv.IMREAD_UNCHANGED)
(bheight, bwidth) = base.shape[:2]
(oheight, owidth) = overlay.shape[:2]
print("base:", bheight, bwidth)
print("overlay:", oheight, owidth)
# place overlay in center
#ox = (bwidth - owidth) // 2
#oy = (bheight - oheight) // 2
# place overlay in top left
ox = 0
oy = 0
overlay_color = overlay[:,:,:3]
overlay_alpha = overlay[:,:,3] * np.float32(1/255)
# "unsqueeze" (insert 1-sized color dimension) so numpy broadcasting works
overlay_alpha = np.expand_dims(overlay_alpha, axis=2)

composite = base.copy()
base_roi = base[oy:oy+oheight, ox:ox+owidth]
composite_roi = composite[oy:oy+oheight, ox:ox+owidth]
composite_roi[:,:] = overlay_color * overlay_alpha + base_roi * (1 - overlay_alpha)

合成的

这就是你想要的左上角。 请注意,白色前景上的徽标在 pant.jpg 的背景上不起作用。

相比之下只有 17 行代码

import cv2
import numpy as np

img1 = cv2.imread('pant.jpg')
overlay_img1 = np.ones(img1.shape,np.uint8)*255
img2 = cv2.imread('logo3.png')
rows,cols,channels = img2.shape
overlay_img1[0:rows, 0:cols ] = img2
img2gray = cv2.cvtColor(overlay_img1,cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(img2gray,220,255,cv2.THRESH_BINARY_INV)
mask_inv = cv2.bitwise_not(mask)
temp1 = cv2.bitwise_and(img1,img1,mask = mask_inv)
temp2 = cv2.bitwise_and(overlay_img1,overlay_img1, mask = mask)
result = cv2.add(temp1,temp2)
cv2.imshow("Result",result)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

在此处输入图像描述

徽标调整大小(320x296):

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM