很無聊地做了一個視訊轉字元圖的Python代碼,把最近火的一趟糊塗的蔡徐坤轉成字元圖像。
效果可以看這裡
https://www.bilibili.com/video/av50295619/www.bilibili.com
思路很簡單,借助OpenCV讀取視訊提取圖像,圖像轉灰階圖,再量化,根據量化值取字元。
代碼及注釋如下:
import cv2
import time
import numpy as np
import curses
# pixel後面4位都是空格,代表像素值比較大的
# 近似白色背景
pixels = " .,-'`:!1+*% "
def get_images(video_name, size):
'''
視訊幀分解
圖像轉灰階圖,再縮放
:param video_name:
:param size:
:return: 灰階圖清單
'''
img_list = []
cap = cv2.VideoCapture(video_name)
while cap.isOpened():
ret, frame = cap.read()
if ret:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
img = cv2.resize(gray, size, interpolation=cv2.INTER_AREA)
img_list.append(img)
else:
break
cap.release()
return img_list
def img_2_char(img):
'''
灰階圖像映射成字元[0,255] -> [0,16]
用[0,16]索引值取字元
:param img:
:return: 字元數組
'''
ret = []
p = img / 255
indexes = (p * (len(pixels) - 1)).astype(np.int)
height, width = img.shape
for row in range(height):
line = ""
for col in range(width):
index = indexes[row][col]
line += pixels[index] + " "
ret.append(line)
return ret
def video_2_char(img_list):
'''
圖像清單 轉換成 字元圖清單
:param img_list:
:return:
'''
video_char = []
for img in img_list:
pic = img_2_char(img)
video_char.append(pic)
return video_char
def play_video(video_char):
width, height = len(video_char[0][0]), len(video_char[0])
stdscr = curses.initscr()
curses.start_color()
try:
stdscr.resize(height, width * 2)
for pic_i in range(len(video_char)):
for line_i in range(height):
# 将pic_i的第i行寫入第i列。(line_i, 0)表示從第i行的開頭開始寫入。最後一個參數設定字元為白色
stdscr.addstr(line_i, 0, video_char[pic_i][line_i], curses.COLOR_WHITE)
stdscr.refresh() # 寫入後需要refresh才會立即更新界面
time.sleep(1 / 24)
finally:
curses.endwin()
if __name__ == "__main__":
imgs = get_images('c:videokun.mp4', (64, 40))
video_chars = video_2_char(imgs)
play_video(video_chars)
注意事項:
進入指令行控制台,使用pip install opencv-python 安裝cv2
http://www.lfd.uci.edu/~gohlke/pythonlibs/#curses
下載下傳curses, 然後用 pip install 檔案名.whl 安裝curses
pip install numpy 安裝numpy
最後,運作程式時,務必在指令行裡敲入: python 腳本名.py
厚臉皮 一波
凱威講堂www.kaiweitalk.com