我在实际工作中需要将一个存在alpha图层的Png图片经过正片叠底后,合成出一个新的渲染后图片,之后图片进行处理导出成jpg图片,这就需要剔除图片中的alpha通道,然而直接粗暴的剔除则会发生图片的正片叠底效果完全无用,变成了一大片图片糊在上面(因为透明内容丢失)
此时我参考了一篇这个文章,因为我核心的处理需求还是(透明底转换成白色底)
#利用Pillow进行处理-opencv同理
from PIL import Image
def alphabg2white_PIL(img):
img=img.convert('RGBA')
sp=img.size
width=sp[0]
height=sp[1]
print(sp)
for yh in range(height):
for xw in range(width):
dot=(xw,yh)
color_d=img.getpixel(dot)
if(color_d[3]==0):
color_d=(255,255,255,255)
img.putpixel(dot,color_d)
img.show()
return img
使用效果,的确能够把透明内容转换成白色内容,可是:【太】【卡】【了】!
运行效率极其低下
解剖一下代码的原理,无非就是遍历搜索(两层高度和长度的遍历)*(每一层内部的RGBA值得遍历),复杂度高到爆炸。
即时使用numpy进行优化(说明一下原理,numpy会把矩阵处理的内容通过预制的二进制代码的方式进行处理,相比Python解释器慢慢挪动,numpy简直就是火箭),也一样会花费大量的实践。
回头一想
为什么要用遍历呢?【笨蛋!】
一个极其简单的思维,创建一个白色无透明的白色模板,尺寸与相关处理图片尺寸一致,作为底色蒙版,利用PIL的alpha通道混合算法将已经处理后的图片粘贴上去,再将rgb值单独提取出来保存为jpg格式不是更好么?
#渲染代码---需要将两张图片进行合并
def back_fusion(self):
savePath = self.savePath + "\ansBack.png"
img1 = Image.open("tmp.jpg")
img1 = img1.convert("RGBA")
img2 = Image.open(self.FoldDiagram_back_path)
#创建白色模板
white = Image.new("RGBA", img2.size, color=(255, 255, 255, 255))
print("开始正片叠底:", img1.mode, "----", img2.mode)
ans = IC.multiply(img2, img1)
# 将白色模板和导出后的图片进行重叠
ans = Image.alpha_composite(white, ans)
ans.save(savePath, dpi=(96, 96))
# 调用去除alpha通道算法,如果不需要去除alpha通道注释掉即可
self.removeAlpha(savePath)
if os.path.isfile(savePath):
os.remove(savePath)
print("保存褶皱图【后】渲染 成功")
# 移除alpha通道并将png保存为jpg
def removeAlpha(self, path):
img = cv2.imread(path, -1) # 读取渲染图
bgr = img[:, :, :3]
cv2.imwrite(path[:-3]+"jpg", bgr, [
int(cv2.IMWRITE_PNG_COMPRESSION), 0]) # 0 ~ 9 (low - high)
和遍历相比较,通过创建一个纯色空间的图片进行重叠处理,比长宽不等消耗内存越来越多速度越来越慢的循环处理方法,可以规避掉O(n^2)的复杂度变为常数级
Post Views:
901