视频转字符动画(Python3)

今天刷抖音,看到了一个《极乐净土》的字符动画,舞蹈看起来妖娆啊,满屏幕的字符勾勒出美女的身影,在配上极乐净土的音乐,简直是程序员们的精神食粮啊!!!!

以前也遇到过这种字符动画,当时简单想了想,大概就是控制台的字符输出刷新,再输出什么的吧,只是觉得所有字符手撸太累了,就没深入思考,今天看到这个《极乐净土》中途压制不住内心的冲动,要自己动手来一个了。

关于原理什么的,这篇文章介绍的比较多,我就不多赘述了,也感谢这位老哥提供思路,不然这么久的python图像处理感觉白玩了

视频转字符动画-Python-60行代码

该教程基于python使用openvc做的,我下面的代码使用skimage实现的:

from skimage import color,transform as trans
import imageio

class Transfer:
    # 视频路径
    __video_path = ''
    # 视频中提取出来的帧图像
    __input_imgs = []
    # 字符填充 从左到右辨识度增加
    __pixels = " .,-'`:!1+*abcdefghijklmnopqrstuvwxyz<>()\/{}[]?234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ%&@#$"
    # 输出的字符'图像'
    __output_imgs = []
    # 填充字符长度
    __pixels_length = 0

    def run(self):
        self.__pixels_lenth = len(self.__pixels)
        self.__readVideo()
        self.__transImgsIntoChars()
        print(len(self.__output_imgs))
        self.__play()
        # echo 0

    # 设置视频路径
    def setVideo(self, video_path):
        self.__video_path = video_path
        return  self

    # 读取视频的每一帧图像转化为灰度图,输出图像列表
    def __readVideo(self):
        imgs = imageio.get_reader(self.__video_path,'ffmpeg')
        for num,img in enumerate(imgs):
            print(img.shape)
            a = color.rgb2gray(img)
            # 根据你控制台的尺寸自己定义resize后的尺寸
            b = trans.resize(a, (64, 64),1,None,0,True,True,None,None)
            self.__input_imgs.append(b)

    # 灰度图像转化为字符图像
    def __transImgsIntoChars(self):
        for input in self.__input_imgs:
            item = []
            (h,w) = input.shape
            for row in range(h):
                row_chars = ''
                for col in range(w):
                    index = int(input[row][col] * (self.__pixels_lenth -1))
                    row_chars += self.__pixels[index]
                item.append(row_chars)
            self.__output_imgs.append(item)

    # 播放
    def __play(self):
        import time
        import curses
        width, height = len(self.__output_imgs[0][0]), len(self.__output_imgs[0])
        stdscr = curses.initscr()
        curses.start_color()
        try:
            # 调整窗口大小,宽度最好略大于字符画宽度。另外注意curses的height和width的顺序
            stdscr.resize(height, width * 2)

            for pic_i in range(len(self.__output_imgs)):
                # 显示 pic_i,即第i帧字符画
                for line_i in range(height):
                    # 将pic_i的第i行写入第i列。(line_i, 0)表示从第i行的开头开始写入。最后一个参数设置字符为白色
                    stdscr.addstr(line_i, 0, self.__output_imgs[pic_i][line_i], curses.COLOR_WHITE)
                stdscr.refresh()  # 写入后需要refresh才会立即更新界面
                time.sleep(1 / 24)  # 粗略地控制播放速度。更精确的方式是使用游戏编程里,精灵的概念
        finally:
            # curses 使用前要初始化,用完后无论有没有异常,都要关闭
            curses.endwin()
            # print(1)


video_path = './1532448544946410.mp4'
a = Transfer()
a.setVideo(video_path).run()

上面的代码直接粘贴,视频可以用自己的,但是要注意调整尺寸,手机录的分辨率太高,控制台驾驭不了

b = trans.resize(a, (64, 64),1,None,0,True,True,None,None)

这行代码里面的(64,64)就是resize后的尺寸

执行的话最好在控制台操作,不要直接在IDE里面运行

下图所示分别为原视频截图和字符动画截图

很晚了,要猝死了,今天先到这,后续再研究其他的吧

猜你喜欢

转载自blog.csdn.net/liangxun0712/article/details/81194948