通过python绘制华强买瓜的字符画视频

已经11月了,不知道还有没有人看华强买瓜。。。要把华强卖瓜做成字符视频,总共分为三步

  1. 读取视频
  2. 把每一帧转为字符画
  3. 把字符画表现出来

读取视频

通过imageio读取视频,除了pip install imageio之外,还需要pip install imageio-ffmpeg

由于视频中的图像都是彩色的,故而需要将rgb三色转为单一的强度,并将转化后的图像装入一个列表中。

import imageio
import numpy as np
import matplotlib.pyplot as plt
video = imageio.get_reader('test.mp4')
imgs = []
for img in video:
    imgs.append(np.mean(img,2))
plt.imshow(imgs[0])
plt.show()

效果如下,看到了如此亲切的画面,华强骑着他心爱的小摩托,背后原因让人暖心。

在这里插入图片描述

转为字符

这个视频虽然已被压缩,但对于字符画而言还是太大了,所以转字符画之前需对其进一步压缩。这里采取最简单的方法——即对相邻的像素取平均值。

from itertools import product   #用于循环嵌套
def resizeImg(img,w,h=None):
    m,n = img.shape
    if n<w:
        return img
    if not h:
        h = int(m*w/n)
    im = np.zeros([h,w])
    rw,rh = n/w,m/h
    dw,dh = int(rw),int(rh) #取均值的步长
    for i,j in product(range(h),range(w)):
        I,J = int(i*rh),int(j*rw)
        im[i,j] = np.mean(img[I:I+dh,J:J+dw])
    return im

这个函数的功能是将图像宽度缩小至width,函数中rw, rh分别表示缩放比例,接下来测试一下

im = resizeImg(imgs[0],160)
plt.imshow(im)
plt.show()

效果如下,可以清晰地发现,华强变糊了,但这丝毫阻挡不了瓜老板的命运,背后原因让世界变暖。

在这里插入图片描述

接下来,就可以生成字符画了,所谓字符画,无非是将像素值映射成一个字符,下面选取的用于映射的字符为:▇圞國图囜ⒶⒷⒸB8&WMZO0QJX@%&jfoavunxr#t/|()1{}[]?-_+~<>i!lI;:,"^'. ^'. ,由密集到稀疏

pixels = "▇圞國图囜ⒶⒷⒸB8&WMZO0QJX@%&jfoavunxr#t/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ^`'. " 
def im2txt(img):
    im = np.floor(img/255*len(pixels)).astype(int)
    txts = ""
    for line in im:
        txts += "".join([pixels[i] for i in line])
        txts += '\r\n'    #像素换行时文本也要换行
    return txts
#测试
txt = im2txt(im)
print(txt)

结果就可以从字符中依稀看到华强的音容笑貌

在这里插入图片描述

动画

让命令行绘制字符视频,听上去可能有些不可思议,但这个功能可以仅凭python内置的模块实现——即curses,唯一可惜的是,Windows下的Python并不内置这个模块,需要额外安装。所以这个内置模块也是内置了个寂寞。

先下载和自己python版本相符的curses,然后通过pip命令安装

>pip install "curses-2.2.1+utf8-cp310-cp310-win_amd64.whl"

然后就可以在python中调用了。由于视频太大,所以这里只演示一小段,效果如下

在这里插入图片描述

主程序的代码如下

if __name__ == "__main__":
    video = imageio.get_reader('test.mp4')
    txts = []
    # 生成字符画
    for img in video:
        im = resizeImg(np.mean(img,2),120,30)
        txts.append(im2txt(im))

    scr = curses.initscr()
    scr.timeout(40)
    #scr.
    for txt in cycle(txts):
        scr.addstr(0,0,txt)
        scr.border(0)
        scr.refresh()
        #curses.delay_output(25)
        if scr.getch()==27: #如果按下`esc`则退出`
            break

其中scr在初始化之后,将每次等待键盘输入的时间为了40ms。

完整代码

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微小冷

请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值