一段蛋疼的代碼:超不清視頻播放器

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

在控制檯裏播放視頻,用字符來表示畫面

不過我覺得它至少可以有三個作用:1.用來練習視頻和圖像處理的編程開發;2.在沒有圖形界面的服務器上播放視頻(雖然效果不咋地);3.作爲一種獨特的藝術風格化處理

程序的原理其實很簡單,關鍵是你要理解計算機中一張圖像的組成:一堆像素點。我們平常說的 1920*1080 之類的分辨率,也就是指這個像素點的多少。我們想做成字符畫,也就是考慮如何用不同的字符來表示一個像素。

通常一個像素點由3個0~255的值表示,分別表示紅、綠、藍三種顏色值,值越大表示顏色越深。但字符畫是沒有顏色的,所以需要將圖像轉成灰度圖,這樣就可以跟一組從深到淺的字符形成一種對應關係。比如深的點就是 @,淺色的點就是 .。

一幅圖像全部轉成字符序列後,就可以直接在控制檯輸出了。對於一個視頻來說,只需要將每一幀都轉換後輸出,並按照一定的時間間隔清屏、輸出下一幀,即可達到我們的需要的效果。

轉換後的效果:

代碼:

# coding: utf8
import cv2 as cv
import os
import time
# 替換字符列表
ascii_char = list(r"$@B%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. 關於輸出,有幾個值得注意的點:輸出一幀前需要清屏,不同平臺命令有區別;時間間隔、控制檯的字體大小、縮放比例都要根據實際情況作調整;如果計算時間過長、刷新太慢而屏幕閃爍,可以考慮進一步縮小圖片,或者先將所以幀轉換完畢後再統一輸出。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章