1 项目背景
看到关于字幕提取项目有不断迭代优化的版本,感觉非常有趣,本项目基于前面版本的优化大幅度提高字幕读取速度和降低字幕重复度次数……

前言就不说了,这里基于前辈探索继续优化,前辈探索总结请看该链接[图片相似度计算+PaddleOCR:视频字幕极速提取器的实现] by @深渊上的坑

2 效果对比
这里选取1分25秒视频作为提取结果对比视频

方案 效果 耗时
[当字幕君的文档丢失了…] 未知 未知
[字幕提取实验] 较好(部分重复字、漏字) 10小时6分钟
[图片相似度计算+PaddleOCR:视频字幕] 较好(部分重复字、漏字) 1分钟24秒
[本项目版本] 接近完美(100%还原OCR提取效果) 6秒
[本项目文本相似度探索版本] 接近完美(100%还原OCR提取效果) 12秒
3 结果对比
原视频字幕 前辈版本字幕 本项目字幕 本文本相似度项目字幕
让我们从一次时光旅行 让我们从一次时光旅行 让我们从一次时光旅行 让我们从一次时光旅行
开启植物天堂的故事 开启植物天堂的故事 开启植物天堂的故事 开启植物天堂的故事
地球的午夜 地球的午夜 地球的午夜 地球的午夜
是在火山喷发中度过的 是在火山喷发中度过的 是在火山喷发中度过的 是在火山喷发中度过的
到了凌晨三四点 到了凌晨三四点 到了凌晨三四点 到了凌晨三四点
在海洋深处有了生命的迹象 在海洋深处有了生命的迹象 在海洋深处有了生命的迹象 在海洋深处有了生命的迹象
清晨6点多 清晨6点多 清晨6点多 清晨6点多
更加壮丽的生命乐章开始了 更加壮丽的生命乐章开始了 更加壮丽的生命乐章开始了 更加壮丽的生命乐章开始了
一种蓝藻细菌 一种蓝藻细菌,种蓝藻细菌 一种蓝藻细菌 一种蓝藻细菌
学会利用二氧化碳水和阳光 学会利用二氧化碳,学会利用二氧化碳水和阳光 学会利用二氧化碳水和阳光 学会利用二氧化碳水和阳光
制造生命所需能量 制造生命所需能量 制造生命所需能量 制造生命所需能量
同时释放出了氧气 同时释放出了氧气 同时释放出了氧气 同时释放出了氧气
这个被称为光合作用的过程 这个被称为光合作用的过程 这个被称为光合作用的过程 这个被称为光合作用的过程
为植物世界打开了大门 为植物世界打开了大门 为植物世界打开了大门 为植物世界打开了大门
此时 此时 此时 此时
中国的陆地 中国的陆地 中国的陆地 中国的陆地
也逐渐从海洋露出形成岛屿 也逐渐从海洋露出形成岛屿 也逐渐从海洋露出形成岛屿 也逐渐从海洋露出形成岛屿
但在相当长的时间里 但在相当长的时间里 但在相当长的时间里 但在相当长的时间里
陆地十分荒凉没有生机 陆地十分荒凉没有生机 陆地十分荒凉没有生机 陆地十分荒凉没有生机
这些岩石坚硬 这些岩石坚硬 这些岩石坚硬 这些岩石坚硬
无法储存水分 无法储存水分 无法储存水分 无法储存水分
是当时陆地环境的写照 是当时陆地环境的写照 是当时陆地环境的写照 是当时陆地环境的写照
直到晚上九点多 直到晚上九点多 直到晚上九点多 直到晚上九点多
也就是四亿年前左右 也就是四亿年前左右 也就是四亿年前左右 也就是四亿年前左右
一些矮小的生命 些矮小的生命 些矮小的生命 些矮小的生命
开始征服陆地 开始征服陆地 开始征服陆地 开始征服陆地
她们用一种近似于根的构造 未识别出字幕结果 她们用一种近似于根的构造 她们用一种近似于根的构造
固定在岩石上 未识别出字幕结果 固定在岩石上 固定在岩石上
1 配置环境
In [20]
!pip3 install scikit-image
!pip3 install -U paddleocr
!pip3 install -U paddlenlp
2 导入环境
In [2]
import os
import cv2
from PIL import Image
import numpy as np
from skimage.metrics import structural_similarity as compare_ssim
from tqdm import tqdm
from paddleocr import PaddleOCR, draw_ocr
from paddlenlp import Taskflow
3 导入模型
In [19]
ocr = PaddleOCR(use_angle_cls=False, lang=“ch”)
为减少干扰,进一步提高识别效果和速度,对于字幕固定在下方的视频,我们最好通过抠图,把会出现字幕的部分裁剪出来,然后用这些数据预测。在这里插入图片描述
4 前辈原版实现
In [17]
src_video = cv2.VideoCapture(‘Trim.mp4’)

