Python20行代碼實現視頻字符化


Python20行代碼實現視頻字符化

我們經常在B站上看到一些字符鬼畜視頻,主要就是將一個視頻轉換成字符的樣子展現出來。看起來是非常高端,但是實際實現起來確實非常簡單,我們只需要接觸opencv模塊,就能很快的實現視頻字符化。但是在此之前,我們先看看我們實現的效果是怎樣的:

在這裏插入圖片描述

上面就是截取的一部分效果圖,下面開始進入我們的主題。

一、OpenCV的安裝及圖片讀取

在Python中我們只需要用pip安裝即可,我們在控制檯執行下列語句:

pip install opencv-python

安裝完成就可以開始使用。我們先讀取一個圖片:

import cv2
im = cv2.imread('jljt')    # 讀取圖片
cv2.imshow('im', im)    # 顯示圖片
cv2.waitKey(0)    # 等待鍵盤輸入
cv2.destroyAllWindows()    # 銷燬內存

首先我們使用cv2.imread方法讀取圖片,該方法返回一個ndarray對象。然後調用imshow方法顯示圖像,調用後會出現一個窗口,因爲這個窗口只會出現一瞬間,所以我們調用waitKey等待輸入,傳入0表示無限等待。因爲opencv是使用c++編寫的,所以我們需要銷燬內存。

二、OpenCV中的一些基礎操作

我們將視頻字符化的思路就是先將視頻轉換爲一幀一幀的圖像,然後對圖像進行字符化處理,最後展示出來就是字符視頻的效果了。在我們生成字符畫之前,我們還要看一些OpenCV的操作。

(1)灰度轉換

灰度處理是一個非常常用的操作,我們原始的圖片是有BGR三個圖層(在OpenCV中,圖像是以BGR形式讀取)。我們進行灰度處理直觀上看就是將圖片變成黑白,而本質上是將圖片的三個圖層通過計算,變成一個圖層。而這種計算是不需要我們做的,我們只需要調用OpenCV中的函數即可:

import cv2
# 讀取圖片
im = cv2.imread('jljt.jpg')
# 灰度轉換
grey = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)

效果圖和原圖對比如下:

左邊爲原圖,右邊爲灰度轉換後的圖像。

(3)改變圖片大小

因爲字符化後圖像會比較大,所以我們需要先縮小圖片,我們調用cv2.resize即可改變圖像大小:

import cv2
# 讀取圖像
im = cv2.imread('jljt.png')
# 改變圖像大小
re = cv2.resize(im, (100, 40))
cv2.imshow('11', re)
cv2.waitKey(0)
cv2.destroyAllWindows()

(2)逐幀讀取視頻

我們可以通過VideoCapture讀取視頻,然後調用其中的方法讀取每一幀。

import cv2
# 讀取視頻
video = cv2.VideoCapture('jljt.mp4')
# 讀取幀,該方法返回兩個參數,第一個爲是否還有下一幀,第二個爲幀的ndarray對象
ret, frame = video.read()
while ret:
    # 循環讀取幀
    ret, frame = video.read()

有了上面的操作,我們就可以開始我們下一步的工作了。

三、圖片字符化

對於只有一個通道的圖片,我們可以把它當成一個矩形,這個矩形最小單位就是一個像素。而字符化的過程就是用字符替代像素點的過程。所以我們要遍歷圖像的每個像素點,但是我們應該用什麼字符取代呢?

我們顏色有一個參照表,而opencv將這個參數表切割成256份,代表不同的程度,我們也可以做一個參照表,不過表中的內容不是顏色,而是字符。

顏色表

上圖爲顏色表,我們可以使顏色表和字符表建立映射關係。假如字符表如下:

mqpka89045321@#$%^&*()_=||||}

我們可以得到下列公式:

顏色和字符之間的等式

經過變換可以求得相應顏色對應字符表中的字符:

獲取字符在字符表中的位置

這個公式不理解也沒關係,只需要會用即可。下面就是我們完整的代碼了:

import cv2
str = 'mqpka89045321@#$%^&*()_=||||}' # 字符表
im = cv2.imread('jljt.jpg')    # 讀取圖像
grey = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)    # 灰度轉換
grey = cv2.resize(grey, (50, 18))    # 縮小圖像
str_img = ''    # 用於裝字符畫
for i in grey:    # 遍歷每個像素
    for j in i:
        index = int(j / 256 * len(str))    # 獲取字符座標
        str_img += str[index]    # 將字符添加到字符畫中
    str_img += '\n'
print(str_img)

生成如下字符畫:

字符畫

因爲尺寸比較小的關係,看出來的效果不是很好,我們調節好大小就好了。

四、視頻轉字符

我們知道圖片轉字符,自然視頻轉字符就不是什麼問題了,我們只需要在逐幀讀取中執行圖片字符化操作即可。

import os
import cv2
str = 'mqpka89045321@#$%^&*()_=||||}'    # 字符表
video = cv2.VideoCapture('jljt.mp4')     # 讀取視頻
ret, frame = video.read()    # 讀取幀
while ret:    # 逐幀讀取
    str_img = ''    # 字符畫
    grey = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)    # 灰度轉換
    grey = cv2.resize(grey, (100, 40))    # 該表大小
    for i in grey:    # 遍歷每個像素點
        for j in i:
            index = int(j / 256 * len(str))    # 獲取字符座標
            str_img += str[index]    # 將字符添加到字符畫中
        str_img += '\n'
    os.system('cls')    # 清除上一幀輸出的內容
    print(str_img)    # 輸出字符畫
    ret, frame = video.read()    # 讀取下一幀
    cv2.waitKey(5)

這樣我們就會每個5毫秒執行一幀畫面,在我們使用pycharm執行時,會發現並沒有執行清屏操作,所以我們需要到命令行運行。最終效果就是我們的字符視頻了:

最終效果

在選取字符表時我們需要注意主體的顏色,如果主體顏色較淺,則字符表的尾部應該爲一些複雜字符,如:$%#@&。字符表頭部爲一些簡單字符,如:-|/等。如果主體顏色較深,而背景顏色較淺,則反之。當然這沒有唯一的標準,大家可以慢慢調節。感興趣的讀者,可以關注我的個人公衆號:ZackSock,看到摳鼻屎的就是我沒錯了。

     精 彩 文 章 

END
最後說個題外話,相信大家都知道視頻號了,隨着灰度範圍擴大,越來越多的小夥伴都開通了視頻號。小詹也開通了一個視頻號,會分享互聯網那些事、讀書心得與副業經驗,歡迎掃碼關注,和小詹一起向上生長!「沒有開通發佈權限的儘量多互動,提升活躍度可以更快開通哦」

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章