Python+OpenCV实现png透明图像叠加在jpg图像上

您所在的位置:网站首页 银镶玉的寓意和象征 Python+OpenCV实现png透明图像叠加在jpg图像上

Python+OpenCV实现png透明图像叠加在jpg图像上

2024-07-08 23:01:16| 来源: 网络整理| 查看: 265

【问题发现】本人在图像处理项目过程中,经常需要将一幅jpg图像叠加到另一幅背景jpg图像上,来实现一些特定的需求。例如我们经常在抖音中看到一些视频特效的叠加效果,猫耳朵等等特效在背景人脸图像上的叠加。我们利用Python+OpenCV的方式可以很简单的实现jpg图像之间的叠加,但实际项目中更多需要png透明图像在jpg图像上叠加。这种情况下,仍然适用传统的jpg叠加方式,就会出现原本透明的png图像,叠加后直接变为不透明的jpg图像,达不到我们想要的效果。本篇将主要讲解如何利用Python+OpenCV来实现png透明图像叠加到jpg图像上的方法。

 

 

 

【解决方案】

1. 如何正常读取4通道的png图像为了解决上述问题,首先我们要弄清楚jpg图像和png图像的区别。我们利用Python+OpenCV方式读取的jpg图像为BGR三通道图像,每一个通道代表了一个色彩描述。而png图像则是四通道图像,除了BGR通道外,还有一个A通道,即Alpha通道,描述了图像的透明程度。但需要注意的是:OpenCV提供的图像读取函数cv2.imread(),在默认情况下读取png图像会自动忽略Alpha通道,即png图像直接变为jpg图像。因此,在读入png图像时,我们需要特别注意。

import cv2 img_path = 'imgs/demo.png' # 设置透明png图像路径 #img_bgr0 = cv2.imread(img_path, cv2.IMREAD_COLOR) # 默认读取BGR彩色图像,忽略Alpha通道 #img_bgr1 = cv2.imread(img_path) # 默认读取方式,结果同上 #img_gray = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE) # 读入灰度图像 img_png = cv2.imread(img_path, cv2.IMREAD_UNCHANGED) # 正常读入图像,并保留其通道数不变,png图像为4通道,jpg图像为3通道

 

 

2. 为jpg图像增加Alpha通道

首先,传统jpg图像之间的叠加是在背景图像上确定一块与待叠加图像尺寸相同的区域进行叠加。例如,50*50*3尺寸的jpg图像要叠加到100*100*3尺寸的jpg背景图像上,需要在背景图像上指定50*50*3的区域来放入前者。代码如下:

import numpy as np import cv2 # 创建一张100*100*3尺寸的黑色背景图像 img_bg = np.zeros((100,100), dtype=np.uint8) img_bg = cv2.cvtColor(img_bg, cv2.COLOR_GRAY2BGR) # 创建一张50*50*3尺寸的白色待叠加图像 img_white = np.ones((50,50), dtype=np.uint8) img_white = cv2.cvtColor(img_white, cv2.COLOR_GRAY2BGR) # 将白色图像叠加到黑色背景背景图像上,叠加位置为左上角 img_bg[:50,:50,:] = img_white # 显示图像 cv2.imshow('result', img_bg) # 显示叠加后的结果图像 if cv2.waitKey(0) & 0xFF == 27: cv2.destroyAllWindows()

 

 

 

jpg图像叠加时,它们的通道数都为3,不会出现问题。但当png4通道图像往jpg3通道图像上叠加时,则会出现图像尺寸不匹配的问题。例如,在100*100*3尺寸的jpg图像上无法划定出50*50*4的空间来让png图像放入。为了解决这一问题,我们需要为jpg图像增加Alpha通道,可以理解成我们来增大jpg图像的尺寸,使它足够大能容下png图像。代码如下:

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

 

3. 将png透明图像叠加到jpg图像上

在叠加图像前,我们需要确定在背景图像的哪个位置进行叠加,这里我们在背景图像中设2个坐标点:(x1, y1) 和 (x2, y2) 分别表示叠加位置的左上角坐标和右下角坐标。

 

 

图像叠加代码如下:

img_bg[y2:y1,x1:x2] = img_white

 

OK,了解了基础原理后,我们现在开始进行正式的图像叠加,代码如下:

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 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

 

这里我讲上述所有代码进行整合,png图像叠加到jpg图像上的完整代码如下:

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 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() 

 

【结果显示】

用我家主子的照片来试一下效果啦~

最后,希望本文能帮助到热爱图像处理的小伙伴们~

 

 

原文出处:https://blog.csdn.net/weixin_40065609/article/details/114886234

 



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