最近在mooc上看了一个公开课:职场英语,用来学习在找工作时或者工作中用到的英语交流技巧,非常不错。由于自己听力不是很好,有的字幕中的单词不认识,并且想记下来便于以后学习。所以想把公开课中的字幕都记录下来,存到一个txt中,便于自己去翻译或者后续温习。基于这个需求,通过python opencv tesseract等工具,完成了视频字幕的提取。

首先,我们需要将mooc上的公开课录制下来,这里,我使用了win10自带的xbox录屏工具(快捷键win+G可以调出来),打开mooc职场英语公开课,播放时按快捷键win+Alt+R开始录制,会得到mp4格式的视频。

我录制的视频如下图所示:

有了视频之后我们就可以编写python程序来进行字幕的提取。

首先我们看一下通过python opencv来读取视频:

import cv2
#读取视频
videoCapture = cv2.VideoCapture('./test.mp4')
#读一帧
success, frame = videoCapture.read()
#连续读帧,保存成图片
cnt = 0
while success:jpg_name = "./frame"+str(cnt)+".jpg"cv2.imwrite(jpg_name,frame)cnt += 1success, frame = videoCapture.read() #获取下一帧

这样,我们会在当前路径下看到视频保存成了一张一张的图片。

既然用opencv将视频能变成一张一张的图片,我们就可以在程序的while中进行处理,将字幕提取出来。对于提取字幕,其实是一个ocr的问题,首先需要文本检测,之后进行识别。

这里我们使用一个比较简单的文本检测方法,分两步,垂直分割与水平分割。垂直分割我们考虑到字幕都是出现在视频的下方,所以简单的使用一个固定的垂直方向ratio(比如0.9)就可以,我们提取(图片高*ratio,图片高)这个范围内的一个长条子图像就可以了,比如图片高100,我们提取(90,100)这个长条图像。水平分割我们在图像二值化之后的图上做(字幕像素为255,背景像素为0),逐列检测这个长条图像的像素值,发现这一列上有的像素不为0,说明这一列包含字幕了,这样可以找到左右边界,做切分就可以。为了使后面的识别准确率高一些,我们最好不要完全按照左右边界去切,左右各留出一个小边界最好。这两部分的代码如下(我们定义了一个函数,逐步完成 灰度化->二值化->垂直切分->水平切分 操作。左右切分时的小边界代码中用的10像素。函数参数thresh_代表二值化时的分割线,小于thresh_的像素置零,大于的置255。函数参数v_cut_ratio_代表垂直切分的固定ration,如上文说的0.9。注意函数中的if代表我们考虑了没有字幕的情况,如果左右边界特别小,code中是小于20,我们认为它没有字幕,就不会进入if,从而返回一个np.zero(1)):

def caption_region_extr(src_img, thresh_, v_cut_ratio_):#to grayimgray = src_imgif len(src_img.shape)==3 and src_img.shape[-1]==3:imgray = cv2.cvtColor(src_img,cv2.COLOR_BGR2GRAY)#binaryth,img_bn = cv2.threshold(imgray,thresh_,255,cv2.THRESH_BINARY)#vertical cutcrop_start = int(v_cut_ratio_ * img_bn.shape[0])crop_end = img_bn.shape[0]v_cut_img = img_bn[crop_start:crop_end,:]#horizontal cuth_left = 0h_right = 0for i in range(v_cut_img.shape[1]):if np.any(v_cut_img[:,i]>0):h_left = ibreakfor i in range(v_cut_img.shape[1]-1,-1,-1):if np.any(v_cut_img[:,i]>0):h_right = ibreakh_cut_img = np.zeros(1)if (h_right-h_left)>20:#expand a littleh_left = max(h_left - 10,0)h_right = min(h_right + 10, v_cut_img.shape[1]-1)h_cut_img = v_cut_img[:,h_left:h_right+1]return h_cut_img

经过这个函数的处理,我们得到的图像就是只包含字幕的区域(二值图像):

将这个图像送入tesseract,就可以得到正确的string,把这个string保存到txt中即可。

import pytesseract
text = pytesseract.image_to_string(cap_img)

tesseract我是下载的4.0版本,windows,地址:https://tesseract-ocr.github.io/tessdoc/4.0-with-LSTM.html#400-alpha-for-windows,下载完成之后安装,需要将安装路径加入到环境变量Path,并且需要新加入一个用户变量TESSDATA_PREFIX:

否则会出现如下错误:

安装好tesseract之后就可以在win的cmd中使用tesseract了。要在python程序中使用,还需要安装python库:pip install pytesseract

