import xlwt #导入模块
from skimage.metrics import structural_similarity as ssim # 使用这个库进行对于生成图片的细筛
import time # 使用这个库对程序的运行进行计时
import os # 使用这个库进行输入和输出
import cv2 # 使用了这个库进行fps读取和图片的读取
import easyocr #离线OCR,需要配置,可自行百度EasyOcr配置方法
'''
Author: 符若_float
Date: 2022.10.18
Title: Galgame: Video Words to Excel
Ver: 1.1 ET/BT (EasyOcr & TerminalInput)/(BaiduOcr & TerminalInput)
**默认运行模式为EasyOcr,要使用百度Ocr,请填写API端口并用注释段替换原函数
Theme: 抽取视频关键帧(可设置抽样频率和相似程度要求)并批量OCR识别图片并输出时间轴和内容到Excel文档
Content:
0. *两个用户可设定参数*
a. 抽帧频率targetFPS (每秒钟抽取几帧)
b. 目标相似度threshold (低于此相似度的图片将会被保存)
更高的targetFPS会消耗更多的时间, 但是会生成更精确的时间码
1. 选择一个视频文件
2. 按给定的每秒帧数进行抽帧(cv2.VideoCapture) 抽取的帧存储在temp.jpg中
对于第0个满足条件的帧, 存储至cache中
对于其它满足条件的帧, 将之与cache作比较:
如果相似度大于threshold ->储存至本地和cache, 更新cache为这一图片, 输出储存信息
OCR并将OCR结果和名字分别写入excel, 保存超链接
如果相似度小于threshold ->输出舍弃信息
完成后, 关闭抽帧相机, 输出完成的信息
'''
targetFPS = 1 # 目标每秒选取的帧数(越低越快,相对的,时间轴精度就比较低)
threshold = 0.98 # 目标相似度(低于此相似度的图片才会被保存)
def img2str(img_path):
reader = easyocr.Reader(['ja'], gpu=True) # 没有gpu的话需要加上gpu=False
try:
result = reader.readtext(img_path)
text = ''
for sentences in result:
text += sentences[1]
return text
except Exception as e:
return ("ocr wrong occur here")
#如果要使用百度OCR版本,请用此段替换上一段函数
'''
def get_file_content(file):
with open(file, 'rb') as fp:
return fp.read()
def img2str(img_path):
APP_ID = "qwq" # 填自己的信息
API_KEY = "qwqq"
SECRET_KEY = "qwqqq"
client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
image = get_file_content(img_path)
# 调用通用文字识别, 图片参数为本地图片
client.basicGeneral(image)
# 如果有可选参数
options = {}
options["language_type"] = "JAP" # 不说明是日语的话会爆炸!(x
options["detect_direction"] = "false"
options["detect_language"] = "false"
options["probability"] = "false"
# 带参数调用通用文字识别, 图片参数为本地图片
try:
res = client.basicGeneral(image, options)
strx = ""
for tex in res["words_result"]: # 遍历结果
strx += tex["words"] # 每一行,不换行
return strx # 返回字符串
except Exception as e:
return ("ocr wrong occur here")
'''
# 给定fps,将帧数转化为指定格式的视频时间(匹配popsub,小时数是假的2333,不能超过1小时,想要什么格式可以自己改ww)
def frames2time(frames, fps, sign):
fpm = fps*60
a = int(frames/fpm) # 分钟数(取整)
frames %= fpm # 余下帧数
b = frames/fps
return "0"+sign+f"{str(a):0>2}"+sign+f"{b:0>5.2f}"
def checkPath(path):
if not os.path.exists(path): # 如果文件目录不存在则创建目录
os.makedirs(path)
def video2xlsx(video_path, output_path, frame_frequency):
workbook = xlwt.Workbook() #创建workbook 对象
worksheet = workbook.add_sheet('sheet1') #创建工作表sheet
checkPath(output_path)
camera = cv2.VideoCapture(video_path) # 创建一个相机,读取视频帧
frames = -1
i=0
T = int(frame_frequency/targetFPS) # 周期每秒targetFPS帧
while True:
frames = frames + 1 # 第frames帧(0base)
res, image = camera.read()
if not res:
workbook.save(output_path+r'\Text.xls') #保存表为Text.xls
print('Completed!')
break
if frames % T == 0: # 按照周期抽帧,不到周期就跳过
cv2.imwrite(output_path + '/temp.jpg', image)
img1 = cv2.imread(output_path + '/temp.jpg') # 每周期保存一个临时文件
if frames == 0:
output_img=output_path + '/' + frames2time(frames,frame_frequency, '_')+'.jpg'
cv2.imwrite(output_img, image)
cache = img1 # 每次遇到“新图片”就存储,进行识别,并刷新缓存
text = img2str(output_img) # OCR
print(text)
worksheet.write(i, 0,xlwt.Formula('HYPERLINK("{}","{}")'.format(output_path,frames2time(frames, frame_frequency, ':')))) #0,0格为百度翻译
try:
worksheet.write(i, 1, xlwt.Formula('HYPERLINK("{}","{}")'.format(output_img,text))) #往表中写内容,第一各参数表示行,第二个参数表示列,第三个参数为内容
except Exception as e:
worksheet.write(i, 1, "write wrong occur here")
print("write wrong occur here")
i+=1
print('OvO '+str(frames)+' OvO')
else:
if ssim(img1, cache, multichannel=True) > threshold:
print('___ '+str(frames)+' ___')
else:
output_img=output_path + '/' + frames2time(frames,frame_frequency, '_')+'.jpg'
cv2.imwrite(output_img, image)
cache = img1 # 每次遇到“新图片”就存储,进行识别,并刷新缓存
text = img2str(output_img) # OCR
print(text)
worksheet.write(i, 0, frames2time(frames, frame_frequency, ':'))
try:
worksheet.write(i, 1, xlwt.Formula('HYPERLINK("{}","{}")'.format(output_img,text))) #往表中写内容,第一各参数表示行,第二个参数表示列,第三个参数为内容
except Exception as e:
worksheet.write(i, 1, "write wrong occur here")
print("write wrong occur here")
i+=1
print('OvO '+str(frames)+' OvO')
os.remove(output_path + '/temp.jpg') # 删除临时文件
camera.release() # 释放相机
from warnings import simplefilter
simplefilter(action='ignore', category=FutureWarning) #关闭futurewarning
if __name__ == "__main__":
print("你好! 欢迎使用Galgame:Video2Xlsx!\nAuthor:符若_float\nVersion:1.1 ET (EasyOcr & TerminalInput)")
if input("请问需要修改参数吗?\n0: 直接开始!\n1:需要修改参数!\n>> ")=='1':
targetFPS = float(input(f"请输入TargetFPS\n(该值意思为您的视频抽帧频率,推荐值为1,您之前的值为{targetFPS})\n这个值越大字幕时间轴的精度越高, 不过也会导致处理速度成倍降低、重复OCR次数少量增加哦\n>> ")) # 目标每秒选取的帧数(越低越快,相对的,时间轴精度就比较低)
threshold = float(input(f"请输入threshold\n(该值意思为您的视频文字变动的判断阈值,推荐值为0.98,您之前的值为{threshold})如果效果尚可建议不要修改哦\n>> ")) # 目标相似度(低于此相似度的图片才会被保存)
print("现在开始运行程序!\n注意:中途终止会导致xlsx保存失败哦")
video_name= input("请输入文件地址~\n(您可以直接把文件拖入终端窗口或复制文件地址,输出文件将在您的视频文件的同一目录下的同名文件夹中)\n>> ") # 可以批量选取!结果输出在相同目录的同名文件夹
start = time.time()
videoCapture = cv2.VideoCapture(video_name)
print("正在处理视频: "+video_name)
fps = videoCapture.get(cv2.CAP_PROP_FPS) # 获取帧速率(frames per second)
video2xlsx(video_name, video_name[:-4], fps) # 输出在同一目录下的同名文件夹
print("视频"+video_name+"已处理完成~")
end = time.time()
print(f"该视频的处理总用时共计{end-start}秒\n感谢您的使用!")
B站 @符若_float 版本持续更新到满意为止!