prev_frame = None # 用于保存上一帧图像
total_frame = int(src_video.get(cv2.CAP_PROP_FRAME_COUNT)) # 计算视频总帧数
save_text = []
last_res = None
for i in range(total_frame):
success, frame = src_video.read()
if i == 0:
prev_frame = frame[-120:-30,:] # 裁剪视频的下方部分
src_video.release()

src_video = cv2.VideoCapture(‘Trim.mp4’)
for i in tqdm(range(total_frame)):

for i in tqdm(range(2400)):

success, frame = src_video.read()
# if not firstlaunch:
if success:
    ssim1 = compare_ssim(frame[-120:-30,:], prev_frame, multichannel=True)
    # print(ssim1)
    if ssim1 > 0.9:
        pass
    else:
        result = ocr.ocr(frame[-120:-30,:], cls=True)
        # print(result)
        if len(result)> 0: 
            res = result[0][1][0]
            if res != last_res:
                print(result[0][1][0])
                save_text.append(res)
                last_res = res
        prev_frame = frame[-120:-30,:].copy() # 存储此帧

In [44]

输出结果

save_text
[‘让我们从一次时光旅行’,
‘开启植物天堂的故事’,
‘地球的午夜’,
‘是在火山喷发中度过的’,
‘到了凌晨三四点’,
‘在海洋深处有了生命的迹象’,
‘清晨6点多’,
‘更加壮丽的生命乐章开始了’,
‘一种蓝藻细菌’,
‘种蓝藻细菌’,
‘学会利用二氧化碳水和阳光’,
‘制造生命所需能量’,
‘同时释放出了氧气’,
‘这个被称为光合作用的过程’,
‘为植物世界打开了大门’,
‘此时’,
‘中国的陆地’,
‘也逐渐从海洋露出形成岛屿’,
‘但在相当长的时间里’,
‘陆地十分荒凉没有生机’,
‘这些岩石坚硬’,
‘无法储存水分’,
‘是当时陆地环境的写照’,
‘直到晚上九点多’,
‘也就是四亿年前左右’,
‘些矮小的生命’,
‘开始征服陆地’,
‘,开始征服陆地’,
‘开始征服陆地’,
‘她们用一种近似于根的构造’,
‘固定在岩石上’]
5 本项目版本实现
In [16]
src_video = cv2.VideoCapture(‘Trim.mp4’)
fps = int(src_video.get(cv2.CAP_PROP_FPS))
total_frame = int(src_video.get(cv2.CAP_PROP_FRAME_COUNT)) # 计算视频总帧数

save_text = []
last_res = ‘None’
for i in tqdm(range(total_frame)):

for i in tqdm(range(2400)):

success, frame = src_video.read()
# if not firstlaunch:
if i % (fps) == 0:
    if success:
        result = ocr.ocr(frame[-120:-30,:], cls=True)
        if len(result)> 0: 
            res = result[0][1][0]
            if ((res[:-1] not in last_res) and (last_res[:-1] not in res)):
                save_text.append(res)
                last_res = res

finally_text = []
for save in save_text:
if not any(save[:-1] in text for text in finally_text):
finally_text.append(save)
In [39]

输出结果