介绍完了tesseract,我们继续完善我们的python程序,由于opencv while读取一帧一帧的视频会造成字幕重复的现象,有可能我们好几帧提取的都是一行字幕,毕竟字幕变化没有帧率快的。所以我们还需要提取完图像之后增加一个去重的功能,这里就是简单的实现了一个Equal_函数来判断两幅提取的图像是不是相似的,通过图像尺寸与图像矩阵的余弦距离来进行判断,代码如下(注意之所以将图像矩阵转换为float64,就是怕矩阵展开成向量计算相似读的时候int型越界):

def Equal_(region_a_, region_b_, thresh_):if region_a_.shape != region_b_.shape:return Falsea = region_a_.reshape(-1).astype(np.float64)b = region_b_.reshape(-1).astype(np.float64)a_norm = np.linalg.norm(a)b_norm = np.linalg.norm(b)similiarity = np.dot(a, b.T)/(a_norm * b_norm) dist = 1. - similiarityif dist>thresh_:return Falseelse:return True

当然,我们通过将字幕图像输入给tesseract,识别之后在string上判断是否相同也是可以的,这里我们用图像判断一次,然后再用tesseract结果判断一次,鲁棒一些。

这样,我们就会逐帧得到对应的字幕string,将其保存在一个list中,读完视频之后将list写入文件中就可以了。

这个整体过程就介绍完了,当然这个过程是很简单的,其实我们可以引入一些神经网络模型来做文本的提取与识别。这里就是简单的做水平垂直分割,后续复杂场景可以再进行引入。比如各种视频的文本提取等应用,我们可以考虑EAST或者CTPN文本检测,CRNN+CTC文本识别的方案,还有端到端的检测识别方案FOTS等。再完善一些,我们将识别出来的英文文本txt进行翻译变成其他语言,引入更加完美的方案。

本录制视频的字幕提取整体python 代码如下所示:

import cv2
import numpy as np
import pytesseractdef caption_region_extr(src_img, thresh_, v_cut_ratio_):#to grayimgray = src_imgif len(src_img.shape)==3 and src_img.shape[-1]==3:imgray = cv2.cvtColor(src_img,cv2.COLOR_BGR2GRAY)#binaryth,img_bn = cv2.threshold(imgray,thresh_,255,cv2.THRESH_BINARY)#vertical cutcrop_start = int(v_cut_ratio_ * img_bn.shape[0])crop_end = img_bn.shape[0]v_cut_img = img_bn[crop_start:crop_end,:]#horizontal cuth_left = 0h_right = 0for i in range(v_cut_img.shape[1]):if np.any(v_cut_img[:,i]>0):h_left = ibreakfor i in range(v_cut_img.shape[1]-1,-1,-1):if np.any(v_cut_img[:,i]>0):h_right = ibreakh_cut_img = np.zeros(1)if (h_right-h_left)>20:#expand a littleh_left = max(h_left - 10,0)h_right = min(h_right + 10, v_cut_img.shape[1]-1)h_cut_img = v_cut_img[:,h_left:h_right+1]return h_cut_imgdef Equal_(region_a_, region_b_, thresh_):if region_a_.shape != region_b_.shape:return Falsea = region_a_.reshape(-1).astype(np.float64)b = region_b_.reshape(-1).astype(np.float64)a_norm = np.linalg.norm(a)b_norm = np.linalg.norm(b)similiarity = np.dot(a, b.T)/(a_norm * b_norm) dist = 1. - similiarityif dist>thresh_:return Falseelse:return True#获得视频的格式
videoCapture = cv2.VideoCapture('./test.mp4')#获得码率及尺寸
# fps = videoCapture.get(cv2.CAP_PROP_FPS)
# size = (int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),
#  int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
# fNUMS = videoCapture.get(cv2.CAP_PROP_FRAME_COUNT)
# print(size)
# print(fps)#读帧
success, frame = videoCapture.read()name_cnt = 0crop_ratio_ = 0.9
pre_cap_region = np.zeros(1)
ocr_=list()b_reference_ = Falsewhile success:# cv2.imshow('windows', frame) #显示# cv2.waitKey(int(1000/fps)) #延迟cap_region = caption_region_extr(frame, 200, crop_ratio_)#first captionif (len(pre_cap_region) == 1) and (len(cap_region.shape) != 1):pre_cap_region = cap_regionif b_reference_:img_name = "zimu"+str(name_cnt)+".jpg"cv2.imwrite(img_name, pre_cap_region)name_cnt += 1text = pytesseract.image_to_string(pre_cap_region)ocr_.append(text)if len(cap_region.shape) != 1:if False == Equal_(cap_region,pre_cap_region,0.1):if b_reference_:img_name = "zimu"+str(name_cnt)+".jpg"cv2.imwrite(img_name, cap_region)name_cnt += 1text = pytesseract.image_to_string(cap_region)if text!=ocr_[-1]:ocr_.append(text)pre_cap_region = cap_regionsuccess, frame = videoCapture.read() #获取下一帧videoCapture.release()with open("result.txt","w") as wf:for line in ocr_:wf.writelines(line+"n")

