年輕人不講武德,竟用Python讓馬老師表演閃電五連鞭!

11月份的頭條,是屬於馬保國的。
html


一位69歲的老同志,慘遭年輕人偷襲,不講武德。
python



看看把老同志欺負的...git


要不是馬老師講仁義講道德,甩手就是一個五連鞭。web



哈哈哈,因此本期咱們就用Python給馬保國老師作一個閃電五連鞭動態詞雲圖
api


詞雲數據來自B站,使用stylecloud詞雲庫繪製。
瀏覽器



主要參考百度AI Studio上的一個開源項目,使用PaddleSeg對人像進行分割。微信


年輕小F不講武德這樣好嗎耗子尾汁app



/ 01 / 彈幕數據獲取ide


沒從B站上直接爬取,使用第三方庫bilibili_api函數


這是一個用Python寫的調用Bilibili各類API的庫,範圍涵蓋視頻、音頻、直播、動態、專欄、用戶、番劇等。


地址:https://passkou.com/bilibili_api/docs/


使用video模塊下面的兩個方法,能夠獲取11月天天的視頻彈幕。



首先須要獲取SESSDATACSRF(bili_jct)的值。


谷歌瀏覽器能夠經過下圖查看,域名選擇bilibili.com。



以點擊量爲排序,選取排行第一的視頻獲取彈幕。沒想到馬老師老早就火了,耗子尾汁。



點擊排名第一的視頻,而後在瀏覽器的訪問欄獲取BV號,BV1HJ411L7DP。


獲取彈幕代碼以下。


from bilibili_api import video, Verify
import datetime

# 參數
verify = Verify("你的SESSDATA值""你的bili_jct值")

# 獲取存在歷史彈幕的日期列表
days = video.get_history_danmaku_index(bvid="BV1HJ411L7DP", verify=verify)
print(days)

# 獲取彈幕信息,並保存
for day in days:
    danmus = video.get_danmaku(bvid="BV1HJ411L7DP", verify=verify, date=datetime.date(*map(int, day.split('-'))))
    print(danmus)

    f = open(r'danmu.txt''a')
    for danmu in danmus:
        print(danmu)
        f.write(danmu.text + '\n')
    f.close()


獲得結果。



我大E了啊,沒有閃。


使用jieba對彈幕數據進行分詞處理


