1. 程式人生 > >一段蛋疼的程式碼:超不清視訊播放器

一段蛋疼的程式碼:超不清視訊播放器

今天分享的這段程式碼,看起來沒啥實際用處,而且有些反潮流,因為現如今大家看視訊都追求更高解析度的超清畫質,而我們這個,是一個“超不清”的視訊播放器

在控制檯裡播放視訊,用字元來表示畫面

不過我覺得它至少可以有三個作用: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)

程式碼不長,稍微解釋下其中幾處:

  1. ascii_char 這個字元序列並不是必須這樣,只要大致上滿足其中的字元看起來從深到淺即可,字元越多越準確,效果就越好。

  2. 讀取視訊使用了 opencv-python,並直接用它提供的方法轉了灰度圖,在之前的文章中也有過介紹:OpenCV-Python,計算機視覺開發利器

  3. resize 這一步比較重要,因為有的視訊解析度很高,直接一個畫素轉一個字元的話量太大,所以先縮小圖片。另一個原因是字元一般都不是正方形,所以在圖片長寬比上要做一定的調,這樣最終效果比較好。(實際中要根據你自己控制檯中的字型效果來調整縮放比例)

  4. ascii_char[int(pixel / 256 * char_len)] 是整個轉換的核心,因為一個畫素的顏色範圍是 0~255,通過 pixel / 256 * char_len 可以將一個畫素值對應於字元序列中灰度相當的字元

  5. 關於輸出,有幾個值得注意的點:輸出一幀前需要清屏,不同平臺命令有區別;時間間隔、控制檯的字型大小、縮放比例都要根據實際情況作調整;如果計算時間過長、重新整理太慢而螢幕閃爍,可以考慮進一步縮小圖片,或者先將所以幀轉換完畢後再統一輸出。