算上空格与一些注释行才100行,非常简单。

python中提取几列_自己录制的公开课视频中提取字幕(python+opencv+Tesseract-OCR)相关推荐

  1. 转:如何选择 Excel 中的数据列,然后将数据粘贴到文本文件中?

    从网上找到的一篇关于选择Excel中指定列然后保存到文本文件的文章,正好解了燃眉之急.收录如此,供日后再看! --------------------------------------------- ...

  2. python数据结构算法 北京大学_北京大学公开课《数据结构与算法Python版》

    之前我分享过一个数据结构与算法的课程,很多小伙伴私信我问有没有Python版. 看了一些公开课后,今天特向大家推荐北京大学的这门课程:<数据结构与算法Python版>. 课程概述 很多同学 ...

  3. (SGPN)南加州大学 phd 王薇月:深度学习在点云分割中的应用 | 公开课视频内容分享总结

    (SGPN)南加州大学 phd 王薇月:深度学习在点云分割中的应用 | 公开课视频内容分享总结 本博客基于论文:SGPN: Similarity Group Proposal Network for ...

  4. PDF课件下载!北京大学公开课《数据结构与算法Python版》

    北京大学公开课<数据结构与算法Python版>,面向具有Python语言程序设计基础的大学生和社会公众,介绍常见的基本数据结构以及相关经典算法,强调问题-数据-算法的抽象过程,关注数据结构 ...

  5. 怎么提取pdf中的表格数据_如何从pdf第1部分中提取表格数据

    怎么提取pdf中的表格数据 In this article, we talk about the challenges and principles of extracting tabular dat ...

  6. python提取html表格_想知道世界谁最有钱?3行Python代码告诉你

    想了解世界谁最有钱吗? 维基百科有专门的网页来描述世界最有钱的人. 当然,为了快速和精确定位符合预期的结果,用Python来爬取网页并分析是一个不错的办法. 但你知道吗?Python中用于执行Web爬 ...

  7. orm提取指定列_使用ORM提取数据很容易! 是吗?

    orm提取指定列 介绍 几乎所有系统都以某种方式与外部数据存储一起运行. 在大多数情况下,它是一个关系数据库,并且通常将数据获取委托给某些ORM实现. ORM涵盖了很多例程,并且带来了一些新的抽象作为 ...

  8. java取出字符串中的后四位_[原]Java面试题-将字符串中数字提取出来排序后输出...

    [Title][原]Java面试题-将字符串中数字提取出来排序后输出 [Date]2013-09-15 [Abstract]很简单的面试题,要求现场在纸上写出来. [Keywords]面试.Java. ...

  9. 谷歌浏览器网页表格复制一列_如何冻结或隐藏Google表格中的列和行

    谷歌浏览器网页表格复制一列 The greater the number of rows and columns in your Google Sheets spreadsheet, the more ...

最新文章

  1. java核心技术读书笔记1
  2. 目的港无人提货的法律风险及风险承担
  3. 第一章:前端视角——js运行环境之node.js基础入门
  4. JavaScript JSON操作
  5. poj 2398 Toy Storage (计算几何,判断点和线段关系)
  6. 骗子公司陆续公布中...
  7. postgre管理员 无法访问表_postgresql – 授予用户对所有表的访问权限
  8. angular学习笔记(九)-css类和样式2
  9. (Origin)设置图例位置
  10. 简单排序---冒泡排序
  11. java us ascii,在Java中,哪种编码方案是8位US ASCII?
  12. python界面打开为什么是黑的_Pycharm设置界面全黑的方法
  13. 征途2经典版服务器双线哪个稳定,《征途2》11月14日全区服务器版本更新公告
  14. 10分钟学会发送邮件到指定邮箱
  15. java中modifier_Java Modifier工具类
  16. 我,晋升为阿里P9,越想越后怕...
  17. MATLAB系统仿真其三:Ornstein-Uhlenbeck(OU)噪声
  18. Hadoop集群搭建(所需软件安装包已上传发布)
  19. 从一个class文件深入理解Java字节码结构
  20. 监管总局严打虚假检测报告

热门文章

  1. android github轮播图,GitHub - ZTJzzz/Banner: Android轮播图
  2. android drawLayout抽屉布局
  3. 搜狐畅游笔试题:1. 美丽的项链(动态规划) 2.多线程并发交替输出
  4. PHP中使用CURL实现Get和Post请求方法
  5. WPF教程六:布局之Grid面板(转)
  6. Bootstrap 图片
  7. 冲刺阶段(二) 第六天
  8. shell 除法 小数点
  9. java es api jar包_Elasticsearch 搜索服务器 Java API 使用详解
  10. Python之网络爬虫(验证码、代理IP、防反爬策略、封装一个抓取页面的函数)