這篇博客是我看到一個視頻,使用python實現的一個趣味代碼,然後就自己嘗試實現了一下,以此記錄一下整個過程。
主要實現的內容就是使用mmfpeg這個工具,實現對視頻的讀取,然後從視頻中按照一定的幀率提取出來照片,再將這些照片轉化為灰度圖像,設定合適的阈值,找到符合阈值的灰度值的位置。
首先給大家看一下結果,然後再一步一步說明怎麼實現的:
1. 這是在網上找的一個GIF圖,然後轉成MP4視頻
2. 運行結果如下(博客好像不能插入視頻,我就截了幾張圖):
前期准備:
首先要下載ffmpeg,這裡只說Windows下的方式(linux不難),首先去官網,下載Windows版本的安裝包
下載完成後,解壓,放到你喜歡的位置,然後找到目錄下的bin文件夾,將該目錄放到你的環境變量中(如何配置環境變量這裡不細說,百度之。)
之後就是測試一下有沒有配置成功,打開你的cmd
,輸入ffmpeg -version
,輸出以下東西,就是成功了
目錄結構
我們的思路是視頻——>圖片——>txt文件,再“播放”這些txt文件。所以在你的工作目錄下要放2個文件夾image
和txt
,分別存放圖像和txt文件,看一下我的目錄
test.py
文件就是我們要寫的python文件了。
我們有三個函數,分別實現視頻轉圖片,圖片轉txt,和main函數。
首先第一個函數get_image(video_path, image_path)
,兩個參數就是你的視頻路徑和存放圖片的路徑。變量frame
是用來決定你將每一秒視頻轉化為多少張圖片的參數。然後os.system()那句話就是讓你的Windows在cmd裡面執行裡面那句話,大致的意思就是以10幀每秒的頻率提取該視頻的圖片,保存到你的目錄。具體用法可以百度ffmpeg,這個有點麻煩,就不細說了。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
from PIL import Image # 如果沒有該庫,請 pip install PIL
import numpy # 如果沒有該庫,請 pip install numpy
frame = 10 # 每秒10幀, 即一秒十張
def get_image(video_path, image_path):
try:
os.system('ffmpeg -i {0} -r {1} -f image2 {2}\%05d.png'.format(video_path, frame, image_path))
except:
print('ERROR !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
然後我們提取到了圖片,去image
文件夾下去看,可以看到很多圖片
接下來,是將圖片轉化為txt文件,寫的函數是image_to_txt(image_path, txt_path)
,這裡的兩個參數分別是你讀取圖片的路徑和存放txt文件的路徑,代碼解釋放在注釋當中了。
def image_to_txt(image_path, txt_path):
txt_count = 1 # 用於命名txt文件
fileList = os.listdir(image_path) # 返回所有圖片名稱,是個字符串列表
for file in fileList: # 遍歷每一張圖片
img = Image.open(image_path + '\\'+ file).convert('L')
# 這裡使用到PIL庫convert函數,將RGB圖片轉化為灰度圖,參數'L'代表轉化為灰度圖
charWidth = 140
# 這個是設置你後面在cmd裡面顯示內容的窗口大小,請根據自己的情況,適當調整值
img = img.resize((charWidth, 40))
target_width, target_height = img.size
data = numpy.array(img)[:target_height, :target_width]
# 使用numpy庫,將圖像轉化為數組
with open(txt_path + '\\' + str(txt_count) + '.txt', 'w', encoding='utf-8') as f:
txt_count += 1 # 一張圖對應一個txt文件,所以每遍歷一張圖,該值加一
for row in data:
for pixel in row:
if pixel < 127: # 如果灰度值小於127,也就是偏黑的,就寫一個字符 '*'
f.write('*')
else:
f.write(' ')
f.write('\n')
這是txt
文件夾的結果:
最後就是,一個run(txt_path)
函數,用於“播放”這些txt文件,同樣的參數是txt文件的路徑
def run(txt_path):
fileList = os.listdir(txt_path)
for i in range(1, len(fileList)+1): # 遍歷所有的txt文件
try:
os.system('type ' + txt_path + '\\' + str(i) + '.txt')
# 這裡type命令是Windows下的命令,相信很多人沒怎麼用過,你試一下就知道,type+文件名,就可以在cmd裡面顯示文件內容
os.system('cls')
# 清屏的意思,每顯示一次txt文件,就清屏,然後顯示下一個txt
# 這裡還可以適當的加延時函數,如果顯示的太快的話
except:
print('ERROR !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
最後的最後:讓這三個函數跑起來~~
if __name__ == '__main__':
video_path = r'你的視頻路徑'
image_path = r'你存儲圖片的路徑'
txt_path = r'你存儲txt文件的路徑'
get_image(video_path, image_path)
image_to_txt(image_path, txt_path)
run(txt_path)
這個代碼不具有什麼實用性,純屬有點好玩,再加上可以練習python,沒事的時候可以玩一玩。還有處理的視頻最好是顏色單一的,然後人物形象顏色也要單一,這樣找那個阈值比較好找。所以我這裡直接找了黑白的圖,如果顏色及較多又分散的話,最後的效果也不是很好。
記第一次寫博客,完。