視頻轉字符動畫(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裏面運行

下圖所示分別爲原視頻截圖和字符動畫截圖

很晚了,要猝死了,今天先到這,後續再研究其他的吧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章