前言
做视频后期处理的时候,有一类需求特别常见:把视频里的字幕、台标LOGO、比分牌这些”包装元素”给擦掉。但在动手擦之前,有个更关键的问题——你得先精确地找到这些东西在哪儿。这个”找”的过程,远比想象中复杂。字幕会出现又消失,LOGO从头到尾都在,比分牌的格式五花八门,还有些包装是半透明的……每种类型都需要不同的检测策略。这篇文章的重点不在擦除本身,而是聊聊怎么智能地检测出这些需要被擦除的目标。
正文
一、整体流程:先检测,再擦除
视频擦除本质上是一个”检测 + 修复”的两阶段任务。检测阶段负责找到需要擦除的区域,生成精确的Mask;修复阶段拿着Mask把对应区域的像素”填”回去。这两个阶段的效果是乘法关系——检测不准,后面修复得再好也白搭。
在我的项目里,需要检测的目标主要分三大类:字幕、LOGO(台标)、包装(比分牌、角标等)。它们的视觉特征和时间特性差异很大,所以检测策略也完全不同。
整体的处理流程是这样的:先对视频做镜头切换检测,把视频切成一个个场景片段,获得关键帧索引;然后在每个场景内,分别跑字幕检测、LOGO检测和包装检测三条流水线;最后把三条线的Mask合并,送入擦除模块。
二、字幕检测:投票机制与先验逻辑
字幕的特点是:位置相对固定(通常在画面下方左右两侧)、有明确的文字特征、会随时间出现和消失。听起来好像不难检测,但实际踩的坑可不少。
基础检测:DBNet + OCR
第一步是用DBNet这类文字检测网络定位画面中的文字区域,再通过OCR识别出具体内容。但问题来了——画面里不只有字幕,路牌、招牌、广告牌上的文字也会被检测出来。怎么区分”真字幕”和”场景文字”?
投票机制
这是我觉得最关键的设计。对视频做整体采样检测,在一个时间窗口内统计每个区域被检测到文字的频率。字幕的特征是”出现一段时间又消失”,而场景文字是”一直在那儿”。通过投票统计,可以筛选出那些出现频率符合字幕特征的区域。
投票还分两个阶段:第一阶段用较高的阈值筛选出高置信度的字幕区域;第二阶段适当降低阈值,补充第一阶段漏掉的。为什么不一步到位?因为如果一次性把阈值调低,正确的区域会被淹没在错误区域里。分阶段划分,反而能得到更准确的结果。
先验逻辑
光靠投票还不够,还需要加一些”常识”来辅助判断:
- 位置先验:字幕通常只在画面左右两侧出现,如果中间也检测到了大量文字,说明可能是特殊场景(比如歌词字幕),需要单独处理。
- 行数筛选:正常字幕一般是一到两行,如果检测到的box合并后超过两行,可能是误检。
- 高度一致性:同一行字幕的文字区域高度差应该基本一致,高度差异大的大概率不是字幕。
- 角度过滤:box区域有明显角度的不认为是字幕区域——字幕几乎都是水平的。
- 编辑距离:通过OCR识别的字幕内容,用编辑距离找到字幕的切换点,保证帧间内容一致性。
另外还有一个强制模式(strict mode),对于多行字幕或特殊文字区域,直接对投票检测到的所有区域都做擦除,不再做复杂的筛选。
三、LOGO检测:底库匹配与局部特征
台标LOGO跟字幕完全不一样——它是”常驻”的,从头到尾都在那儿,位置和大小基本不变。
底库模板匹配
最直接的方案是建一个LOGO底库,把各个电视台的台标模板存好,然后用SIFT特征匹配来定位。具体流程是:对场景关键帧提取特征,跟底库里的模板做匹配,找到LOGO的位置。
但这里有不少细节要处理:
- 尺度一致性:匹配的时候对象的尺度要一致,尺度不一致会匹配不到。
- 局部匹配:一个底库模板可能匹配到画面中的多个位置(比如LOGO的一部分跟某个场景元素相似),需要新增局部匹配逻辑,防止一个模板匹配到多个LOGO但只保留其中之一。
- 半透明LOGO:这是最头疼的。半透明LOGO跟背景做了Alpha混合,用差值方案去检测的话误差很大,普通像素的干扰太强。目前的做法是结合颜色分布特征和时域稳定性来综合判断。
- 特殊字体LOGO:有些平台(比如B站、咪咕)的LOGO用了特殊字体,常规的文字检测反而会把它过滤掉,需要单独处理。
无底库方案
不是所有LOGO都能提前入库的。对于底库里没有的LOGO,我用的是静态区域分析——在整个视频里找那些”从头到尾都没怎么变过”的区域,大概率就是台标。但这个方案对半透明LOGO效果不好,因为半透明区域的像素值会随背景变化。
四、包装检测:体育比赛的特殊挑战
“包装”是个行业术语,指的是视频里叠加的图形化信息元素,比如体育比赛里的比分牌、球员名字、角标、广告条等。这类元素的检测是最复杂的,因为它们的样式千变万化,没有统一的模式。
包装的特点
跟字幕和LOGO不同,包装元素有几个棘手的特性:
- 格式多样:不同比赛、不同转播方的包装样式完全不同,没法用一套模板搞定。
- 动态变化:比分会变、球员名字会换、进球动画会弹出来,包装不是静态的。
- 位置约束:包装区域通常限制在画面的上下部分,但具体位置因转播方而异。
- 对称性:比分牌通常是左右对称的(两个队名分列两侧),这个先验可以利用。
检测策略
我的包装检测流程是这样设计的:
- 区域限定:先根据先验知识限定包装可能出现的区域(画面上下大概位置),缩小搜索范围。
- 底库匹配:跟LOGO检测类似,用底库模板做初步匹配。但包装的底库更复杂,因为同一个包装在不同时刻长得不一样(比分变了)。
- SAM2辅助:用SAM2(Segment Anything Model 2)作为匹配器,替代传统的底库匹配。SAM2的优势是用Mask级别的IoU做标准,比box级别的匹配更精确。当IoU非常大(阈值0.95)时认为是包装,但这个阈值太高会漏检,调低到0.8又会引入误检,需要反复调优。
- 对称性验证:利用比分牌左右对称的先验,统计检测区域内所有框的最大最小坐标,验证是否纵向对称。如果第一次包装出现时两边box位置对称,说明不是进球人名(因为进球人名只会在一边出现),同时确定了行数和基本格式,后续如果包装格式不一样则丢弃。
LOGO与包装的择优
LOGO和包装的检测区域经常会重叠。我的处理原则是:默认LOGO检测区域比包装检测区域更精准,所以当两者重合时,采用LOGO的检测结果。
五、工程优化:速度与准确率的平衡
检测流程跑通之后,工程化的优化同样重要。
- 多线程加速:镜头检测、字幕检测、LOGO匹配这些模块都做了多线程处理。线程全部使用8个,每个线程的采样数取0.1比例、最大10个,在速度和覆盖率之间取平衡。
- 按场景加载:按场景和窗口长度加载数据,避免一次性把整个视频读进内存。
- 黑边检测:只对场景关键帧做黑边检测,减少不必要的计算。
- 指定区域与自动检测并行:支持指定区域擦除和自动检测擦除同时执行,用户可以手动指定一些区域,同时让算法自动检测其他区域。
整体检测+擦除的速度从最初的14.6fps优化到了28fps左右,当然具体速度还跟需要擦除的帧数有关——有些视频字幕帧不多,速度就更快。
最后
参考文章:
DBNet: Real-time Scene Text Detection with Differentiable Binarization
SAM 2: Segment Anything in Images and Videos
IOPaint - Image inpainting tool powered by SOTA AI Model
声明
本文仅作为个人学习记录,由AI辅助编写。