利用Python做一个舞动起来的小姐姐词云视频

实现过程

一、选取视频并下载

可以利用you-get把哔哩哔哩的视频下载到本地
具体可参考上一篇文章:传送门

二、获取视频的弹幕内容

爬取弹幕内容,我在这里给大家推荐一个非常好用的第三方库,bilibili_api,详细内容可参考官方文档:传送门
代码如下:

from bilibili_api import Verify, video

verify = Verify(sessdata="你的sessdata值的内容", csrf="你的csrf值的内容")
# 参数
BVID = "这里填爬取视频弹幕的BV号"
# 获取视频信息
info = video.get_video_info(bvid=BVID, verify=verify)

# # 假设这里获取 p1 的最新弹幕信息,需要取出 page_id,即每 p 都有自己的编号
page_id = info["pages"][0]["cid"]

# 然后开始获取弹幕
danmakus = video.get_danmaku(bvid=BVID, page_id=page_id)

# 保存弹幕内容
list_all = list()
filename = 'D:/danmu.txt'  # 这里是保存的地址
for dm in danmakus:
    dm = dm.text
    list_all.append(dm)
    # print(list_all)
file = open(filename, 'w', encoding='utf-8')
for i in range(len(list_all)):
    s = str(list_all[i]).replace('[', '').replace(']', '')  # 去除[]
    s = s.replace("'", '').replace(',', '') + '\n'  # 去除单引号,逗号,每行末尾追加换行符
    file.write(s)  # 将列表中数据依次写入文件中
print('弹幕获取完毕!!!')
file.close()

Q:sessdata和csrf的值怎么找?

A:在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里面找到sessdatabili_jct的内容即可(官方文档说,bili_jct的值的值就是csrf的值)

注意:这两个值不要暴露给别人,可能会被盗号(来自官方文档的提示)

结果显示如下:
在这里插入图片描述

三、从视频中提取图片

(一帧一帧地提取,工程量还是蛮大的)
我们可以使用下面的代码先查看,总共可以分为多少张。

import cv2
# 查看总共有多少张图片
cap = cv2.VideoCapture(r"这里是下载的视频所在的路径")
num = 1
while True:
    ret, frame = cap.read()
    if ret:
        num += 1
    else:
        break
    print(num)
cap.release()   # 释放资源

emmm,我爬的这个一分多钟的视频有两千多张,我们可以选取一个范围,就取从第521张到第1314张吧。

import cv2
cap = cv2.VideoCapture(r"这里是下载的视频所在的路径")
num = 1
while True:
    # 逐帧读取视频  按顺序保存到本地文件夹
    ret, frame = cap.read()
    if ret:
        if 521 <= num < 1314:
            cv2.imwrite(f"这里填预保存图片文件夹的路径/img_{num}.jpg", frame)   # 保存一帧帧的图片
            print(f'========== 已成功保存第{num}张图片 ==========')
        num += 1
    else:
        break
cap.release()   # 释放资源

结果如下:
在这里插入图片描述

四、人像分割(借助免费的百度AI)

首先,打开百度AI,传送门,点击右上角的控制台,使用手机扫码登录。登录成功,点击左栏的人脸分析,进行应用创建,创建成功之后,你会在你的应用里得到三个值:
在这里插入图片描述
这三个值马上就会用到。
接着,查看人脸分析的Python SDK文件,文件链接传送门
基本熟悉一下它的应用。

最后,直接上代码:

from aip import AipBodyAnalysis
import os
import cv2
import base64
import numpy as np
import time
import random

# 百度云中已创建应用的  APP_ID API_KEY SECRET_KEY
APP_ID = '你的APP_ID的值'
API_KEY = '你的API_KEY的值'
SECRET_KEY = '你的SECRET_KEY的值'

