寫在最前邊:
很長時間沒有來CSDN上來寫博客了,最近看到有位UP主的微信公眾號推出了通過爬取B站上彈幕生成詞云,再將詞云合成小姐姐跳舞的視頻,并且這位博主還給出了實作思路和原始碼,照著那位博主的方法,也最終實作了這個效果,并且在這個實作程序中也學到了不少其他的東西,夜深人靜的時候就做一個總結,權當做一個筆記,
目錄
寫在最前邊:
準備環境:
涉及到的技術:
實作程序:
1. 視頻下載
2. 人像分割
3. 彈幕爬取
4. 分詞與構造詞云
5. 視頻合成
寫在最后:
常見的問題總結:
準備環境:
環境這里實際上是沒有什么問題的,但是微信公眾號上那位博主使用的MACOS系統,所以在具體實作中還是會有一些區別,所以我這里還是交代一下環境:
作業系統:win10
編譯器:anaconda3---------jupyter(base環境下)-------------python3
涉及到的技術:
視頻下載====》人像分割====》python爬蟲(爬取彈幕)====》分詞、詞云====》視頻合成
實作程序:
1. 視頻下載
B站視頻下載的方式有很多,這里我們使用的是you-get工具來進行下載
具體操作:
1.1 安裝好anaconda3以后,打開win運行視窗,輸入cmd回車,進入命令列視窗
1.2 執行 pip install you-get
1.3 安裝成功以后,執行 you-get -i https://www.bilibili.com/video/BV11C4y1h7nX
你可以試著將上邊的這個網址復制在瀏覽器中打開,你所下載的視頻就是這位跳《無價之姐》舞蹈的小姐姐,這里冒一句:我是第一次聽《無價之姐》這歌,聽多了還挺帶勁!
補充:
我剛剛有提到過,實際上下載視頻的方式有很多種,你可以隨意,只要你喜歡,我這里想說的是,也是想對我自己說的,研究一下 bilibili_api 這個庫,挺有意思的庫,因為后來爬取彈幕使用這個庫的話是非常方便的,這里下載B站視頻用它也是可以的,
https://github.com/MoyuScript/bilibili-api/
https://github.com/MoyuScript/bilibili-api/上邊這個網址就是在GitHub上bilibili_api的地址,下邊我把在這個庫里邊關于下載視頻的demo鏈接也放上,
bilibili-api/video.md at main · MoyuScript/bilibili-api · GitHub
https://github.com/MoyuScript/bilibili-api/blob/main/docs/examples/video.md關于視頻的下載,就說到這里,
總之一個目的,獲得小姐姐,不,不是,是獲得小姐姐的跳舞視頻,
1.4 使用opencv將視頻逐幀保存
之前的博主講是他只截取其中的部分視頻然后逐幀進行保存,我這里把整個視頻逐幀保存了,因為實際上也沒有多少圖片,我們大概算一下,這個視頻是3分3秒,也就是183秒,然后按每秒30幀吧,那就是:5490幀,實際上跟我實際中存的幀數也差不多,我最后分下來是5503幀,
print(183*30)
廢話不多講了,我把讀取視頻,然后逐幀保存圖片的代碼奉上:
但是需要注意的是,你得提前在anaconda的作業目錄下創建 dancepictrues 檔案夾,還有如果你發現在匯入cv2的時候報錯的話,那你就是沒有安裝這個庫,你還是直接打開cmd命令列視窗,使用pip install opencv-python 進行安裝,
import cv2
#讀取視頻
cap=cv2.VideoCapture(r"無價之姐~讓我乘風破浪~~~.flv")
#逐幀讀取并且將圖片存在指定檔案夾下的指定檔案
num=1
while 1:
ret,frame=cap.read()
if ret:
cv2.imwrite(f".\dancepictrues\img_{num}.jpg",frame)
num+=1
else:
break
#釋放cap物件
cap.release()
2. 人像分割
這里是直接呼叫百度AI上的人體分析中的影像分割功能(放心,基本屬于白嫖,因為只要注冊成功,你是可以免費呼叫人體分析系列介面10000次),
這里主要涉及兩步:
第一步,注冊百度云賬號,在里邊找一個人工智能的產品,然后找人體分析的模塊,在里邊有一個影像分割的功能,立即使用,然后創建應用,回到應用串列中,這些繁瑣的步驟是干嘛呢?主要是為了獲取到影像分割應用的APP_ID 、API_KEY 、SECRET_KEY
第二步,使用如下代碼,將第一步獲取到的APP_ID 、API_KEY 、SECRET_KEY寫入代碼即可,
對了,在執行代碼之前還是要創建檔案夾mask_img
import cv2
import base64
import numpy as np
import os
from aip import AipBodyAnalysis
import time
import random
#呼叫百度云的人體分割模塊
APP_ID="你的"
API_KEY="你的"
SECRET_KEY="你的"
client=AipBodyAnalysis(APP_ID,API_KEY,SECRET_KEY)
path="./mask_img/"
img_files=os.listdir("./dancepictrues")
print(img_files)
for num in range(1,len(img_files)+1):
img=f"./dancepictrues/img_{num}.jpg"
img1=cv2.imread(img)
height,width,_=img1.shape
with open(img,"rb") as fp:
img_info=fp.read()
seg_res=client.bodySeg(img_info)
labelmap = base64.b64decode(seg_res['labelmap']) # res為通過介面獲取的回傳json
nparr = np.fromstring(labelmap, np.uint8)
labelimg = cv2.imdecode(nparr, 1)
# width, height為圖片原始寬、高
labelimg = cv2.resize(labelimg, (width, height), interpolation=cv2.INTER_NEAREST)
im_new = np.where(labelimg==1, 255, labelimg)
mask_name=path+"mask_{}.png".format(num)
cv2.imwrite(mask_name, im_new)
print(f"=============第{num}張圖分割完成=============")
執行完上邊的命令后你就可以在 mask_img 檔案夾下查看到影像分割完成的圖片了,但是這個程序因為用到了百度第三方的介面,執行速度很慢,而且糟糕的話,可能最后不會把你所有的圖片進行分割,不過這倒無所謂,只要分割一部分就可以了,不是嗎?
3. 彈幕爬取
經過漫長的等待,恭喜你終于來到了第三步,對于從來沒有學習過網站爬取資料的我這個地方著實花費了我很多時間,所以,我會用簡單的方式幫你獲取到彈幕,實際上,也就是獲取到彈幕這個簡單,這里我想吐槽一下之前的博主,使用他的方法理論上是沒有問題的,但是過于復雜、繁瑣,我這里講一個簡單的,
還記得在第一步中提到的 bilibili_api 這個庫嗎?對的,使用簡單的方法就是去呼叫這個庫的video類的獲取彈幕的方法,簡單實用,video類的原始碼我也把地址放在下方,
https://github.com/MoyuScript/bilibili-api/blob/main/bilibili_api/video.py
https://github.com/MoyuScript/bilibili-api/blob/main/bilibili_api/video.py在 video 類中有一個 get_danmakus() 方法,沒錯,就是這個方法,就可以獲得對應視頻的彈幕,執行下邊的代碼就可以獲取到該視頻對應的彈幕,
import asyncio #協程
import nest_asyncio
from bilibili_api import video
import re
import pandas as pd
nest_asyncio.apply()
# BVid(B站視頻編號)、fileName存放彈幕
BVid = "BV11C4y1h7nX"
file_name = 'barrages.txt'
# 獲取彈幕
my_video = video.Video(bvid=BVid)
danmu = await my_video.get_danmakus(cid="211304647")
#danmu.encoding="utf-8"
#資料處理
data = [data.text for data in danmu]
for i in data:
i = re.sub('\s+', '', i)
# #查看數量
print("彈幕數量為:{}".format(len(data)+1))
# 輸出到檔案
df = pd.DataFrame(data)
df.to_csv(file_name, index=False, header=None, encoding="utf_8_sig")
print("寫入檔案成功")
補充:
上邊的代碼中,其中bvid是B站視頻的編號,具體什么機制我也不是很懂,懂的朋友可以評論區里留言,cid是視頻所在專欄編號,
獲取bvid我覺得大家不是問題,因為你在網站看視頻的時候看網址就可以看到,難的就是獲取視頻的cid,其實這個也簡單,只需要執行下邊的代碼就可以,獲取到制定視頻的詳細資訊,當然,還是使用了bilibili_api這個庫,
import asyncio #協程
import nest_asyncio
from bilibili_api import video
nest_asyncio.apply()
# 加上這兩句就不會報錯,主要因為ipthon不支持
# import nest_asyncio
# nest_asyncio.apply()
async def main():
# 實體化 Video 類
v = video.Video(bvid="BV11C4y1h7nX")
# 獲取資訊
info = await v.get_info()
# 列印資訊
print(info)
if __name__ == '__main__':
asyncio.get_event_loop().run_until_complete(main())
在info字典中你會看到幾乎所有關于視頻的資訊,當然也包含我們剛剛提到的cid號
4. 分詞與構造詞云
4.1 分詞的目的在于將比較長的句子分為若干個詞語,例如“我是你的小寶貝”這個句子,可以分為“我是”、“你的”、“小寶貝”,為什么這樣?因為最后生成詞云以后,如果有一些長句子會顯得人體影像不自然不逼真,類似于像素,如果像素點很大很少,最后生成的圖片不細膩,
4.2 繪制詞云使用 wordcloud 庫繪制就好,
實作代碼如下:
from wordcloud import WordCloud
import collections
import jieba
import re
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import os
result_list=[]
#讀取彈幕
with open('barrages.txt') as f:
data = f.read()
#正則,匹配漢字“\u4e00-\u9fa5”表示UNICODE中的漢字編碼范圍
new_data = re.findall('[\u4e00-\u9fa5]+', data , re.S)
new_data = "".join(new_data)
#文本分詞
seg_list_exact = jieba.cut(new_data, cut_all=True)
#將分好的詞存入串列result_list
for word in seg_list_exact:
result_list.append(word)
# 篩選后統計詞頻
word_counts = collections.Counter(result_list)
path = './wordcloud/'
img_files = os.listdir('./mask_img')
for num in range(1, len(img_files) + 1):
img = fr'.\mask_img\mask_{num}.png'
# 獲取蒙版圖片
mask_ = 255 - np.array(Image.open(img))
# 繪制詞云
plt.figure(figsize=(8, 5), dpi=200) #這行代碼貌似多余
my_cloud = WordCloud(
background_color='white', # 設定背景顏色 默認是black
mask=mask_, # 自定義蒙版
mode='RGBA',
max_words=200,
font_path='simhei.ttf', # 設定字體 顯示中文
).generate_from_frequencies(word_counts)
# 顯示生成的詞云圖片
# plt.imshow(my_cloud)
# 顯示設定詞云圖中無坐標軸
#plt.axis('off')
word_cloud_name = path + 'wordcloud_{}.png'.format(num)
my_cloud.to_file(word_cloud_name) # 保存詞云圖片
print(f'======== 第{num}張詞云圖生成 ========')
5. 視頻合成
視頻合成這里使用 opencv庫、moviepy 庫
import cv2
import os
# 輸出視頻的保存路徑
video_dir = 'result.mp4'
# 幀率
fps = 30
# 圖片尺寸
img_size = (1920, 1080)
fourcc = cv2.VideoWriter_fourcc('M', 'P', '4', 'V') # opencv3.0 mp4會有警告但可以播放
videoWriter = cv2.VideoWriter(video_dir, fourcc, fps, img_size)
img_files = os.listdir('.//wordcloud') #讀取詞云圖片
#對所有的詞云圖片回圈構造視頻,我這里之前構造了2711張詞云圖片
for i in range(1, 2712):
img_path = './/wordcloud//wordcloud_{}.png'.format(i)
frame = cv2.imread(img_path)
frame = cv2.resize(frame, img_size) # 生成視頻 圖片尺寸和設定尺寸相同
videoWriter.write(frame) # 寫進視頻里
print(f'======== 按照視頻順序第{i}張圖片合進視頻 ========')
videoWriter.release() # 釋放資源
最后一步,將合成的視頻添加背景音樂
import moviepy.editor as mpy
# 讀取詞云視頻
my_clip = mpy.VideoFileClip('result.mp4')
# 截取背景音樂,我這里截取了背景音樂90秒,這個要按照你合成的視頻時間長短來修改數字
audio_background = mpy.AudioFileClip('song.mp3').subclip(0,90)
audio_background.write_audiofile('song1.mp3')
# 視頻中插入音頻
final_clip = my_clip.set_audio(audio_background)
# 保存為最終的視頻 動聽的音樂!漂亮小姐姐詞云跳舞視頻!
final_clip.write_videofile('final_video.mp4')
寫在最后:
每個人情況都不同,可能按照我寫的你也會出現一些問題,但是不要緊,你可以給我留言討論,謝謝!
常見的問題總結:
1. 安裝opencv時的問題
在安裝OpenCV時,我按照網上很多教程,說是先要下載什么OpenCV的whl包,然后放在python的包檔案夾下然后pip安裝,這個地方我也花了不少時間費了很大功夫,因為安裝OpenCV需要和你的python版本及作業系統還有計算機架構匹配,所以你一般很難確定這些,也就安裝不成功,結果最后直接使用 pip install opencv-python 解決問題,如果使用pip安裝OpenCV出錯了,也不要急,只需要對應提示去找原因就可以了,總之這應該是全網最簡單的方法,
2. 協程問題
在執行爬取彈幕代碼的時候,如果出現一行報錯,只需要加上下邊兩行代碼即可,
# 加上這兩句就不會報錯,主要因為ipthon不支持
# import nest_asyncio
# nest_asyncio.apply()
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/389011.html
標籤:其他
上一篇:【OpenCV-Python】18.OpenCV的影像輪廓——霍夫變換
下一篇:案例分享:Qt+RV1126+PLC醫療血漿采集儀(中英文輸入、西門子PLC、資料庫存盤,各種資料統計,數值監測,電子秤操作,記錄查詢,全域報警等等)
