├── Pre.pptx ├── src.cpp ├── README.pdf ├── annex.rar ├── img ├── 1.jpeg ├── 2.png └── 3.png ├── exe_file.rar ├── LICENSE ├── OCR.py └── README.md /Pre.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dinghow/OCR_on_Video/HEAD/Pre.pptx -------------------------------------------------------------------------------- /src.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dinghow/OCR_on_Video/HEAD/src.cpp -------------------------------------------------------------------------------- /README.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dinghow/OCR_on_Video/HEAD/README.pdf -------------------------------------------------------------------------------- /annex.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dinghow/OCR_on_Video/HEAD/annex.rar -------------------------------------------------------------------------------- /img/1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dinghow/OCR_on_Video/HEAD/img/1.jpeg -------------------------------------------------------------------------------- /img/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dinghow/OCR_on_Video/HEAD/img/2.png -------------------------------------------------------------------------------- /img/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dinghow/OCR_on_Video/HEAD/img/3.png -------------------------------------------------------------------------------- /exe_file.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dinghow/OCR_on_Video/HEAD/exe_file.rar -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 DinghowYang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /OCR.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import http.client, urllib.request, urllib.parse, urllib.error, base64, json,os 3 | 4 | ############################################### 5 | #### Update or verify the following values. ### 6 | ############################################### 7 | 8 | # Replace the subscription_key string value with your valid subscription key. 9 | subscription_key = '' 10 | 11 | uri_base = 'api.cognitive.azure.cn' 12 | 13 | headers = { 14 | # Request headers. 15 | 'Content-Type': 'application/octet-stream', 16 | 'Ocp-Apim-Subscription-Key': subscription_key, 17 | } 18 | 19 | params = urllib.parse.urlencode({ 20 | # Request parameters. The language setting "unk" means automatically detect the language. 21 | 'language': 'zh-Hans', 22 | 'detectOrientation ': 'true', 23 | }) 24 | 25 | # The source file of a JPEG image containing text. 26 | imgPath = '...\\captions\\' #Please enter the Path by yourself 27 | txtPath = '...\\outTest.txt' #Please enter the Path by yourself 28 | videoName = 'Game of Thrones' #Please enter the video name by yourself 29 | 30 | fo = open(txtPath, 'w') 31 | fo.write('The caption of '+videoName+'\n') 32 | 33 | #Process the images in a folder 34 | for filename in os.listdir(imgPath): 35 | f = open(imgPath+filename,'rb') 36 | body = f.read() 37 | 38 | try: 39 | # Execute the REST API call and get the response. 40 | conn = http.client.HTTPSConnection('api.cognitive.azure.cn') 41 | conn.request("POST", "/vision/v1.0/ocr?%s" % params, body, headers) 42 | response = conn.getresponse() 43 | data = response.read() 44 | 45 | # 'data' contains the JSON data. The following formats the JSON data for display. 46 | parsed = json.loads(data) 47 | print("Response:") 48 | print(parsed) 49 | #Write the data on output file 50 | fo.write(filename+'\n'+str(parsed)) 51 | conn.close() 52 | 53 | except Exception as e: 54 | print('Error:') 55 | print(e) 56 | fo.close() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 基础信息 2 | 项目网页:[15-OCR on video](http://studentclub.msra.cn/project/institute/10) 3 | 4 | 项目导师:Alan Ip, Chao Chen 5 | 6 | 项目目标:识别电视新闻、综艺、电视剧集等具体场景中的字幕文本 7 | 8 | 9 | 10 | 学校:同济大学 11 | 12 | 队伍名称:学习机器学习队 13 | 14 | 原仓库地址:[video-subtitle-recognition](https://github.com/zhongyuchen/video-subtitle-recognition) from zhongyuchen 15 | 16 | 最终获奖:[Outstanding Winner](http://studentclub.msra.cn/news2/9) 17 | 18 | # 项目文档 19 | 20 | Documented by zhongyuchen 21 | 22 | Recomposed by Dinghow 23 | 24 | ## 简介 25 | 26 | 本项目基于 OpenCV 以及 Azure 的 OCR 服务,成功完成了任务。程序分为两部分: 27 | 28 | - 基于 OpenCV 的字幕提取:利用多线程,使得读取视频和提取字幕并行; 在提取字幕方面,我们开发了一种算法,能够很好地剔除重复、无关的帧,提取出含有字幕的帧,并能滤掉背景 (使成黑色),仅使字幕(白色) 清晰显示。 29 | - 基于 Azure 的 OCR:读取上一步得到的图片文件,返回识别结果. 30 | 31 | 实践证明,我们的算法不仅性能优越,同时也得到了很好的结果。 **precision 最高达到了 100%,且 recall 也能接近 99%。处理接近 3 小时的电影,提取字幕仅用时 12 分钟。** 32 | 33 | ## 使用说明 34 | 35 | Windows 环境下在 powershell 下运行 36 | 37 | ```powershell 38 | > ./run.exe your_video_path subtitle_save_path 39 | ``` 40 | 41 | 需要输入两个路径: 42 | 43 | - your_video_path:待处理视频路径 44 | - subtitle_save_path:存放提取的字幕图片路径 45 | 46 | 然后打开OCR.py,调用Azure的OCR服务批处理字幕图片,获得txt文本,在OCR.py中,用户需要输入: 47 | 48 | `subscription_key`:Azure云服务所需要的key 49 | 50 | `imgPath`:字幕图片文件夹路径,即上一步的`subtitle_save_path` 51 | 52 | `txtPath`:输出的OCR后的字幕txt文件路径 53 | 54 | `videoName`:处理的视频名称(可选输入) 55 | 56 | 57 | 58 | ## 算法原理 59 | 60 | ### 字幕区域识别 61 | 62 | 我们采用传统的图像处理方法,能够很好的识别并定位出字幕的区域,同样也能判断是否存在字幕。 63 | 我们的算法可以用下面伪代码描述 (为了清晰起见,调用函数的名称与MATLAB 函数或者 OpenCV 函数一致): 64 | 65 | ![](https://github.com/Dinghow/15-TongJi-Team_LearnMachineLearning/raw/master/img/3.png) 66 | 67 | 算法的第 3-6 行,是本算法的核心内容。经过第 3 行的灰度化后,第4 行的 imadjust 图像增强是为了将图片的灰度映射到更紧密的一个范围中去,方便下面的处理,实践证明这一步对结果是有举足轻重的作用的。第 5行的 imopen 形态学开操作,是该算法的精髓。这一步可以将字幕区域模糊化,甚至可以做到直接融于背景色中。所以通过最后一步,也就是第六行的差分操作,就可以轻松得到清晰的字幕。其实大多数视频帧做到这一步,效果已经非常好了。 68 | 69 | 算法的 7-21 行,是进一步滤掉背景噪声,得到更为干净的字幕。首先通过算法第 7-8 行的形态学开操作和闭操作,使得字幕的区域能连通成一体。然后通过 9-10 行的一个寻找连通区域的函数,经过筛选,就可以锁定字幕所在的连通区域。我们确立了三条筛选的原则:一是连通区域的平均水平位置是在中央附近 50 像素以内;二是连通区域的底部不高于图片底部 30 像素;三是连通区域大小须超过 4000. 如果没有任何一个连通区域,或者不满足上述任一条件,那么判定为该图片不存在字幕,同时把不符合要求的区域变成黑色;若存在一个区域能满足上述所有条件,那么满足的区域就是字幕所在区域。这样,就得到了干净的字幕。 70 | 71 | ### 字幕去重 72 | 73 | 我们采取的提取策略是每 20 帧提取一张图片进行处理,其余的全都忽略。但是很多时候,一条字幕会跨很多帧。这样势必要解决一个去重的问题。 74 | 75 | 我们的解决策略是计算上一张处理后的字幕图片与当前处理后的字幕图片的余弦相似度。 76 | $$ 77 | cosine = \frac{dot(A,B)}{norm2(A)*norm2(B)} 78 | $$ 79 | 我们判定,$cosine > 0.5$ 的视为两张图片相同;$cosine < 0.5$ 的视为两张图片不同。因为我们滤掉了背景,所以这种方法对于字幕去重极为有用。那么,每当出现前一张和当前这张图片计算余弦相似度,出现 $cosine < 0.5$ 的情况,那么就保存当前这张图片;反之认为图像一致,不进行保存。这样就完成了字幕的去重。 80 | 81 | ### 生产者-消费者模型 82 | 83 | 为了提高程序的效率,我们并不是等视频处理函数读取完每帧图片后再进行处理,而是边读取视频,边处理图片。我们采用了著名的生产者- 消费者模型。 84 | 我们设置了一个队列,保存图片的矩阵头信息 (OpenCV 中的 Mat)。同时开了两个线程,一个读取视频流,每二十帧将图片的矩阵头压入队列中,此为生产者;另一个线程进行从队列中取矩阵头,处理图片,此为消费者。 85 | 86 | 为了防止多线程同时访问共享资源,我们设置了锁。利用 C++11 的`unique_lock` 和 `condition_variable`,可以保证队列线程安全。 87 | 88 | ### 性能与效果 89 | 90 | **示例:** 91 | 92 | 原图 93 | 94 | ![](https://github.com/Dinghow/15-TongJi-Team_LearnMachineLearning/raw/master/img/1.jpeg) 95 | 96 | 字幕提取图: 97 | 98 | ![](https://github.com/Dinghow/15-TongJi-Team_LearnMachineLearning/raw/master/img/2.png) 99 | 100 | 更多图片见附件 101 | 102 | - 性能上,我们对很多视频的字幕提取进行了测速,得到了一个平均值:每秒钟处理能力为 390 帧左右。 6 分钟就能处理完 1h30m 的视频 (Platform:CPU:i7-6700HQ,RAM:8G DDR4 2133Hz) 103 | - 效果上,除非是由于字幕出现不足 20 帧因而被略过的缘故,一般都能找到所有字幕。但是也会掺杂不是字幕的图片,不过一般这些“杂质”不能识别,因此对识别的结果不会产生影响。 104 | 105 | 识别结果见附件 output.txt. 106 | 107 | --------------------------------------------------------------------------------