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

爬遍天下無敵手發表於2020-11-27

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

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

 

 

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

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

 

 

哈哈哈,所以本期我們就用Python給馬保國老師做一個閃電五連鞭動態詞雲圖。

詞雲資料來自B站,使用stylecloud詞雲庫繪製。

 

 

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

年輕人,不講武德。這樣好嗎,耗子尾汁。

PS:如有需要Python學習資料的小夥伴可以加點選下方連結自行獲取

python免費學習資料以及群交流解答點選即可加入

 

/ 01 / 彈幕資料獲取

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

這是一個用Python寫的呼叫Bilibili各種API的庫,範圍涵蓋視訊、音訊、直播、動態、專欄、使用者、番劇等。

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

使用video模組下面的兩個方法,可以獲取11月每天的視訊彈幕。

 

 

首先需要獲取SESSDATA和CSRF(bili_jct)的值。

谷歌瀏覽器可以通過下圖檢視,域名選擇bilibili.com。

 

 

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

 

 

點選排名第一的視訊,然後在瀏覽器的訪問欄獲取BV號,BV1HJ411L7DP。

獲取彈幕程式碼如下。

 
 

 

  1. from bilibili_api import video, Verify

  2. import datetime

  3.  
  4. # 引數

  5. verify = Verify("你的SESSDATA值", "你的bili_jct值")

  6.  
  7. # 獲取存在歷史彈幕的日期列表

  8. days = video.get_history_danmaku_index(bvid="BV1HJ411L7DP", verify=verify)

  9. print(days)

  10.  
  11. # 獲取彈幕資訊,並儲存

  12. for day in days:

  13. danmus = video.get_danmaku(bvid="BV1HJ411L7DP", verify=verify, date=datetime.date(*map(int, day.split('-'))))

  14. print(danmus)

  15.  
  16. f = open(r'danmu.txt', 'a')

  17. for danmu in danmus:

  18. print(danmu)

  19. f.write(danmu.text + '\n')

  20. f.close()

 

得到結果。

 

 

我大E了啊,沒有閃。

使用jieba對彈幕資料進行分詞處理。

 
 

 

  1. import jieba

  2. def get_text_content(text_file_path):

  3. '''

  4. 獲取填充文字內容

  5. '''

  6. text_content = ''

  7. with open(text_file_path, encoding='utf-8') as file:

  8. text_content = file.read()

  9. # 資料清洗,只儲存字串中的中文,字母,數字

  10. text_content_find = re.findall('[\u4e00-\u9fa5a-zA-Z0-9]+', text_content, re.S)

  11. text_content = ' '.join(jieba.cut(str(text_content_find).replace(" ", ""), cut_all=False))

  12. print(text_content)

  13. return text_content

  14.  
  15.  
  16. text_content = get_text_content('danmu.txt')

 

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

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

參考網上的資料,執行如下程式碼即可下載B站視訊。

 
 

 

  1. from bilibili_api import video, Verify

  2. import requests

  3. import urllib3

  4.  
  5. # 引數

  6. verify = Verify("你的SESSDATA值", "你的bili_jct值")

  7.  
  8. # 獲取下載地址

  9. download_url = video.get_download_url(bvid="BV1JV41117hq", verify=verify)

  10. print(download_url["dash"]["video"][0]['baseUrl'])

  11.  
  12. baseurl = 'https://www.bilibili.com/video/BV1JV41117hq'

  13. title = '馬保國'

  14.  
  15.  
  16. def get_video():

  17. urllib3.disable_warnings()

  18.  
  19. headers = {

  20. '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',

  21. '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',

  22. 'Accept-Encoding': 'gzip, deflate, br',

  23. 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8'

  24. }

  25. headers.update({'Referer': baseurl})

  26. res = requests.Session()

  27. begin = 0

  28. end = 1024 * 1024 - 1

  29. flag = 0

  30.  
  31. temp = download_url

  32.  
  33. filename = "./" + title + ".flv"

  34. url = temp["dash"]["video"][0]['baseUrl']

  35. while True:

  36. headers.update({'Range': 'bytes=' + str(begin) + '-' + str(end)})

  37. res = requests.get(url=url, headers=headers, verify=False)

  38. if res.status_code != 416:

  39. begin = end + 1

  40. end = end + 1024 * 1024

  41. else:

  42. headers.update({'Range': str(end + 1) + '-'})

  43. res = requests.get(url=url, headers=headers, verify=False)

  44. flag = 1

  45. with open(filename, 'ab') as fp:

  46. fp.write(res.content)

  47. fp.flush()

  48. if flag == 1:

  49. fp.close()

  50. break

  51.  
  52. print('--------------------------------------------')

  53. print('視訊下載完成')

  54. filename = "./" + title + ".mp3"

  55. url = temp["dash"]["audio"][0]['baseUrl']

  56. while True:

  57. headers.update({'Range': 'bytes=' + str(begin) + '-' + str(end)})

  58. res = requests.get(url=url, headers=headers, verify=False)

  59. if res.status_code != 416:

  60. begin = end + 1

  61. end = end + 1024 * 1024

  62. else:

  63. headers.update({'Range': str(end + 1) + '-'})

  64. res = requests.get(url=url, headers=headers, verify=False)

  65. flag = 1

  66. with open(filename, 'ab') as fp:

  67. fp.write(res.content)

  68. fp.flush()

  69. if flag == 1:

  70. fp.close()

  71. break

  72.  
  73. print('音訊下載完成')

 

