Python使用PIL库实现图片合成的两种方法
本文介绍利用Python PIL库进行图片合成的两种实现方式。第一种方法通过交替选取像素点合成新图,避免曝光过度但可能轮廓模糊;第二种方法按可调比例混合RGB值,效果更自然但需控制参数。文章提供完整代码示例及优劣对比,并提及Image.blend函数的存在。
Python PIL库图片合成概述
Python中的PIL库功能强大,其Image模块封装了丰富的图像处理函数。关于该模块的具体介绍与用法,可参考官方文档:http://effbot.org/imagingbook/image.htm
基于此前看到的一篇博客示例,本文演示如何进行图片合成操作。
方法一:像素交替合成
图像由像素点构成,每个像素对应一个RGB颜色值(red, green, blue)。合成两张照片时,可以在新图中按位置交替选取两张原图的像素点,遍历完成后即可得到合成结果,具体代码如下:
from PIL import Image
##这里采用传入图片地址调用此函数
#这个方法目前不支持按比例合成,默认为1:1
#各取一个像素点合并,传入的参数为两张图片的地址
def merge1(img1_address,img2_addess):
status=100
#状态码100为正常
# 200为地址错误
try:
img1=Image.open(img1_address)
img2=Image.open(img2_address)
except:
status=200
img_new=""
else:
width=min(img1.size[0],img2.size[0])
height=min(img1.size[1],img2.size[1])
print(width,height)
img_new = Image.new('RGB',(width,height))
for x in range(width):
for y in range(height):
if y%2==0:
pixel=img1.getpixel((x,y))
img_new.putpixel((x,y),pixel)
else:
pixel=img2.getpixel((x,y))
img_new.putpixel((x,y),pixel)
finally:
return img_new,status
上述代码执行后会返回一张新图片对象及一个状态码,调用时需使用两个变量分别接收这两个返回值。
方法二:按比例混合合成
另一种方案是对每个像素点,按固定比例(默认各占50%)混合两张原图的颜色值,再放置到对应位置。为增强灵活性,此处将混合比例设为可调参数,默认比例为50%,代码如下:
from PIL import Image
#将像素点按比例取色,然后合成一个新像素点
#传入的参数为两张图片的地址和比例
#如果两者之和不为1则以第一个图片的比例为准
def merge2(img1_address,img2_address,percent1=0.50,percent2=0.50):
status=100
#状态码100为正常
# 200为地址错误
try:
img1=Image.open(img1_address)
img2=Image.open(img2_address)
except:
status=200
img_new=""
else:
if percent1+percent2!=1:
percent2=1-percent1
width = min(img1.size[0],img2.size[0])
height = min(img1.size[1],img2.size[1])
img_new = Image.new('RGB',(width,height))
for x in range(width):
for y in range(height):
r1,g1,b1=img1.getpixel((x,y))
r2,g2,b2=img2.getpixel((x,y))
r=int(percent1*r1+percent2*r2)
g=int(percent1*g1+percent2*g2)
b=int(percent1*b1+percent2*b2)
img_new.putpixel((x,y),(r,g,b))
finally:
return img_new,status
返回参数与前述方法一致。若需保存结果,可调用image.save()函数进行保存。
完整代码如下:
from PIL import Image
##这里采用传入图片地址调用此函数
#这个方法目前不支持按比例合成,默认为1:1
#各取一个像素点合并,传入的参数为两张图片的地址
def merge1(img1_address, img2_addess, direct):
status=100
#状态码100为正常
# 200为地址错误
try:
img1=Image.open(img1_address)
img2=Image.open(img2_address)
except:
status=200
img_new=""
else:
width=min(img1.size[0], img2.size[0])
height=min(img1.size[1], img2.size[1])
print(width,height)
img_new = Image.new('RGB',(width, height))
for x in range(width):
for y in range(height):
if y%2 == 0:
pixel = img1.getpixel((x,y))
img_new.putpixel((x,y), pixel)
else:
pixel = img2.getpixel((x,y))
img_new.putpixel((x,y), pixel)
finally:
return status
#将像素点按比例取色,然后合成一个新像素点
#传入的参数为两张图片的地址和比例
#如果两者之和不为1则以第一个图片的比例为准
def merge2(img1_address, img2_address, direction, percent1):
status = 100
#状态码100为正常
# 200为地址错误
try:
img1 = Image.open(img1_address)
img2 = Image.open(img2_address)
except:
status = 200
img_new = ""
else:
percent2 = 1 - percent1
width = min(img1.size[0], img2.size[0])
height = min(img1.size[1], img2.size[1])
img_new = Image.new('RGB', (width,height))
for x in range(width):
for y in range(height):
r1,g1,b1=img1.getpixel((x,y))
r2,g2,b2=img2.getpixel((x,y))
r = int(percent1 * r1 + percent2 * r2)
g = int(percent1 * g1 +percent2 * g2)
b = int(percent1 * b1 +percent2 * b2)
img_new.putpixel((x,y),(r,g,b))
img_new.save(direction)
#img_new.show()
finally:
return status
#切记在接受返回信息时先判断状态码是否异常,如果正确再执行相应操作
if __name__=='__main__':
img1_address = "B:\Picture\YourName\1.jpg"
img2_address = "B:\Picture\YourName\2.jpg"
direction = "D:/Python/PyQt/课程设计/merges/merge9.png"
status = merge2(img1_address, img2_address, direction, 0.30)
print(status)
此外,Image库提供了Image.blend(image1, image2, alpha)函数用于图片混合,其具体实现原理尚未查阅源码,暂不清楚其内部算法。
原始的两张测试图片如下:

合成后的效果图片如下:

左图为方法一的合成结果,右图为方法二的合成结果。
两种方法的优劣对比
优劣分析: 方法一不会导致曝光过度,因为实际像素值未被修改,仅改变了排列间隔,但可能导致图像轮廓不够清晰。 方法二在比例设置恰当时效果优于方法一,但若比例不当,图像会呈现类似曝光过度的效果。示例中方法二采用的比例为0.3:0.7,若比例选择不当,效果可能较差。具体选用哪种方法,应根据实际视觉效果决定。
以上是关于Python图片合成示例的详细介绍,更多相关技术内容请关注本站其他文章。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













