用Python制作音乐海报


Posted in Python onJanuary 26, 2021

前言

前段时间在一个朋友那么得到的灵感,想到可以用音乐播放页面作为一张海报图片。其实接下来要讲的和海报还是有差距的,而具体实现也只是简单的图片粘贴,但是在效果上还是不错的。效果图如下,希望大家喜欢:

用Python制作音乐海报

左边是原图,右边是需要添加到中间的图,也是图的主角。其实如果直接用ps实现上面的图是非常简单的,反倒是用代码实现有点曲折,不过实现过程还是非常有趣的,希望这篇博客可以可以让你学到知识。

用Pillow创建圆形图

在上面的图片中,中间是一个圆形图片,而Pillow本身是没有提供生成圆形图片的方法(也可能是我没找到),所以就需要自己实现。在实现之前,我们先安装Pillow模块:

pip install pillow

要创建圆形图,我们先根据原图的大小,创建一个RGBA模式的透明图:

# 该方法传入三个参数,第一个为模式,第二个为大小的元组,第三个为颜色
im = Image.new('RGBA', (300, 300), (255, 255, 255, 0))

上述代码是创建了一个完全透明的300*300的图片,我们在该图片上绘制一个最大的圆:

# 获取绘制者
drawer = ImageDraw.Draw(im)
# 绘制一个黄色的圆,ellipse方法传入三个参数,第一个为包含该圆的最小正方形的区域,第二个为颜色,第三个为边宽
drawer.ellipse((0, 0, 300, 300), fill=(255, 255, 0), width=0)

生成图片如下:

用Python制作音乐海报

我们准备一张300*300的正方形图片,然后遍历图片的每个像素,如果像素值的A==0(即像素不透明)那我们就将图片该区域的像素值设置为透明。

用Python制作音乐海报

代码如下:

# 打开要转换成圆形的图片,我们事先把图片裁剪好
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

在上面的方法中,我们改进了一些代码,之前我们需要使用指定大小的图片作为素材,现在只需要是正方形图片就可以了。

生成海报

原本我以为直接将圆形图片粘贴到背景图片上就可以了,但是试过之后发现效果和我想的不太一样,反正就是没成功,效果如下:

用Python制作音乐海报

是粘贴上去了没错,而且图片也是透明效果,但是从这个效果来看粘贴只是像素替换,而不是图片叠加。于是我又想到了遍历像素的办法。

我通过特殊手段获取了上面正方形离左边的像素,和离上边的像素(其实就是用ps看了一下)。我尝试过图形检测和像素判断的办法,想自动识别中间圆的位置,但是效果不佳(反正就是失败了),所以只能无耻的用ps查看像素。

回到正题,我们用遍历像素的办法不需要遍历整个图片,只需要从(left, top)像素开始,遍历到(left+radius, top+radius)区域即可,也就是遍历正方形区域(left、top和radius都是我通过ps获取的)。

我们先将背景图片拷贝一份,然后在副本上进行粘贴。然后遍历粘贴后的图片,如果像素值为透明,我们就将原图该位置的像素替换至副本处,实现原理和上面一样,代码如下:

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 制作音乐海报的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python的常见命令注入威胁
Feb 18 Python
浅谈MySQL中的触发器
May 05 Python
Python简单删除目录下文件以及文件夹的方法
May 27 Python
使用简单工厂模式来进行Python的设计模式编程
Mar 01 Python
详解Python3 中hasattr()、getattr()、setattr()、delattr()函数及示例代码数
Apr 18 Python
django Serializer序列化使用方法详解
Oct 16 Python
Python常见数据结构之栈与队列用法示例
Jan 14 Python
pycharm修改界面主题颜色的方法
Jan 17 Python
Python使用到第三方库PyMuPDF图片与pdf相互转换
May 03 Python
Python拆分大型CSV文件代码实例
Oct 07 Python
Python基于数列实现购物车程序过程详解
Jun 09 Python
C++和python实现阿姆斯特朗数字查找实例代码
Dec 07 Python
python中pyqtgraph知识点总结
Jan 26 #Python
Appium+Python实现简单的自动化登录测试的实现
Jan 26 #Python
使用Python+Appuim 清理微信的方法
Jan 26 #Python
详解使用python爬取抖音app视频(appium可以操控手机)
Jan 26 #Python
python Matplotlib基础--如何添加文本和标注
Jan 26 #Python
python如何用matplotlib创建三维图表
Jan 26 #Python
python软件测试Jmeter性能测试JDBC Request(结合数据库)的使用详解
Jan 26 #Python
You might like
PHP 加密与解密的斗争
2009/04/17 PHP
判断Keep-Alive模式的HTTP请求的结束的实现代码
2011/08/06 PHP
PHP实现简单ajax Loading加载功能示例
2016/12/28 PHP
yii2多图上传组件的使用教程
2018/05/10 PHP
VSCode+PHPstudy配置PHP开发环境的步骤详解
2020/08/20 PHP
JavaScript 错误处理与调试经验总结
2010/08/10 Javascript
jquery高级编程的最佳实践详解
2014/03/23 Javascript
滚动条响应鼠标滑轮事件实现上下滚动的js代码
2014/06/30 Javascript
JQuery+Ajax实现数据查询、排序和分页功能
2015/09/27 Javascript
Jquery attr()方法 属性赋值和属性获取详解
2016/04/15 Javascript
Javascript动画效果(1)
2016/10/11 Javascript
实现单层json按照key字母顺序排序的示例
2017/12/06 Javascript
解决vue页面DOM操作不生效的问题
2018/03/17 Javascript
基于ionic实现下拉刷新功能
2018/05/10 Javascript
Vue2.0 v-for filter列表过滤功能的实现
2018/09/07 Javascript
区别JavaScript函数声明与变量声明
2018/09/12 Javascript
vue最简单的前后端交互示例详解
2018/10/11 Javascript
vue项目每30秒刷新1次接口的实现方法
2018/12/04 Javascript
详解JavaScript实现动态的轮播图效果
2019/04/29 Javascript
通过js示例讲解时间复杂度与空间复杂度
2019/08/06 Javascript
Ant design vue table 单击行选中 勾选checkbox教程
2020/10/24 Javascript
[58:42]DOTA2上海特级锦标赛C组败者赛 Newbee VS Archon第一局
2016/02/27 DOTA
python在回调函数中获取返回值的方法
2019/02/22 Python
Python中的异常处理try/except/finally/raise用法分析
2019/02/28 Python
Django Rest framework三种分页方式详解
2019/07/26 Python
Django异步任务线程池实现原理
2019/12/17 Python
python tkinter实现连连看游戏
2020/11/16 Python
德国网上药房:Apotal
2017/04/04 全球购物
信息总监管理职责范本
2014/03/08 职场文书
优质护理服务演讲稿
2014/05/07 职场文书
机电一体化专业毕业生自荐信
2014/06/19 职场文书
金融保险专业求职信
2014/09/03 职场文书
观看《周恩来的四个昼夜》思想汇报
2014/09/12 职场文书
幼儿园老师工作总结2015
2015/05/22 职场文书
初中政治教学工作总结
2015/08/13 职场文书
CSS 使用 resize 实现图片拖拽切换预览功能(强大功能)
2021/08/23 HTML / CSS