client = AipBodyAnalysis(APP_ID, API_KEY, SECRET_KEY)
# 保存图像分割后的路径
path = '分割后的图像,想要保存的文件夹的路径'
# os.listdir  列出保存到图片名称
img_files = os.listdir('上一步中,保存提取出来的图片的文件夹路径')
# print(img_files)
for num in range(521, 1314):  # 图片范围
    # 按顺序构造出图片路径
    img = f'上一步中,保存提取出来的图片的文件夹路径/img_{num}.jpg'
    img1 = cv2.imread(img)  # imread读取图片
    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'])
    nparr = np.frombuffer(labelmap, np.uint8)
    labelimg = cv2.imdecode(nparr, 1)
    labelimg = cv2.resize(labelimg, (width, height), interpolation=cv2.INTER_NEAREST)
    new_img = np.where(labelimg == 1, 255, labelimg)
    mask_name = path + '\mask_{}.png'.format(num)
    # 保存分割出来的人像
    cv2.imwrite(mask_name, new_img)
    print(f'======== 第{num}张图像分割完成 ========')
    time.sleep(random.randint(1, 2))

结果如下:
在这里插入图片描述

五、词云生成

from wordcloud import WordCloud
import collections
import jieba
import re
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np

# 读取数据
with open('存放弹幕内容的文件路径', "rt", encoding="utf-8") as f:
    data = f.read()
# 文本预处理  去除一些无用的字符   只提取出中文出来
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 = []
with open('stopwords.txt的存放路径', encoding='utf-8') as f:
    con = f.read().split('\n')
    stop_words = set()
    for i in con:
        stop_words.add(i)

for word in seg_list_exact:
    # 设置停用词并去除单个词
    if word not in stop_words and len(word) > 1:
        result_list.append(word)
# 筛选后统计词频
word_counts = collections.Counter(result_list)
path = '保存词云图片的文件夹路径'

for num in range(521, ):
    img = f'保存分割后的图像的文件夹的路径/mask_{num}.png'
    # 获取蒙版图片
    mask_ = 255 - np.array(Image.open(img))
    # 绘制词云
    plt.figure(figsize=(8, 5), dpi=200)
    my_cloud = WordCloud(
        background_color='black',  # 设置背景颜色  默认是black
        mask=mask_,      # 自定义蒙版
        mode='RGBA',
        max_words=500,
        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}张词云图生成 ========')

Q:stopwords.txt文件是什么?

A:就是一个固定的文件,下载下来即可。百度网盘传送门
提取码:iits

运行结果如下:
在这里插入图片描述

在这里插入图片描述

六、查看原视频中的帧率和图片尺寸

import cv2
mp4 = cv2.VideoCapture(r"这里是下载的视频所在的路径")  # 读取视频
is_opened = mp4.isOpened()  # 判断是否打开
print(is_opened)
fps = mp4.get(cv2.CAP_PROP_FPS)  # 获取视频的帧率
print(fps)
width = mp4.get(cv2.CAP_PROP_FRAME_WIDTH)  # 获取视频的宽度
height = mp4.get(cv2.CAP_PROP_FRAME_HEIGHT)  # 获取视频的高度
print(str(width) + "x" + str(height))
i = 1
time_f = int(fps)

运行结果如下:
在这里插入图片描述

七、合成跳舞视频

import cv2
import os

# 输出视频的保存路径
video_dir = '保存视频的文件路径'
# 帧率(最好填上一步得到的帧率)
fps = 25
# 图片尺寸(最好填上一步得到的尺寸)
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('词云图片所在的文件路径')

for i in range(521, 1314):
    img_path = '词云图片所在的文件路径/' + 'wordcloud_{}.png'.format(i)
    frame = cv2.imread(img_path)
    frame = cv2.resize(frame, img_size)   # 生成视频   图片尺寸和设定尺寸相同
    videoWriter.write(frame)      # 写进视频里
    print(f'======== 按照视频顺序第{i}张图片合进视频 ========')

videoWriter.release()   # 释放资源

运行结果如下:
在这里插入图片描述

八、加入原视频音频加以渲染

emmmm,我几个星期前刚把剪辑软件《达芬奇》删掉,于是我用的哔哩哔哩云剪辑,上传了,想看的小伙伴可以去看一下。

视频传送门

也许只有看到这篇文章并且看到这里的小伙伴才会看到这个视频吧。

九、参考博文

参考博文:传送门

猜你喜欢

转载自blog.csdn.net/qq_44921056/article/details/113922289