今天刷抖音,看到了一個《極樂淨土》的字符動畫,舞蹈看起來妖嬈啊,滿屏幕的字符勾勒出美女的身影,在配上極樂淨土的音樂,簡直是程序員們的精神食糧啊!!!!
以前也遇到過這種字符動畫,當時簡單想了想,大概就是控制檯的字符輸出刷新,再輸出什麼的吧,只是覺得所有字符手擼太累了,就沒深入思考,今天看到這個《極樂淨土》中途壓制不住內心的衝動,要自己動手來一個了。
關於原理什麼的,這篇文章介紹的比較多,我就不多贅述了,也感謝這位老哥提供思路,不然這麼久的python圖像處理感覺白玩了
該教程基於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裏面運行
下圖所示分別爲原視頻截圖和字符動畫截圖
很晚了,要猝死了,今天先到這,後續再研究其他的吧