import jieba
def get_text_content(text_file_path):
    '''
    獲取填充文本內容
    '''

    text_content = ''
    with open(text_file_path, encoding='utf-8'as file:
        text_content = file.read()
    # 數據清洗,只保存字符串中的中文,字母,數字
    text_content_find = re.findall('[\u4e00-\u9fa5a-zA-Z0-9]+', text_content, re.S)
    text_content = ' '.join(jieba.cut(str(text_content_find).replace(" """), cut_all=False))
    print(text_content)
    return text_content


text_content = get_text_content('danmu.txt')


選取馬保國原版素材視頻,B站上有高清的。


地址:https://www.bilibili.com/video/BV1JV41117hq


參考網上的資料,運行以下代碼便可下載B站視頻


from bilibili_api import video, Verify
import requests
import urllib3

# 參數
verify = Verify("你的SESSDATA值""你的bili_jct值")

# 獲取下載地址
download_url = video.get_download_url(bvid="BV1JV41117hq", verify=verify)
print(download_url["dash"]["video"][0]['baseUrl'])

baseurl = 'https://www.bilibili.com/video/BV1JV41117hq'
title = '馬保國'


def get_video():
    urllib3.disable_warnings()

    headers = {
        'user-agent''Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36',
        'Accept''text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
        'Accept-Encoding''gzip, deflate, br',
        'Accept-Language''zh-CN,zh;q=0.9,en;q=0.8'
    }
    headers.update({'Referer': baseurl})
    res = requests.Session()
    begin = 0
    end = 1024 * 1024 - 1
    flag = 0

    temp = download_url

    filename = "./" + title + ".flv"
    url = temp["dash"]["video"][0]['baseUrl']
    while True:
        headers.update({'Range''bytes=' + str(begin) + '-' + str(end)})
        res = requests.get(url=url, headers=headers, verify=False)
        if res.status_code != 416:
            begin = end + 1
            end = end + 1024 * 1024
        else:
            headers.update({'Range': str(end + 1) + '-'})
            res = requests.get(url=url, headers=headers, verify=False)
            flag = 1
        with open(filename, 'ab'as fp:
            fp.write(res.content)
            fp.flush()
        if flag == 1:
            fp.close()
            break

    print('--------------------------------------------')
    print('視頻下載完成')
    filename = "./" + title + ".mp3"
    url = temp["dash"]["audio"][0]['baseUrl']
    while True:
        headers.update({'Range''bytes=' + str(begin) + '-' + str(end)})
        res = requests.get(url=url, headers=headers, verify=False)
        if res.status_code != 416:
            begin = end + 1
            end = end + 1024 * 1024
        else:
            headers.update({'Range': str(end + 1) + '-'})
            res = requests.get(url=url, headers=headers, verify=False)
            flag = 1
        with open(filename, 'ab'as fp:
            fp.write(res.content)
            fp.flush()
        if flag == 1:
            fp.close()
            break

    print('音頻下載完成')


記得添加SESSDATA和CSRF(bili_jct)的值



/ 02 / PaddleSeg人像分割


基於百度AI Studio的項目,項目地址:


https://aistudio.baidu.com/aistudio/projectdetail/1176398


首先下載解壓安裝PaddleSeg相關依賴包。


# 下載PaddleSeg
git clone https://hub.fastgit.org/PaddlePaddle/PaddleSeg.git

cd PaddleSeg/

# 安裝所需依賴項
pip install -r requirements.txt


一般去「GitHub」上下載東西,速度都比較慢,可使用加速連接。


這裏的fastgit.org一加,下載速度就能從幾十K飆升到幾兆每秒。


# 新建文件夾
mkdir work/videos
mkdir work/texts
mkdir work/mp4_img
mkdir work/mp4_img_mask
mkdir work/mp4_img_analysis


新建一些文件夾,主要用來存放相關文件的。


這裏能夠將以前爬取到的視頻和音頻放置在videos中。


先對素材視頻進行抽幀,就是獲取視頻每幀的圖片。


def transform_video_to_image(video_file_path, img_path):
    '''
    將視頻中每一幀保存成圖片
    '''

    video_capture = cv2.VideoCapture(video_file_path)
    fps = video_capture.get(cv2.CAP_PROP_FPS)
    count = 0
    while (True):
        ret, frame = video_capture.read()
        if ret:
            cv2.imwrite(img_path + '%d.jpg' % count, frame)
            count += 1
        else:
            break
    video_capture.release()

    filename_list = os.listdir(img_path)
    with open(os.path.join(img_path, 'img_list.txt'), 'w', encoding='utf-8'as file:
        file.writelines('\n'.join(filename_list))

    print('視頻圖片保存成功, 共有 %d 張' % count)
    return fps


input_video = 'work/videos/Master_Ma.mp4'
fps = transform_video_to_image(input_video, 'work/mp4_img/')


一共是獲取到了564張圖片。



而後使用PaddleSeg將全部的視頻圖片,進行人像分割,生成mask圖片。


# 生成mask結果圖片
python 你的路徑/PaddleSeg/pdseg/vis.py \
           --cfg 你的路徑/work/humanseg.yaml \
           --vis_dir 你的路徑/work/mp4_img_mask


使用模型進行預測,其中humanseg.yaml文件是做者提供的,能夠進行圖像分割。


訓練模型deeplabv3p_xception65_humanseg,需下載解壓安裝放在PaddleSeg/pretrained_model下。


因爲預訓練模型較大,就不放網盤上了,直接訪問下面這個連接便可下載。


# 下載預訓練模型deeplabv3p_xception65_humanseg
https://paddleseg.bj.bcebos.com/models/deeplabv3p_xception65_humanseg.tgz


記得須要將humanseg.yaml文件中的路徑信息,修改爲你本身的路徑。



運行上面那三行命令,最後就會生成564張mask文件。




/ 03 / 詞雲生成


使用stylecloud詞雲庫生成詞雲,使用字體方正蘭亭刊黑。


def create_wordcloud():
    for i in range(564):
        file_name = os.path.join("mp4_img_mask/", str(i) + '.png')
        # print(file_name)
        result = os.path.join("work/mp4_img_analysis/"'result' + str(i) + '.png')
        # print(result)
        stylecloud.gen_stylecloud(text=text_content,
                                  font_path='方正蘭亭刊黑.TTF',
                                  output_name=result,
                                  background_color="black",
                                  mask_img=file_name)


由於stylecloud庫沒法自定義詞雲圖片,因此小F修改了它的代碼。


給gen_stylecloud添加了mask_img這個參數,最終做用在gen_mask_array這個函數上。


如此就能將mask圖片轉化成詞雲圖!



將這些詞雲圖片合併成視頻。


def combine_image_to_video(comb_path, output_file_path, fps=30, is_print=False):
    '''
        合併圖像到視頻
    '''

    fourcc = cv2.VideoWriter_fourcc(*'mp4v')

    file_items = [item for item in os.listdir(comb_path) if item.endswith('.png')]
    file_len = len(file_items)
    # print(comb_path, file_items)
    if file_len > 0:
        print(file_len)
        temp_img = cv2.imread(os.path.join(comb_path, file_items[0]))
        img_height, img_width, _ = temp_img.shape

        out = cv2.VideoWriter(output_file_path, fourcc, fps, (img_width, img_height))

        for i in range(file_len):
            pic_name = os.path.join(comb_path, 'result' + str(i) + ".png")
            print(pic_name)
            if is_print:
                print(i + 1'/', file_len, ' ', pic_name)
            img = cv2.imread(pic_name)
            out.write(img)
        out.release()


combine_image_to_video('work/mp4_img_analysis/''work/mp4_analysis.mp4'30)


使用ffmpeg對視頻進一步的處理,裁剪+重疊。


# 視頻裁剪
ffmpeg  -i  mp4_analysis_result.mp4  -vf  crop=iw:ih/2:0:ih/5  output.mp4

# 視頻重疊
ffmpeg -i output.mp4 -i viedeos/Master_Ma.mp4 -filter_complex "[1:v]scale=500:270[v1];[0:v][v1]overlay=1490:10" -s 1920x1080  -c:v libx264 merge.mp4

# 添加音頻
ffmpeg -i merge.mp4 -i  videos/Master_Ma.mp4 -c:v copy -c:a copy work/mp4_analysis_result2.mp4 -y

# 生成gif圖
ffmpeg -ss 00:00:22 -t 3 -i merge.mp4 -r 15 a.gif


ffmpeg的安裝及使用就得靠大夥本身百度啦~


視頻結果以下。



到這裏了,不給小F來個贊嗎,來,炫,來偷吸,我這...



/ 04 / 總結


好了,到此本期的實踐就結束了。


相關代碼及文件已上傳,公衆號回覆「1130」便可獲取


感興趣的小夥伴也能夠動手試一試。


這裏須要注意,在使用PaddleSeg進行人像分割和生成詞雲圖,這期間耗費的時間比較多,慢慢等就行了。


還有就是能夠本身修改一下stylecloud庫的代碼,自定義一下mask_img圖片的大小以及顏色


這兩項小F是沒有修改的,因此生成的圖片是512×512尺寸,致使最後視頻須要裁剪。


顏色主要是將mask圖片變成白底的圖片,小F這裏是黑底的。


能夠經過圖片灰度二值化的方法。


import cv2

# 灰度圖
img = cv2.imread('work/mp4_img_mask/240.png'0)

# 二值化
ret, thresh = cv2.threshold(img, 30255, cv2.THRESH_BINARY_INV)

# 顯示
cv2.imshow("img", thresh)
# 保存圖片
cv2.imwrite('0.png', thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()


就能獲得白底的png圖,符合stylecloud詞雲圖的要求


如此即可以繪製出白底彩色文字的詞雲圖。


萬水千山老是情,點個  👍  行不行。



-END-




掃碼添加早小起

1. 回覆「進羣」進入Python技術交流羣

2. 回覆「Python」得到Python技術圖書

3. 回覆「習題」領取Python數據處理200題





本文分享自微信公衆號 - 早起Python(zaoqi-python)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索