finally_text
[‘让我们从一次时光旅行’,
‘开启植物天堂的故事’,
‘地球的午夜’,
‘是在火山喷发中度过的’,
‘到了凌晨三四点’,
‘在海洋深处有了生命的迹象’,
‘清晨6点多’,
‘更加壮丽的生命乐章开始了’,
‘一种蓝藻细菌’,
‘学会利用二氧化碳水和阳光’,
‘制造生命所需能量’,
‘同时释放出了氧气’,
‘这个被称为光合作用的过程’,
‘为植物世界打开了大门’,
‘此时’,
‘中国的陆地’,
‘也逐渐从海洋露出形成岛屿’,
‘但在相当长的时间里’,
‘陆地十分荒凉没有生机’,
‘这些岩石坚硬’,
‘无法储存水分’,
‘是当时陆地环境的写照’,
‘直到晚上九点多’,
‘也就是四亿年前左右’,
‘些矮小的生命’,
‘开始征服陆地’,
‘她们用一种近似于根的构造’,
‘固定在岩石上’]
6 本项目文本相似度探索版本实现
In [40]
similarity = Taskflow(task=“text_similarity”, mode=“fast”, max_seq_len=16)
[2022-06-15 18:19:35,442] [ INFO] - Already cached /home/aistudio/.paddlenlp/models/simbert-base-chinese/vocab.txt
In [18]
src_video = cv2.VideoCapture(‘Trim.mp4’)
fps = int(src_video.get(cv2.CAP_PROP_FPS))
total_frame = int(src_video.get(cv2.CAP_PROP_FRAME_COUNT)) # 计算视频总帧数

save_text = []
last_res = ‘None’
for i in tqdm(range(total_frame)):

for i in tqdm(range(2400)):

success, frame = src_video.read()
# if not firstlaunch:
if i % (fps) == 0:
    if success:
        result = ocr.ocr(frame[-120:-30,:], cls=True)
        if len(result)> 0: 
            res = result[0][1][0]
            if ((res[:-1] not in last_res) and (last_res[:-1] not in res)):
                save_text.append(res)
                last_res = res

no_similarity_text = []

for text1 in tqdm(save_text):
for text2 in save_text:
if text1 != text2:
score = similarity([[text1, text2]])
if score[0][‘similarity’] > 0.9:
break

if score[0]['similarity'] < 0.9: 
    no_similarity_text.append(text1)

In [46]

输出结果

no_similarity_text
[‘让我们从一次时光旅行’,
‘开启植物天堂的故事’,
‘地球的午夜’,
‘是在火山喷发中度过的’,
‘到了凌晨三四点’,
‘在海洋深处有了生命的迹象’,
‘清晨6点多’,
‘更加壮丽的生命乐章开始了’,
‘一种蓝藻细菌’,
‘学会利用二氧化碳水和阳光’,
‘制造生命所需能量’,
‘同时释放出了氧气’,
‘这个被称为光合作用的过程’,
‘为植物世界打开了大门’,
‘此时’,
‘中国的陆地’,
‘也逐渐从海洋露出形成岛屿’,
‘但在相当长的时间里’,
‘陆地十分荒凉没有生机’,
‘这些岩石坚硬’,
‘无法储存水分’,
‘是当时陆地环境的写照’,
‘直到晚上九点多’,
‘也就是四亿年前左右’,
‘些矮小的生命’,
‘开始征服陆地’,
‘她们用一种近似于根的构造’,
‘固定在岩石上’]
In [ ]

保存读取的字幕文件

with open(‘output.txt’,‘w’) as f:
for i in save_text:
f.writelines(i+‘\n’)
f.close()
3 优化总结
1、采用抽帧读取、规则方法、自然语言文本相似度方法,大大降低了重复字幕数量和提高了视频字幕获取速度。
2、自然语言文本相似度方法需要进行阈值可控调参,目前只是简单的划分,相似度效果还有待提高,还可以加上视频帧图像相似度算法。
3、正如前面所讲,基于paddlenlp开箱即用的文本相似度模型虽然已经被团队优化的非常完美,但是依然会提高运行时间和资源消耗。最后提一句,从我的角度来看,PaddleOCR的轻量模型识别已经能够接近100%捕捉所有计算机字体字幕,效果又快又好,建议大家使用

Logo

学大模型,用大模型上飞桨星河社区!每天8点V100G算力免费领!免费领取ERNIE 4.0 100w Token >>>

更多推荐