記得新增SESSDATA和CSRF(bili_jct)的值

 

/ 02 / PaddleSeg人像分割

基於百度AI Studio的專案,專案地址:

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

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

 
 

 

  1. # 下載PaddleSeg

  2. git clone https://hub.fastgit.org/PaddlePaddle/PaddleSeg.git

  3.  
  4. cd PaddleSeg/

  5.  
  6. # 安裝所需依賴項

  7. pip install -r requirements.txt

 

通常去「GitHub」上下載東西,速度都比較慢,可以使用加速連結。

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

 
 

 

  1. # 新建資料夾

  2. mkdir work/videos

  3. mkdir work/texts

  4. mkdir work/mp4_img

  5. mkdir work/mp4_img_mask

  6. mkdir work/mp4_img_analysis

 

新建一些資料夾,主要用來存放相關檔案的。

這裡可以將之前爬取到的視訊和音訊放置在videos中。

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

 
 

 

  1. def transform_video_to_image(video_file_path, img_path):

  2. '''

  3. 將視訊中每一幀儲存成圖片

  4. '''

  5. video_capture = cv2.VideoCapture(video_file_path)

  6. fps = video_capture.get(cv2.CAP_PROP_FPS)

  7. count = 0

  8. while (True):

  9. ret, frame = video_capture.read()

  10. if ret:

  11. cv2.imwrite(img_path + '%d.jpg' % count, frame)

  12. count += 1

  13. else:

  14. break

  15. video_capture.release()

  16.  
  17. filename_list = os.listdir(img_path)

  18. with open(os.path.join(img_path, 'img_list.txt'), 'w', encoding='utf-8') as file:

  19. file.writelines('\n'.join(filename_list))

  20.  
  21. print('視訊圖片儲存成功, 共有 %d 張' % count)

  22. return fps

  23.  
  24.  
  25. input_video = 'work/videos/Master_Ma.mp4'

  26. fps = transform_video_to_image(input_video, 'work/mp4_img/')

 

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

 

 

然後使用PaddleSeg將所有的視訊圖片,進行人像分割,生成mask圖片。

 
 

 

  1. # 生成mask結果圖片

  2. python 你的路徑/PaddleSeg/pdseg/vis.py \

  3. --cfg 你的路徑/work/humanseg.yaml \

  4. --vis_dir 你的路徑/work/mp4_img_mask

 

使用模型進行預測,其中humanseg.yaml檔案是作者提供的,可以進行影像分割。

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

由於預訓練模型較大,就不放網盤上了,直接訪問下面這個連結即可下載。

 
 

 

  1. # 下載預訓練模型deeplabv3p_xception65_humanseg

  2. https://paddleseg.bj.bcebos.com/models/deeplabv3p_xception65_humanseg.tgz

 

記得需要將humanseg.yaml檔案中的路徑資訊,修改成你自己的路徑。

 

 

執行上面那三行命令,最後就會生成564張mask檔案。

 

 

 

/ 03 / 詞雲生成

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

 
 

 

  1. def create_wordcloud():

  2. for i in range(564):

  3. file_name = os.path.join("mp4_img_mask/", str(i) + '.png')

  4. # print(file_name)

  5. result = os.path.join("work/mp4_img_analysis/", 'result' + str(i) + '.png')

  6. # print(result)

  7. stylecloud.gen_stylecloud(text=text_content,

  8. font_path='方正蘭亭刊黑.TTF',

  9. output_name=result,

  10. background_color="black",

  11. mask_img=file_name)

 

因為stylecloud庫無法自定義詞雲圖片,所以我修改了它的程式碼。

給gen_stylecloud新增了mask_img這個引數,最終作用在gen_mask_array這個函式上。

 

 

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

 

 

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

 
 

 

  1. def combine_image_to_video(comb_path, output_file_path, fps=30, is_print=False):

  2. '''

  3. 合併影像到視訊

  4. '''

  5. fourcc = cv2.VideoWriter_fourcc(*'mp4v')

  6.  
  7. file_items = [item for item in os.listdir(comb_path) if item.endswith('.png')]

  8. file_len = len(file_items)

  9. # print(comb_path, file_items)

  10. if file_len > 0:

  11. print(file_len)

  12. temp_img = cv2.imread(os.path.join(comb_path, file_items[0]))

  13. img_height, img_width, _ = temp_img.shape

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

  16.  
  17. for i in range(file_len):

  18. pic_name = os.path.join(comb_path, 'result' + str(i) + ".png")

  19. print(pic_name)

  20. if is_print:

  21. print(i + 1, '/', file_len, ' ', pic_name)

  22. img = cv2.imread(pic_name)

  23. out.write(img)

  24. out.release()

  25.  
  26.  
  27. combine_image_to_video('work/mp4_img_analysis/', 'work/mp4_analysis.mp4', 30)

 

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

 
 

 

  1. # 視訊裁剪

  2. ffmpeg -i mp4_analysis_result.mp4 -vf crop=iw:ih/2:0:ih/5 output.mp4

  3.  
  4. # 視訊重疊

  5. 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

  6.  
  7. # 新增音訊

  8. ffmpeg -i merge.mp4 -i videos/Master_Ma.mp4 -c:v copy -c:a copy work/mp4_analysis_result2.mp4 -y

  9.  
  10. # 生成gif圖

  11. ffmpeg -ss 00:00:22 -t 3 -i merge.mp4 -r 15 a.gif

 

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

相關文章