Python+OpenCV怎么实现多张png透明图像叠加在jpg图像上?? 就和这张图片一样 多张png叠加在jpg图片上
import cv2
import numpy as np
def gen_png_to_jpg(png_path,jpg_path,png_size=(),jpg_size=(),png_in_jpg_p=(0,0),out_path="",show=True):
png_image = cv2.imread(png_path, cv2.IMREAD_UNCHANGED)
jpg_image = cv2.imread(jpg_path, cv2.IMREAD_UNCHANGED)
if jpg_size:
jpg_image=cv2.resize(jpg_image,jpg_size)
a_mask = png_image[:, :, -1]
x, y = np.where(a_mask == 255)
x_min = min(x)
x_max = max(x)
y_min = min(y)
y_max = max(y)
# 裁剪到最小
new_png = png_image[x_min:x_max, y_min:y_max, :3].copy()
new_mask = png_image[x_min:x_max, y_min:y_max, -1:].copy()
if png_size:
new_png=cv2.resize(new_png, png_size)
new_mask=cv2.resize(new_mask,png_size)
new_mask=new_mask.reshape(new_mask.shape[0],new_mask.shape[1],1)
re_mask = (~new_mask == 255)
if png_in_jpg_p[0]+re_mask.shape[1]<jpg_image.shape[1] or png_in_jpg_p[1]+re_mask.shape[0]<jpg_image.shape[0]:
jpg_image[png_in_jpg_p[1]:re_mask.shape[0]+png_in_jpg_p[1], png_in_jpg_p[0]:re_mask.shape[1]+png_in_jpg_p[0], :] *= re_mask
jpg_image[png_in_jpg_p[1]:re_mask.shape[0]+png_in_jpg_p[1], png_in_jpg_p[0]:re_mask.shape[1]+png_in_jpg_p[0], :] += new_png
if out_path:
cv2.imwrite(out_path,jpg_image)
if show:
cv2.imshow("",jpg_image )
cv2.waitKey()
def gen_png_to_jpg_p(png_path,jpg_path,png_size=(),jpg_size=(),png_in_jpg_p=(0,0),out_path="",show=True):
png_image = cv2.imread(png_path, cv2.IMREAD_UNCHANGED)
if type(jpg_path)==type(""):
jpg_image = cv2.imread(jpg_path, cv2.IMREAD_UNCHANGED)
else:
jpg_image=jpg_path
if jpg_size:
jpg_image=cv2.resize(jpg_image,jpg_size)
a_mask = png_image[:, :, -1]
x, y = np.where(a_mask == 255)
x_min = min(x)
x_max = max(x)
y_min = min(y)
y_max = max(y)
# 裁剪到最小
new_png = png_image[x_min:x_max, y_min:y_max, :3].copy()
new_mask = png_image[x_min:x_max, y_min:y_max, -1:].copy()
if png_size:
new_png=cv2.resize(new_png, png_size)
new_mask=cv2.resize(new_mask,png_size)
new_mask=new_mask.reshape(new_mask.shape[0],new_mask.shape[1],1)
re_mask = (~new_mask == 255)
if png_in_jpg_p[0]+re_mask.shape[1]<jpg_image.shape[1] or png_in_jpg_p[1]+re_mask.shape[0]<jpg_image.shape[0]:
jpg_image[png_in_jpg_p[1]:re_mask.shape[0]+png_in_jpg_p[1], png_in_jpg_p[0]:re_mask.shape[1]+png_in_jpg_p[0], :] *= re_mask
jpg_image[png_in_jpg_p[1]:re_mask.shape[0]+png_in_jpg_p[1], png_in_jpg_p[0]:re_mask.shape[1]+png_in_jpg_p[0], :] += new_png
if out_path:
cv2.imwrite(out_path,jpg_image)
if show:
cv2.imshow("",jpg_image )
cv2.waitKey()
return jpg_image
def gen_pngs_to_jpg(jpg_path,png_path_list,png_size_list=None,jpg_size=(),png_in_jpg_p_list=None,out_path="",show=True):
for i,png_path in enumerate(png_path_list):
jpg_path=gen_png_to_jpg_p(png_path=png_path,jpg_path=jpg_path,jpg_size=jpg_size,png_size=png_size_list[i], png_in_jpg_p=png_in_jpg_p_list[i],out_path="",show=False)
if show:
cv2.imshow("",jpg_path)
cv2.waitKeyEx()
if out_path:
cv2.imwrite(out_path,jpg_path)
if __name__ == '__main__':
# gen_png_to_jpg("457788647446175.png","837709647446145.jpg",png_in_jpg_p=(1,50))
gen_pngs_to_jpg("837709647446145.jpg",png_path_list=["457788647446175.png","457788647446175.png"],jpg_size=(),png_size_list=[(100,50),(100,50)],png_in_jpg_p_list=[(1,50),(103,50)])
import cv2
def cv_show(neme, img):
cv2.imshow(neme, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
def Set_up_the(path, x, y):
"""
图像路径,
想放置的背景图的位置,左上角坐标
:return:
"""
image1 = cv2.imread(path)
im1 = image1 == 0
# 设置"图像1"放置在"背景图"中的位置:
# 设置x y偏移多少
_x, _y = x, y
# 设置的参数:左上角、右下角坐标 x1 y1 x2 y2
x1, y1, x2, y2 = 0 + _x, 0 + _y, image1.shape[1] + _x, image1.shape[0] + _y
return x1, y1, x2, y2, im1, image1
def add(image1, image3, im, x1, y1, x2, y2):
# 掩膜
image1_ = image3[int(y1):int(y2), int(x1):int(x2)] * im
# 图像相加
image1_1 = cv2.add(image1_, image1)
# 赋给原图
image3[int(y1):int(y2), int(x1):int(x2)] = image1_1
return image3
# 图像1
x1, y1, x2, y2, im1, image1 = Set_up_the("1.png", 100, 100)
# 图像2
x10, y10, x20, y20, im10, image2 = Set_up_the("2.png", 500, 100)
# 背景图
image3 = cv2.imread("3.jpg")
img = add(image1, image3, im1, x1, y1, x2, y2)
cv_show('neme', img)
img = add(image2, img, im10, x10, y10, x20, y20)
cv_show('neme', img)
你试一下这一版:
import cv2
import numpy as np
def add_alpha_channel(img):
""" 为jpg图像添加alpha通道 """
b_channel, g_channel, r_channel = cv2.split(img) # 剥离jpg图像通道
alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255 # 创建Alpha通道
img_new = cv2.merge((b_channel, g_channel, r_channel, alpha_channel)) # 融合通道
return img_new
def merge_img(jpg_img, png_img, png2_img,y1, y2, x1, x2, y3, y4, x3, x4):
""" 将png透明图像与jpg图像叠加
y1,y2,x1,x2为叠加位置坐标值
"""
# 判断jpg图像是否已经为4通道
if jpg_img.shape[2] == 3:
jpg_img = add_alpha_channel(jpg_img)
'''
当叠加图像时,可能因为叠加位置设置不当,导致png图像的边界超过背景jpg图像,而程序报错
这里设定一系列叠加位置的限制,可以满足png图像超出jpg图像范围时,依然可以正常叠加
'''
yy1 = 0
yy2 = png_img.shape[0]
xx1 = 0
xx2 = png_img.shape[1]
if x1 < 0:
xx1 = -x1
x1 = 0
if y1 < 0:
yy1 = - y1
y1 = 0
if x2 > jpg_img.shape[1]:
xx2 = png_img.shape[1] - (x2 - jpg_img.shape[1])
x2 = jpg_img.shape[1]
if y2 > jpg_img.shape[0]:
yy2 = png_img.shape[0] - (y2 - jpg_img.shape[0])
y2 = jpg_img.shape[0]
# 获取要覆盖图像的alpha值,将像素值除以255,使值保持在0-1之间
alpha_png = png_img[yy1:yy2,xx1:xx2,3] / 255.0
alpha_jpg = 1 - alpha_png
png2_yy1 = 0
png2_yy2 = png_img.shape[0]
png2_xx1 = 0
png2_xx2 = png_img.shape[1]
if x3 < 0:
png2_xx1 = -x3
x3 = 0
if y3 < 0:
png2_yy1 = - y3
y3 = 0
if x4 > jpg_img.shape[1]:
png2_xx2 = png_img.shape[1] - (x4 - jpg_img.shape[1])
x4 = jpg_img.shape[1]
if y4 > jpg_img.shape[0]:
png2_yy2 = png_img.shape[0] - (y4 - jpg_img.shape[0])
y4 = jpg_img.shape[0]
# 获取要覆盖图像的alpha值,将像素值除以255,使值保持在0-1之间
png2_alpha_png = png2_img[png2_yy1:png2_yy2,png2_xx1:png2_xx2,3] / 255.0
png2_alpha_jpg = 1 - png2_alpha_png
# 开始叠加
for c in range(0,3):
jpg1_img[y1:y2, x1:x2, c] = ((alpha_jpg*jpg_img[y1:y2,x1:x2,c]) + (alpha_png*png_img[yy1:yy2,xx1:xx2,c]))
jpg_img[y3:y4, x3:x4, c] = ((png2_alpha_jpg*jpg1_img[y1:y2,x1:x2,c]) + (png2_alpha_png*png2_img[yy1:yy2,xx1:xx2,c]))
return jpg_img
if __name__ == '__main__':
# 定义图像路径
img_jpg_path = '3.jpg' # 读者可自行修改文件路径
img_png_path = '1.png' # 读者可自行修改文件路径
img2_png_path = '2.png'
# 读取图像
img_jpg = cv2.imread(img_jpg_path, cv2.IMREAD_UNCHANGED)
img_png = cv2.imread(img_png_path, cv2.IMREAD_UNCHANGED)
img2_png = cv2.imread(img2_png_path, cv2.IMREAD_UNCHANGED)
# 设置叠加位置坐标
#图一
x1 = 560
y1 = 180
x2 = x1 + img_png.shape[1]
y2 = y1 + img_png.shape[0]
#图二
x3 = 100
y3 = 100
x4 = x3 + img2_png.shape[1]
y4 = y3 + img2_png.shape[0]
# 开始叠加
res_img = merge_img(jpg_img, png_img, png2_img,y1, y2, x1, x2,y3, y4, x3, x4)
# 显示结果图像
cv2.imshow('result', res_img)
# 保存结果图像,读者可自行修改文件路径
cv2.imwrite('imgs/res.jpg', res_img)
# 定义程序退出方式:鼠标点击显示图像的窗口后,按ESC键即可退出程序
if cv2.waitKey(0) & 0xFF == 27:
cv2.destroyAllWindows()
若是没什么问题请点击采纳
可以结合之前用PS修图时的多层图叠加,就是多图层叠加顺序,然后去实现叠加功能。
图片合并,这里面涉及到图层的设计排版
上面的代码好像没有一个可以跑通的。。。
import cv2
import numpy as np
def add_alpha_channel(img):
""" 为jpg图像添加alpha通道 """
b_channel, g_channel, r_channel = cv2.split(img) # 剥离jpg图像通道
alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255 # 创建Alpha通道
img_new = cv2.merge((b_channel, g_channel, r_channel, alpha_channel)) # 融合通道
return img_new
def merge_img(jpg_img, png_img, y1, y2, x1, x2):
""" 将png透明图像与jpg图像叠加
y1,y2,x1,x2为叠加位置坐标值
"""
# 判断jpg图像是否已经为4通道
if jpg_img.shape[2] == 3:
jpg_img = add_alpha_channel(jpg_img)
'''
当叠加图像时,可能因为叠加位置设置不当,导致png图像的边界超过背景jpg图像,而程序报错
这里设定一系列叠加位置的限制,可以满足png图像超出jpg图像范围时,依然可以正常叠加
'''
yy1 = 0
yy2 = png_img.shape[0]
xx1 = 0
xx2 = png_img.shape[1]
if x1 < 0:
xx1 = -x1
x1 = 0
if y1 < 0:
yy1 = - y1
y1 = 0
if x2 > jpg_img.shape[1]:
xx2 = png_img.shape[1] - (x2 - jpg_img.shape[1])
x2 = jpg_img.shape[1]
if y2 > jpg_img.shape[0]:
yy2 = png_img.shape[0] - (y2 - jpg_img.shape[0])
y2 = jpg_img.shape[0]
# 获取要覆盖图像的alpha值,将像素值除以255,使值保持在0-1之间
alpha_png = png_img[yy1:yy2,xx1:xx2,3] / 255.0
alpha_jpg = 1 - alpha_png
# 开始叠加
for c in range(0,3):
jpg_img[y1:y2, x1:x2, c] = ((alpha_jpg*jpg_img[y1:y2,x1:x2,c]) + (alpha_png*png_img[yy1:yy2,xx1:xx2,c]))
return jpg_img
if __name__ == '__main__':
# 定义图像路径
img_jpg_path = 'imgs/0.jpg' # 读者可自行修改文件路径
img_png_path = 'imgs/0.png' # 读者可自行修改文件路径
# 读取图像
img_jpg = cv2.imread(img_jpg_path, cv2.IMREAD_UNCHANGED)
img_png = cv2.imread(img_png_path, cv2.IMREAD_UNCHANGED)
# 设置叠加位置坐标
x1 = 560
y1 = 180
x2 = x1 + img_png.shape[1]
y2 = y1 + img_png.shape[0]
# 开始叠加
res_img = merge_img(img_jpg, img_png, y1, y2, x1, x2)
# 显示结果图像
cv2.imshow('result', res_img)
# 保存结果图像,读者可自行修改文件路径
cv2.imwrite('imgs/res.jpg', res_img)
# 定义程序退出方式:鼠标点击显示图像的窗口后,按ESC键即可退出程序
if cv2.waitKey(0) & 0xFF == 27:
cv2.destroyAllWindows()
加一个for就行了
import cv2
import numpy as np
def add_alpha_channel(img):
""" 为jpg图像添加alpha通道 """
b_channel, g_channel, r_channel = cv2.split(img) # 剥离jpg图像通道
alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255 # 创建Alpha通道
img_new = cv2.merge((b_channel, g_channel, r_channel, alpha_channel)) # 融合通道
return img_new
def merge_img(jpg_img, png_img, y1, y2, x1, x2):
""" 将png透明图像与jpg图像叠加
y1,y2,x1,x2为叠加位置坐标值
"""
# 判断jpg图像是否已经为4通道
if jpg_img.shape[2] == 3:
jpg_img = add_alpha_channel(jpg_img)
'''
当叠加图像时,可能因为叠加位置设置不当,导致png图像的边界超过背景jpg图像,而程序报错
这里设定一系列叠加位置的限制,可以满足png图像超出jpg图像范围时,依然可以正常叠加
'''
yy1 = 0
yy2 = png_img.shape[0]
xx1 = 0
xx2 = png_img.shape[1]
if x1 < 0:
xx1 = -x1
x1 = 0
if y1 < 0:
yy1 = - y1
y1 = 0
if x2 > jpg_img.shape[1]:
xx2 = png_img.shape[1] - (x2 - jpg_img.shape[1])
x2 = jpg_img.shape[1]
if y2 > jpg_img.shape[0]:
yy2 = png_img.shape[0] - (y2 - jpg_img.shape[0])
y2 = jpg_img.shape[0]
# 获取要覆盖图像的alpha值,将像素值除以255,使值保持在0-1之间
alpha_png = png_img[yy1:yy2,xx1:xx2,3] / 255.0
alpha_jpg = 1 - alpha_png
# 开始叠加
for c in range(0,3):
jpg_img[y1:y2, x1:x2, c] = ((alpha_jpg*jpg_img[y1:y2,x1:x2,c]) + (alpha_png*png_img[yy1:yy2,xx1:xx2,c]))
return jpg_img
if __name__ == '__main__':
# 定义图像路径
pnglist = ["xxx.png","xxx"]#这里填所有的png路径
for i in pnglist:
img_jpg_path = 'imgs/0.jpg' # 读者可自行修改文件路径
img_png_path = i
# 读取图像
img_jpg = cv2.imread(img_jpg_path, cv2.IMREAD_UNCHANGED)
img_png = cv2.imread(img_png_path, cv2.IMREAD_UNCHANGED)
# 设置叠加位置坐标
x1 = 560
y1 = 180
x2 = x1 + img_png.shape[1]
y2 = y1 + img_png.shape[0]
# 开始叠加
res_img = merge_img(img_jpg, img_png, y1, y2, x1, x2)
# 显示结果图像
cv2.imshow('result', res_img)
# 保存结果图像,读者可自行修改文件路径
cv2.imwrite('imgs/res.jpg', res_img)
# 定义程序退出方式:鼠标点击显示图像的窗口后,按ESC键即可退出程序
if cv2.waitKey(0) & 0xFF == 27:
cv2.destroyAllWindows()
你是不是顺序错了?先粉的,后蓝的,最后是鞋
按顺序一张一张叠加就好,先是背景,再是最下层的,再一张一张往上叠加就可以实现多张png的透明叠加。
import cv2
def cv_show(neme, img):
cv2.imshow(neme, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
def Set_up_the(path, x, y):
"""
图像路径,
想放置的背景图的位置,左上角坐标
:return:
"""
image1 = cv2.imread(path)
im1 = image1 == 0
# 设置"图像1"放置在"背景图"中的位置:
# 设置x y偏移多少
_x, _y = x, y
# 设置的参数:左上角、右下角坐标 x1 y1 x2 y2
x1, y1, x2, y2 = 0 + _x, 0 + _y, image1.shape[1] + _x, image1.shape[0] + _y
return x1, y1, x2, y2, im1, image1
def add(image1, image3, im, x1, y1, x2, y2):
# 掩膜
image1_ = image3[int(y1):int(y2), int(x1):int(x2)] * im
# 图像相加
image1_1 = cv2.add(image1_, image1)
# 赋给原图
image3[int(y1):int(y2), int(x1):int(x2)] = image1_1
return image3
# 图像1
x1, y1, x2, y2, im1, image1 = Set_up_the("1.png", 100, 100)
# 图像2
x10, y10, x20, y20, im10, image2 = Set_up_the("2.png", 500, 100)
# 背景图
image3 = cv2.imread("3.jpg")
img = add(image1, image3, im1, x1, y1, x2, y2)
cv_show('neme', img)
img = add(image2, img, im10, x10, y10, x20, y20)
cv_show('neme', img)
排一下图层顺序