一段蛋疼的程式碼:超不清視訊播放器
今天分享的這段程式碼,看起來沒啥實際用處,而且有些反潮流,因為現如今大家看視訊都追求更高解析度的超清畫質,而我們這個,是一個“超不清”的視訊播放器:
在控制檯裡播放視訊,用字元來表示畫面
不過我覺得它至少可以有三個作用:1.用來練習視訊和影象處理的程式設計開發;2.在沒有圖形介面的伺服器上播放視訊(雖然效果不咋地);3.作為一種獨特的藝術風格化處理
程式的原理其實很簡單,關鍵是你要理解計算機中一張影象的組成:一堆畫素點。我們平常說的 1920*1080 之類的解析度,也就是指這個畫素點的多少。我們想做成字元畫,也就是考慮如何用不同的字元來表示一個畫素。
通常一個畫素點由3個0~255的值表示
一幅影象全部轉成字元序列後,就可以直接在控制檯輸出了。對於一個視訊來說,只需要將每一幀都轉換後輸出,並按照一定的時間間隔清屏、輸出下一幀,即可達到我們的需要的效果。
轉換後的效果:
程式碼:
# coding: utf8 import cv2 as cv import os import time # 替換字元列表 ascii_char = list(r"
[email protected]%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ") char_len = len(ascii_char) # 載入視訊 cap = cv.VideoCapture('video.mp4') while True: # 讀取視訊每一幀 hasFrame, frame = cap.read() if not hasFrame: break # 視訊長寬 width = frame.shape[0] height = frame.shape[1] # 轉灰度圖 img_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) # 縮小圖片並調整長寬比 img_resize = cv.resize(img_gray, (int(width / 10), int(height / 10))) text = '' # 遍歷圖片中的畫素 for row in img_resize: for pixel in row: # 根據畫素值,選取對應的字元 text += ascii_char[int(pixel / 256 * char_len)] text += '\n' # 清屏 os.system('cls') # mac是'clear' # 輸出生成的字元方陣 print(text) # 適當暫停一下 time.sleep(0.03)
程式碼不長,稍微解釋下其中幾處:
-
ascii_char 這個字元序列並不是必須這樣,只要大致上滿足其中的字元看起來從深到淺即可,字元越多越準確,效果就越好。
-
讀取視訊使用了 opencv-python,並直接用它提供的方法轉了灰度圖,在之前的文章中也有過介紹:OpenCV-Python,計算機視覺開發利器
-
resize 這一步比較重要,因為有的視訊解析度很高,直接一個畫素轉一個字元的話量太大,所以先縮小圖片。另一個原因是字元一般都不是正方形,所以在圖片長寬比上要做一定的調整,這樣最終效果比較好。(實際中要根據你自己控制檯中的字型效果來調整縮放比例)
-
ascii_char[int(pixel / 256 * char_len)]
是整個轉換的核心,因為一個畫素的顏色範圍是 0~255,通過pixel / 256 * char_len
可以將一個畫素值對應於字元序列中灰度相當的字元。 -
關於輸出,有幾個值得注意的點:輸出一幀前需要清屏,不同平臺命令有區別;時間間隔、控制檯的字型大小、縮放比例都要根據實際情況作調整;如果計算時間過長、重新整理太慢而螢幕閃爍,可以考慮進一步縮小圖片,或者先將所以幀轉換完畢後再統一輸出。