讓程式碼和邁克傑克遜一起跳舞

Python知識圈發表於2019-02-27

此文首發於公眾號「Python知識圈」,歡迎直接去公眾號看

“ 閱讀文字大概需要 3 分鐘

還記得讀高中時,有一次和同學一次去網咖上網,他讓我看一個視訊,是 Michael Jackson 的前傾 45° 的動作,當時覺得舞蹈還可以這樣跳,太炫酷了。那時在網咖看了 2 小時 MJ 的舞蹈。此後就迷上了 MJ,迷上了他的太空步,迷上了他的機械舞,迷上了他的超強節奏律動的歌曲,成為了小小的 MJFans。那時為了備戰高考,我和這位同學一起在學校附近住了一間房間,那時鎮上的房租也很便宜。學習累了,就一起在 MJ 的歌曲中練練太空步,樂此不疲。

大學期間,我還在宿舍沒人時自己偷偷看視訊練習 MJ 的舞蹈 dangerous,可惜自己基礎太差,上不了檯面,上臺表演的夢想只好作罷。

如今都畢業幾年了,手機也換得頻繁,但手機裡總會有 MJ 的歌,累了乏了就會聽聽,邊聽邊跟著節奏一起打著節拍,聽完之後感覺全身又充滿了力量。看到有些視訊軟體上有人釋出了 MJ 的視訊,也總會忍不住點進去看看。

最近看到一個有意思的程式:ffmpeg。它是一套可以用來記錄、轉換數字音訊、視訊,並能將其轉化為流的開源計算機程式。可以用來把視訊轉化為圖片,在用 PIL 庫把圖片處理成編碼,這樣編碼就可以和 MJ 視訊一起律動起來了。

說幹就幹,首先開啟之前收集的 MJ 的視訊,把那些背景干擾比較少的鏡頭剪下下來處理。這個工作是個苦差,因為 MJ 的舞蹈視訊基本都在演唱會上,背景比較多,效果不是太明顯,再加上之前也很少用這些視訊處理軟體。弄了大半天總算拼了兩段稍微好點的,配上了自己剪下的音樂。

這裡不好上傳本地視訊,視訊在公眾號裡可看,有興趣的通過下方進入公眾號去觀看,這裡放兩張截圖看看。

讓程式碼和邁克傑克遜一起跳舞
讓程式碼和邁克傑克遜一起跳舞

專案環境

語言: Python3
工具:Pycharm

工具準備

ffmpeg,剛才說的處理視訊的程式,可去官網下載https://www.ffmpeg.org/download.html#build-windows,我的電腦是windows 64 位的,和我一樣系統的話也可以公眾號回覆「ff」獲取。

PIL 包:Python 的圖形處理庫。
numpy 包:Python 的一種開源的數值計算擴充套件,可用來儲存和處理大型矩陣。

程式結構

我寫了三個 py 檔案,一個用來把視訊轉換為圖片,一個用來把圖片轉為編碼,最後一個來做最後的執行。

視訊處理

下面的 ffmpeg 程式後面的幾個引數我解釋一下,-i 後面需要指定輸入的檔名。-f 指定格式(音訊或視訊格式)。-vframes 設定轉換多少楨(frame)的視訊。-ss 從指定的時間(s)截圖。

def getImage(videoPath, imagePath):
    img_count = 1
    crop_time = 0.0
    while crop_time <= 15.0:
        os.system(`ffmpeg -i %s -f image2 -ss %s -vframes 1 %s.png`% (videoPath, str(crop_time), imagePath + str(img_count)))
        img_count += 1
        print(`Geting Image ` + str(img_count) + `.png` + ` from time ` + str(crop_time))
        crop_time += 0.1
    print(`圖片收集結束!!!`)
複製程式碼

用這個函式獲取視訊的每幀圖片,給出的視訊存放路徑和獲取圖片的路徑呼叫此函式就可以獲取視訊每幀的圖片,我設定了每 0.1 秒儲存一張圖片。

圖片轉換

用 convert(`L`) 把圖片轉換為為二值影像,非黑即白。但是它每個畫素用 8 個bit 表示,0 表示黑,255 表示白。

def image2txt(inputFile, outputFile):
    im = Image.open(inputFile).convert(`L`)
    charWidth = 100
    im = im.resize((charWidth, charWidth // 2))
    target_width, target_height = im.size
    data = numpy.array(im)[:target_height, :target_width]
    f = open(outputFile, `w`,encoding=`utf-8`)
    for row in data:
        for pixel in row:
            if pixel > 127:
                f.write(`1`)
            else:
                f.write(` `)
        f.write(`
`)
    f.close() 
複製程式碼

執行這個函式不會有資料返回,用下一個 go.py 檔案匯入呼叫才行。

控制輸出

呼叫上個函式 image2txt,圖片轉換為編碼。

def getTxt(imagePath, txtPath):
    img_count = 1
    while img_count <= len(os.listdir(imagePath)):
        imageFile = imagePath + str(img_count) + `.png`
        txtFile = txtPath + str(img_count) + `.txt`
        image2txt.image2txt(imageFile, txtFile)
        print(`MJ舞蹈載入中: ` + str(img_count) + `%`)
        img_count += 1
複製程式碼

通過 os.system(`cls`) 控制螢幕的及時清除,以便及時顯示下一幀圖片的編碼。

def play(txtPath):
    txt_count = 1
    while txt_count <= len(os.listdir(txtPath)):
        os.system(`type ` + txtPath + str(txt_count) + `.txt`)
        txt_count += 1
        os.system(`cls`)
複製程式碼

給出編碼檔案路徑和圖片路徑,執行函式。

txt_dir_path = r`D:MJmjtxt` + `\`
img_dir_path = r`D:MJmjimages` + `\`
getTxt(img_dir_path, txt_dir_path)
play(txt_dir_path)
複製程式碼

收集完視訊圖片後在 cmd 控制檯執行 go.py 檔案,編碼出現後點選視訊播放就能達到剛才視訊中的效果了。

你們可以用自己的視訊去做,視訊背景固定的話效果更好。

在公眾號回覆「MJ」獲取原始碼。

寫在最後

方法教給大家了,視訊素材可以優化,大家可以自己收集好的視訊素材,發到朋友圈,讓程式碼騷動起來!覺得有意思的話希望大家能多給點支援,該關注關注,該點贊點贊,該轉發轉發,有什麼問題歡迎在後臺聯系我,也可以在後臺加入技術交流群,群裡有大神,可以一起交流學習。

推薦閱讀:

用 Python 玩微信,機器人陪你嘮嗑

這篇文章帶你輕鬆入門 python 爬蟲

讓程式碼和邁克傑克遜一起跳舞

「Python知識圈」公眾號專注:

1.python 技術分享

2.python 爬蟲分享

3.資料、工具共享

歡迎關注我們,一起成長!

相關文章