Python制作音乐海报:Pillow圆形裁剪与像素合成实战
本文介绍使用Python的Pillow库制作音乐海报的方法。通过创建透明RGBA图像并绘制圆形,实现非正方形图片的圆形裁剪。随后利用像素遍历技术,将圆形图片与背景图进行透明区域替换合成,解决直接粘贴导致的边缘问题。
前言
受朋友启发,尝试将音乐播放界面转化为海报图片。虽然最终效果与专业海报仍有差距,且核心实现仅涉及基础图片粘贴,但整体视觉呈现效果良好。具体效果见下文示例,期待读者喜爱。

左侧为原始素材图,右侧为需嵌入中心的主体图片。若使用Photoshop完成此效果十分简便,但通过代码实现过程较为曲折。尽管挑战不小,实现过程颇具趣味,希望本文能为您带来技术启发。
使用Pillow创建圆形图像
观察前述示例,中心区域为圆形图片。Pillow库未直接提供生成圆形图片的内置方法(或笔者尚未发现),因此需自行实现。首先,请确保已安装Pillow模块:
pip install pillow
创建圆形图像的第一步,是根据原始图片的尺寸,创建一个RGBA模式的透明图像:
# 该方法传入三个参数,第一个为模式,第二个为大小的元组,第三个为颜色
im = Image.new('RGBA', (300, 300), (255, 255, 255, 0))
上述代码生成了一个尺寸为300x300的完全透明图像。接下来,在该图像上绘制一个最大内切圆:
# 获取绘制者
drawer = ImageDraw.Draw(im)
# 绘制一个黄色的圆,ellipse方法传入三个参数,第一个为包含该圆的最小正方形的区域,第二个为颜色,第三个为边宽
drawer.ellipse((0, 0, 300, 300), fill=(255, 255, 0), width=0)
生成的图像效果如下:

准备一张300x300的正方形图片,遍历其每个像素。若某像素的Alpha通道值为0(即不透明),则将该位置像素设为透明。

具体实现代码如下:
# 打开要转换成圆形的图片,我们事先把图片裁剪好
pic = Image.open(img_path).convert('RGBA')
# 遍历图片的每个像素
for i in range(300):
for j in range(300):
# 获取该像素点的像素
r, g, b, a = im.getpixel((i, j))
# 当rgb值不是黄色时,即像素值为透明时
if (r, g, b) != (255, 255, 0):
# 将原图的像素值设置为透明
pic.putpixel((i, j), (255, 255, 255, 0))
此时,pic变量即为生成的圆形图片。完整代码示例如下:
# 背景图中圆的直径
radius = 533
# 图片的大小
circle_size = (radius, radius)
def generate_circle_image(img_path):
# 创建一个透明的正方形
im = Image.new('RGBA', circle_size, (255, 255, 255, 0))
# 获取绘画者
drawer = ImageDraw.Draw(im)
# 在透明的正方形上画一个黄色的圆
drawer.ellipse((0, 0, circle_size[0], circle_size[1]), fill=(255, 255, 0), width=0)
# 打开要转换成圆形的图片,我们事先把图片裁剪好
pic = Image.open(img_path).convert('RGBA')
# 修改图片大小,让图片和圆大小一样
re_pic = pic.resize(circle_size, Image.ANTIALIAS)
# 遍历图片的每个像素
for i in range(circle_size[0]):
for j in range(circle_size[1]):
r, g, b, a = im.getpixel((i, j))
if (r, g, b) != (255, 255, 0):
re_pic.putpixel((i, j), (255, 255, 255, 0))
return re_pic
上述方法对代码进行了优化。此前需使用特定尺寸的图片作为素材,现在仅需输入正方形图片即可自动处理。
生成海报
起初认为直接将圆形图片粘贴至背景图即可,但实际测试效果不符预期,具体失败效果如下:

