Python之禅字幕显示_仿抖音渐显文字

Python之禅字幕显示_仿抖音渐显文字

大家好,我是萍乡李兴球,专业从事Python教研的,主要方向为Python创意程序的编写与教学。编程是细活,在本次要讲的程序中,我们要听到一首曲子。它是日本民谣四季歌。让我们先来听一下这首歌曲吧。

下面是歌词:

喜爱春天的人儿啊 心地纯洁的人,象紫罗兰的花儿一样,是我知心的朋友。
喜爱夏天的人儿啊 意志坚强的人,象冲击岩石的波浪一样,是我敬爱的父亲。
喜爱秋天的人儿啊 感情深重的人,象抒发爱情的海涅一样,是我心上的人。
喜爱冬天的人儿啊 胸怀宽广的人,象融化冰雪的大地一样,是我亲爱的母亲。

李兴球Python公众号四季歌背景

相信能慢慢地聆听完这首歌的人,都是有耐心的人,恭喜你,已经具备学习编程的重大品质之一了!

李兴球Python公众号女人打太极拳

所谓,快不如慢,意思就是说,我们有时候需要慢,才能体会到过程中的乐趣。在我们上网的时候,有时候网速很慢,我们能看到图片是逐像素显示出来的。在本次程序介绍中,我们是人为地让一幅图形逐行像素地慢慢显示出来。就像下面这样:

本次编程需要用到的模块有兰姆派模块,即numpy模块。如果计算机中没有安装兰姆派模块,那么在命令提示符下使用pip install numpy即可安装。


还有就是要有枕头模块,即pillow模块。安装方法也一样,输入pip install pillow即可。

李兴球Python公众号枕头模块

最后,要有一个显示图形的模块,这里选用的是tkinter模块。当然用turtle模块也可以。

李兴球Python公众号萌小海龟

俗话说,打蛇打七寸,这里先说一下将要编写的程序的主要工作原理。

蛇李兴球Python公众号蛇

那就是用numpy模块的split命令把数组辟开成若干行,每一行都是一行像素!接下来就转换成高度只有一个像素的图形列表。看到这里,读者蒙了吧。我们先从简单的开始。

李兴球Python公众号使劲劈

下面用’red’,’orange’等来表示一个像素值!按照我老李的习惯,先上代码:

>>> import numpy as np
>>> cs = [['red','orange','yellow','green'],
          ['white','cyan','blue','magenta'],
          ['gray','blue','orange','lime']]
>>> colors = np.array(cs)                # 把cs转换成np二维数组
>>> a = len(colors)                      # a表示数组的行数,本例是3行
>>> rows = np.split(colors,a)            # 辟开为a行,
>>> rows                                 # rows是一个列表,存储了3行np数组
[array([['red', 'orange', 'yellow', 'green']], dtype='<U7'),
 array([['white', 'cyan', 'blue','magenta']], dtype='<U7'), 
array([['gray', 'blue', 'orange', 'lime']], dtype='<U7')] >>> rows[0]
array([['red', 'orange', 'yellow', 'green']], dtype='<U7') >>>

在上面的程序中,给兰姆派取了一个叫np的别名。有一个叫cs的嵌套列表,colors则是np二维数组。关键就是np.split命令,就是它把colors数组一行一行的辟开了!每一行都放在了rows列表中。也就是说rows[0]就是红橙黄绿,rows[1]就是白青蓝品红,rows[2]就是灰蓝橙亮绿!

在一幅图像中,我们把图像也辟开成一行一行的像素,然后把每行像素在tkinter的画布的不同位置显示出来,那么就能看到逐行显示图像的效果。下面就是核心函数!代码如下所示:

def split_image(pic):
    """pic是一张图片,返回图片的每行像素"""
    im = Image.open(pic)                          # 打开图形
    ims = np.array(im)                            # 转为数组
    rows = np.split(ims,len(ims))                 # 按行辟开
    return [Image.fromarray(row) for row in rows] # 返回每行 

接下来,我们只要把每一行像素在画布的不同位置显示即可。由于画布的坐标系和图像是一样的。所以,每行像素在画布显示的y坐标逐步加1即可。以下是逐行像素显示图形的所有代码!

"""
   逐行像素显示图形.py
"""
__author__ = '李兴球'
__blog__ = 'www.lixingqiu.com'
__date__ = '2021/2/20'

import time
import numpy as np
from tkinter import *
from PIL import Image,ImageTk

def split_image(pic):
    """pic是一张图片,返回图片的每行像素"""
    im = Image.open(pic)                          # 打开图形
    ims = np.array(im)                            # 转为数组
    rows = np.split(ims,len(ims))                 # 按行辟开
    return [Image.fromarray(row) for row in rows] # 返回每行 

root = Tk()                                       # 新建窗口
cv = Canvas(width=480,height=360,bg='white')      # 新建画布
cv.pack()                                         # 放置画布           

turtle = cv.create_image(240,180,image='')        # 创建图形对象

rows = split_image('turtle.png')                  # 调用函数辟开图
a = len(rows)                                     # 行数

ps = [ImageTk.PhotoImage(im) for im in rows]  # 包装每行为PhotoImage对象
items = [cv.create_image(240,180+i,image='') for i in range(a)]

for i in range(a):
    cv.itemconfig(items[i],image=ps[i])          # 配置一行像素
    cv.update()                                  # 更新画布显示
    time.sleep(0.1)                              # 等待0.1秒

root.mainloop()

在上面的代码中,ps列表是每行像素的PhotoImage包装。items则是所有要在画布上显示的图形!为什么要准备这么多图形的item?这是由于,虽然我们是显示一幅图,但是由于要慢慢地显示这幅图,所以把它拆成了很多很多的图像来显示。这些图的高度只有一个像素!宽度则和原图相同。

李兴球Python公众号一像素高

如果显示一张名为turtle.png图的宽度是220像素,高度是166像素。通过split命令及转换后,把它拆分成了166张图。它们的宽度都是220,高度都是1个像素。在最后的for循环中,就是重新配置每一个item编号的图形。

好了,上面已经讲了如何逐行像素的显示图形了。下面就是发挥想像力,制作的一个小作品。视频效果如下所示:

实现上面效果的程序有本次讲的程序稍有区别,主要是采用了面向对象编程的思想。在程序中设计了一个名叫Shower的类。它有display方法,实现慢慢地显示图形。它有disappear方法,实现慢慢地消失图形。关注公众号: 李兴球Python,回复pythonzhi可免费得到本程序源代码及所有素材。谢谢你认真阅读了我写的文章。

李兴球

李兴球的博客是Python创意编程原创博客