虽然图片已粘贴且呈现透明效果,但从结果看,粘贴操作仅为像素替换,并未实现真正的图片叠加混合。因此,笔者转而尝试遍历像素的方法。
通过特殊手段获取了正方形图片中圆形区域距离左侧和上侧的像素坐标(此处借助Photoshop查看)。曾尝试通过图形检测和像素判断自动识别圆形位置,但效果不佳(最终失败),故只能使用Photoshop手动获取像素坐标。
回归正题,采用遍历像素的方法无需遍历整张图片,只需从(left, top)坐标开始,遍历至(left+radius, top+radius)区域即可。该区域为正方形范围,其中left、top和radius参数均通过Photoshop获取。
首先拷贝背景图片,在副本上进行圆形图片粘贴。随后遍历粘贴后的图像,若某像素值为透明,则将原背景图对应位置的像素替换至副本中。原理与前述圆形裁剪一致,代码如下:
def generate_music_post(circle_im, bg_im):
"""
传入圆形图片和背景图片生成音乐海报
circle_im:圆形图片
bg_im:背景图片
return:生成的图片
"""
# 拷贝副本
bg_copy = bg_im.copy()
# 将圆形图片粘贴到副本上
bg_copy.paste(circle_im, (left, top))
# 遍历像素正方形区域
for i in range(left, left+radius):
for j in range(top, top+radius):
# 获取像素值
color = bg_copy.getpixel((i, j))
# 如果像素透明。color的值为(r,g,b,a),color[3]为a的值,即透明值
if color[3] == 0:
# 将原图像素替换至副本透明处
bg_copy.putpixel((i, j), bg_im.getpixel((i, j)))
# 返回合成后的图片
return bg_copy
至此,海报生成完成。完整代码示例如下:
from PIL import Image, ImageDraw
left = 273 # 圆离左边的距离
top = 573 # 圆离上边的距离
radius = 533 # 圆的直径
circle_size = (radius, radius) # 圆的外接正方形的大小
def generate_circle_image(img_path):
# 创建一个透明的正方形
im = Image.new('RGBA', circle_size, (255, 255, 255, 0))
# 获取绘画者
drawer = ImageDraw.Draw(im)
# 在透明的正方形上画一个黄色的圆
drawer.ellipse((0, 0, circle_size[0], circle_size[1]), fill=(255, 255, 0), width=0)
# 打开要转换成圆形的图片,我们事先把图片裁剪好
pic = Image.open(img_path).convert('RGBA')
re_pic = pic.resize(circle_size, Image.ANTIALIAS)
# 遍历图片的每个像素
for i in range(circle_size[0]):
for j in range(circle_size[1]):
r, g, b, a = im.getpixel((i, j))
if (r, g, b) != (255, 255, 0):
re_pic.putpixel((i, j), (255, 255, 255, 0))
return re_pic
def generate_music_post(circle_im, bg_im):
"""
传入圆形图片和背景图片生成音乐海报
circle_im:圆形图片
bg_im:背景图片
return:生成的图片
"""
# 拷贝副本
bg_copy = bg_im.copy()
# 将圆形图片粘贴到副本上
bg_copy.paste(circle_im, (left, top))
# 遍历像素正方形区域
for i in range(left, left+radius):
for j in range(top, top+radius):
# 获取像素值
color = bg_copy.getpixel((i, j))
# 如果像素透明。color的值为(r,g,b,a),color[3]为a的值,即透明值
if color[3] == 0:
# 将原图像素替换至副本透明处
bg_copy.putpixel((i, j), bg_im.getpixel((i, j)))
# 返回合成后的图片
return bg_copy
# 生成圆形图片
pic = generate_circle_image('girl.jpeg')
# 以RGBA模式读取背景图片
bg_im = Image.open('music.jpg').convert('RGBA')
# 生成音乐海报
music_post = generate_music_post(pic, bg_im)
music_post.show()
此外,该示例可进一步智能化。例如,利用OpenCV识别主体图片中的人脸,根据人脸区域计算合适的正方形裁剪区。这样便无需预先传入正方形图片(但仍需考虑人脸识别的精度等因素)。
完整代码已上传至GitHub,地址如下:https://github.com/IronSpiderMan/MusicPost
示例素材图片亦包含在仓库中。
以上为使用Python制作音乐海报的详细内容,更多Python制作海报的相关资料请关注本站其他文章。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













