资讯动态

CTPN文本检测算法全解析:从原理到工程实践

发布时间:2026/10/16 17:16:49 来源:尧图企业网站定制
做 OCR 项目这几年我在文本检测这一步上花的时间比对识别模型本身花的时间还多。原因很现实识别模型再强检测框给歪了、切碎了、漏掉了后面的一切都是白搭。今天要聊的 CTPN全称 Connectionist Text Proposal Network是我最早系统吃透、也反复用在真实业务里的一个文本检测网络哪怕后来各种更快的检测头层出不穷它在水平文本场景下的稳定性和可解释性依然是很多项目默认的首选。这篇把 CTPN 从设计思路到训练部署的完整链路讲透适合刚入门 OCR 的算法同学也适合准备在老项目里替换或改进检测模块的工程师。1. 为什么通用目标检测器做不好文本检测1.1 文本不是“物体”而是细长的序列我见过不少团队在接到文本检测需求时第一反应就是把 Faster R-CNN、SSD 甚至 YOLO 拉过来直接训。短文本、印章这类相对方正的场景还能凑合一旦遇到说明书上的小字、票据里的长串号码、或者海报上占了半屏的标语通用检测器就全线崩溃。问题出在哪出在我们对“目标”的定义完全不同。通用目标检测面对的是“物体”瓶子、汽车、人、猫狗这些目标有明确的封闭轮廓长宽比基本都在 0.5 到 2 之间。而文本行不是这样的一句话可能只有 4 个字符也可能有 50 个字符长宽比从 1 到 30 甚至更高字符之间有大小写、笔画疏密、空格形态极度不规律。你很难让一个为矩形物体设计的 anchor 体系去覆盖这种极端长宽比分布也很难让一个滑动窗口感受到“这一串东西是一个语义整体”。更麻烦的是文本行内部没有清晰的物体边界。通用目标检测器里目标就是目标背景就是背景RPN 只需要区分这两类。文本行不一样它内部有很多空白和半字符区域同一个文本行里并不是每个像素都属于“文字”但检测框却要完整包住它们。这就导致模型学到的特征响应经常是离散的、碎片化的要么只激活了每个字符所在的小块要么把背景也一起激活了。1.2 直接套用 Faster R-CNN 会踩到什么坑就算你把 Faster R-CNN 的 anchor 长宽比改成 1:5、1:10、1:20硬让它去拟合长条形文本行还是会遇到几个绕不开的问题。第一个是正负样本严重失衡。极端长宽比的 anchor 数量天然庞大但真正落在文本行上的比例极低大部分长条 anchor 跨在背景上。训练时分出的正样本太少负样本太多模型会偏向把一切判定为背景召回率惨不忍睹。第二个是回归目标不稳定。文本行的高度和宽度变化范围极大横跨几十个像素的长文本行其坐标回归难度远超一个标志牌或者一个水杯。小误差在短文本上可能只偏几像素在长文本上就可能让右侧端点偏出半个框导致下游识别直接把最后几个字符切掉。第三个是感受野的矛盾。要判断一个像素是不是文本序列的一部分你需要看到它左右两侧的上下文但通用检测器里的卷积感受野往往是方形的、对称的对水平方向的序列信息并不敏感。结果就是模型经常把单独一个汉字当成一个有效目标而无法确认它到底属于哪一行。我当时在实际项目里最直观的体验是用通用检测器跑一段 30 个字符的发票号它会输出七八个碎框每个框认定里面是“文字”但没有任何一个框能把整行串起来。这不是调参能解决的问题是设计范式的问题。1.3 CTPN 的破局思路把检测框拆成文本片段CTPN 最核心的决策是不再试图一次性预测完整的文本行框而是把文本行拆成一连串固定宽度的“文本片段”每个片段只负责预测自己的高度和中心位置最后再做一次连接把相邻的片段拼成完整的文本行。用大白话说这就像把一句话拆成一行积木每块积木只管自己那一小块拼起来就是完整的意思。这里面有两个关键转变。第一个转变是从“矩形检测”变成“序列预测”。文本行天然是序列结构字符从左到右依次排列有强上下文关系。CTPN 把网络设计成了 CNN 提取特征 Bilstm 建模序列的结构这就比纯卷积网络更贴合文本的本质。第二个转变是让 anchor 适应文本的局部一致性。文本行的高度在局部范围内是基本恒定的所以 CTPN 只使用“垂直方向”的 anchor——固定宽度、变化高度只回归每个 anchor 的中心 y 和高度。这个设计大幅压缩了回归空间让模型更容易收敛也让后续的文本行连接有了物理依据。所以从思路上看CTPN 不只是一个检测模型它把文本检测重新定义成了“检测密集 anchor 序列 序列连接”的组合任务。这种定义方式让它在水平文本场景下天然比通用检测器更稳。2. CTPN 网络结构拆解从骨干网络到三路输出2.1 骨干网络VGG16 特征提取与感受野考量CTPN 的骨干网络用的是 VGG16准确说是用到 conv5_3 这一层输出的特征图。图片输入网络之前会先缩放到固定尺度常见做法是把高度缩放到 720 左右或者宽度限制在 960 以内具体看显存和业务目标大小。VGG16 的 stride 到这里是 16也就是说原始图像上 16x16 的区域在特征图上对应一个像素点。为什么不选更轻的骨干也不选 ResNet历史原因是一部分但从效果上看VGG16 的 512 通道特征在文本检测这种任务上非常够用。文本检测需要的是对笔画边缘、字符纹理、局部间距的精细感知这些特征在浅层和中层卷积里响应明显VGG16 这种“深而窄”的结构反而比较容易稳定训练。换 ResNet 做骨干也不是不行但梯度路径更复杂早期 CTPN 开山时大家没有太多现成的预训练权重可用VGG16 就是最省事、最稳的选择。我自己的经验是骨干网络的选择要看你处理的文字尺度。如果业务里有很多小字就需要注意 VGG16 的 stride 16 会把小字的细节磨掉很多特征图上一个小字可能只剩一两个响应点。这种情况下要么放大输入图像要么换更浅的骨干配合多尺度特征不能指望 VGG 硬扛。2.2 序列建模Bilstm 为什么对文本有效CTPN 真正区别于当时其他检测器的地方是在卷积特征之上接了一个双向 LSTM。这一步在很多人看来是“玄学”但它有非常扎实的依据。卷积神经网络在任意一层上的输出光看一个局部窗口是分不清“这个像素是文字中间还是文字边缘”的。文本行的语义要靠上下文才能确定比如你看到“地址”两个字左侧可能是“收件人”右侧可能是具体内容模型如果能感知到这种顺序关系就能更准确地把同一行的文字聚在一起。Bilstm 的作用就是提供这种跨距离的序列记忆能力。具体实现上CTPN 把特征图按宽度方向看成一条序列。假设特征图是 H x W x 512每个位置沿宽度方向展开就得到一个长度 W 的序列每个时间步对应一个特征列向量。把这条序列送进双向 LSTM每个方向 128 个隐藏单元两个方向拼接后得到 256 维再接一个全连接层映射到 512 维。实测下来去掉 Bilstm 直接接全连接短文本检测差异不大但连续长文本的召回会明显下降尤其是行内有空格、字间距较大或者排班很密的场景断行率能涨十几个点。原因很直观卷积只能看到固定感受野范围内的局部信息而 LSTM 可以在几十甚至上百个像素的范围内传递“我还在同一行”的上下文信号。这也是 CTPN 在长文本上比同期很多纯卷积方案强的原因。2.3 三路输出分类、垂直回归、边线细化Bilstm 输出接全连接层之后网络会分成三个分支对应三种不同任务。这是理解 CTPN 的关键很多人看论文容易把这三分支混在一起。第一路是分类分支输出 2k 个通道。这里 k 是每个特征点上的 anchor 数量默认是 10 或 11 个2k 对应每个 anchor 的“是文字 / 非文字”两个得分。这一路直接决定这个位置有没有文本片段存在。第二路是垂直回归分支同样输出 2k 个通道。每个 anchor 回归两个值中心点 y 坐标的偏移量以及高度的缩放量。因为文本片段宽度固定为 16 像素所以不需要回归 x 和 w只需要把每条“竖条”放到正确的纵向位置、调整到真实文字高度即可。第三路是边线细化分支对每个 anchor 输出其左右端点的水平偏移用来精细化文本行的左右边界。别小看这一路后面文本行构造时如果只靠 16 像素宽的 anchor 去对齐边界误差会不断累积最后整行的右边界可能偏出几个像素甚至更多。边线细化就是用来修正这种累积误差的我在证件类项目里实测过开着这一路分支下游识别对最后几个字符的切分错误率能降一半以上。三个分支共享同一份卷积和 Bilstm 特征只有最后的全连接层参数不同所以推理时计算量几乎没有额外增加。这就是 CTPN 能保持不错速度的原因之一。3. 核心机制vertical anchor 与坐标回归3.1 固定宽 16 像素的 anchor 设计CTPN 里 anchor 的设计很特别它摒弃了通用检测器里那种“各种长宽比、各种尺寸”的 anchor 组合只保留了一种形态宽度固定为 16 像素、高度在一定范围内变化的竖条。这个 16 是 VGG16 在特征图上的采样步长对应的原始图像尺寸换句话说特征图上的一个点对应原图一个 16x16 的区域那么 anchor 宽度定为 16正好让每个特征点对应一个文本片段位置。那高度怎么定CTPN 在每个特征点上同时生成 k 个不同高度的 anchor论文里 k 取 10 或 11高度值按照对数均匀分布在十几个像素到两三百个像素之间。这样设计的原因很直接训练前你不知道数据里文字有多高所以先用一组覆盖范围较广的候选高度让网络去选再通过回归精调。真正落地时不要死抄论文里的那组高度应该先对自己的数据集做一次文字高度统计然后用统计分布重新设计 anchor 高度。比如电商小票里的文字普遍只有 15 到 25 像素而门头招牌上的文字可能高达 300 像素anchor 覆盖范围差着一个数量级。这里有一个容易忽略的换算问题。anchor 是在特征图坐标系里定义的但回归目标和最终输出都要映射回原图。由于 stride 是 16特征图坐标乘 16 就是原图坐标这个换算看起来简单但一旦涉及多尺度输入或者裁剪推理就特别容易出错。我在工程里吃过一次亏把特征图坐标映射回原图时忘了乘 stride导致所有检测框整体缩小了 16 倍最后一句“请重新缩放输入”排查了大半天。3.2 垂直 IoU 匹配与回归目标CTPN 匹配 anchor 和真实框的时候用的不是通用检测里的完整 IoU而是只算垂直方向的 IoU。这个设计说出来你可能觉得简单但它非常关键。为什么只算垂直方向因为 anchor 宽度固定为 16 像素而文本行通常比 16 像素宽得多一个 anchor 只覆盖文本行的一部分水平区间。在这种情况下如果还按完整 IoU 去匹配那几乎不可能有 anchor 和整个文本行框的 IoU 超过阈值。所以 CTPN 干脆只比较 y 方向上的交并比。假设 anchor 的 y 区间是 [ya1, ya2]真实框的 y 区间是 [yt1, yt2]垂直 IoU 就是这两个区间交集长度除以并集长度。具体匹配规则是垂直 IoU 大于 0.7 的 anchor 作为正样本小于 0.5 的作为负样本。注意还有一个附加条件anchor 的中心 y 坐标需要落在真实文本行的 y 范围内否则即使垂直 IoU 很高也不能算正样本这能防止 anchor 歪着匹配到文本行边缘。回归目标是两个值中心点 y 的偏移量 v_c以及高度缩放量 v_h。计算公式可以理解为v_c (cy_gt - cy_anchor) / h_anchor v_h log(h_gt / h_anchor)这里 cy_gt 是真实文本行中心 ycy_anchor 是 anchor 中心 yh_anchor 是 anchor 高度h_gt 是真实高度。除以 h_anchor 是为了把偏移量归一化高度用 log 而不用直接差值是因为高度跨度可能很大用对数可以让小文字和大文字的回归误差处于可比量级。训练时回归分支的目标就是用 smooth-L1 损失去拟合这两个值。我在训练初期踩过一个常见的坑只看分类得分高就以为检测好了其实垂直回归没收敛导致所有预测框的高度一致偏大或偏小。文本行连接的时候又依赖 height 一致性最后整个文本行构造成了一团乱麻。所以训练时建议单独监控垂直回归的误差项而不是只看总 loss。3.3 side-refinement 到底是干嘛的side-refinement 这一路在不少讲解里被一笔带过但它在精度敏感场景里非常重要。当我们把若干个 16 像素宽的 anchor 拼成文本行时行首和行尾这两个 anchor 的边界并不一定准确对齐真实文本行的左右边界。因为 anchor 的 x 坐标是按固定步长滑动的文本行右边界可能落在 anchor 的中间而不是正好在边界上。如果直接拿 anchor 的 x1 和 x2 当文本行边界误差就是半个 anchor 宽度级别累计下来可能偏出 8 到 16 像素。side-refinement 的做法是对行首和行尾的 anchor 分别回归一个水平偏移量让最终输出的文本行框能精确对齐真实左右边界。这个分支的回归目标同样用 smooth-L1 损失。在车牌、身份证号、二维码下方一长串数字这类场景里边界哪怕偏 2 个像素识别结果的置信度都会明显下降所以这一步属于“增加少量计算量换回大块精度收益”的典型操作。4. 文本行构造与后处理4.1 从 proposal 到文本行贪心连接算法模型输出的是一堆“文本片段”每个片段有自己的预测框、文字得分和边线偏移。要让这些片段变成一句话就得做文本行构造。CTPN 的做法是贪心连接不是全局最优但在实践中非常有效。第一步先过滤掉低置信度的 anchor通常阈值设 0.7。这一步能去掉大量背景碎片。第二步对所有剩余 anchor 按分类得分从高到低排序得分最高的那一个作为新文本行的起点。第三步逐个检查当前文本行的最后一个 anchor 和下一个候选 anchor 是否满足连接条件。条件有两个核心指标垂直重叠度和水平距离。垂直重叠度用两个 anchor 在 y 方向上的 IoU 衡量要求大于 0.7水平距离则要求两个 anchor 的 x 方向间隔不能太大论文中的常见设定是两个 anchor 之间不允许隔开超过 2 倍 anchor 宽度。满足条件的 anchor 就拼接到当前文本行末尾然后继续向下一个候选扩展不满足就跳过直到没有可连接的 anchor再开始一个新的文本行。第四步每个文本行内所有 anchor 的得分取平均作为该行的置信度行内做一次 NMS去掉相互重叠的重复框最后用 side-refinement 的输出精细调整整行的左右边界。整个后处理过程几乎不用 GPU纯 CPU 也很快。伪代码大概长这样sort proposals by score desc for each proposal p: if p.score 0.7: continue if p is already assigned: continue start new line with p while True: find unassigned proposal q that: q is the nearest right neighbor of line tail vertical IoU(p_tail, q) 0.7 horizontal distance 2 * anchor_width if found: append q to line else: break这个流程看起来简单但有几个细节决定成败。第一个是“只向右扩展”还是“双向扩展”原论文是向右扩展因为文本行有明确的方向性。第二个是垂直 IoU 的阈值它不是随便定的要保证同一个文本行里字符高度一致阈值设太低会把不同高度的文字混进同一行设太高则会把同一个文本行拆成好几段。4.2 阈值选择与后处理踩坑实录我最早用自己的数据集跑 CTPN 后处理时最重要的三个阈值来回调了两周最后总结出一套经验。得分阈值上0.7 对多数场景是个不错起点。如果文本比较密集、字符笔画细、或者图片有噪声可以适当降到 0.6 甚至 0.55但低于 0.5 以后背景碎片会大量混入连接过程文本行之间容易被横穿连成一条横线非常难清洗。如果场景里文字很大、很清晰阈值可以拉到 0.8 以上减少误检带来的后处理成本。垂直 IoU 阈值上0.7 是论文默认值。我自己的体感是文字大小比较均匀的印刷体0.7 很稳手写体或者字体大小参差不齐的票据可以降到 0.5 到 0.6否则一行字里稍微大一点的字母会让行内连接直接断掉。水平距离阈值是最容易踩坑的地方。它决定哪些相邻 anchor 可以连成一行。25 像素到 35 像素之间是常见区间。如果文本行内部有大段空格比如发票号“1234 5678 9012”中间的空格这个阈值设太小就会把一行拆成两段。但设太大又会出现跨行连接尤其垂直方向有多个文本行的时候。我的做法是先按文本高度动态计算水平距离阈值比如用文本行高度的一半作为参考而不是全图用一个固定值效果会好很多。另一个经常被忽略的点是文本行连接之前最好先做一个基于分类得分的小范围 NMS。因为相邻的 anchor 可能对同一个字符响应得分的都是 0.9如果不先压掉重复框行内会出现一堆几乎完全重叠的检测结果虽然不影响最终框但会影响文本行的平均得分和边线偏移回归的稳定性。5. 训练细节与工业落地经验5.1 损失函数与正负样本采样CTPN 的训练损失由三部分组成分类的交叉熵损失、垂直回归的 smooth-L1 损失、side-refinement 的 smooth-L1 损失。总损失就是这三者的加权和权重通常都设为 1.0不需要太多调参。分类损失处理的是每个 anchor 是文字还是背景这是标准的二分类问题。回归损失只对正样本计算因为只有正样本才对应真实的文本行负样本的回归目标是无效的。实际操作中我建议把回归损失只在正样本掩码上计算并且在代码里显式确认掩码和损失形状一致不然很容易出现所有 anchor 都参与回归的情况那损失虽然会降但检测结果一塌糊涂。正负样本采样是文本检测里不可忽视的一环。一张密集文字图片上正面 anchor 可能只占所有 anchor 的 1% 甚至更低如果全量参与训练模型会严重偏向输出“非文字”。常见做法是在每张图的 anchor 里随机采样一批保持正负样本比例大约 1:1。这里有一个细节不要只采样简单的负样本那些靠近文字边缘、含有偏旁部首或部分字符的负样本是真正难分的样本最好保留下来。如果正负样本失衡特别严重可以上在线难例挖掘把损失最大的 128 个负样本挑出来专门训练这种方式在发票、证件这种版式复杂的图片上提升明显。我在实际项目中还发现分类分支和回归分支的训练节奏最好错开一点点。刚开训的前几个 epoch模型还在学“哪里可能有文字”这时回归分支容易因为目标不稳定而震荡建议前 2500 次迭代只训练分类分支等分类基本收敛后再放开回归分支联合训练。这个技巧没有写进论文但实践里能明显减少早期 loss 爆掉的情况。5.2 数据准备与多尺度训练CTPN 训练用的数据格式跟通用检测器不太一样。标注时通常需要给出文本行的 box 坐标最常见的是用四个顶点坐标表示一个四边形。CTPN 内部处理时需要把四边形转为外接矩形或者至少提取出 y 方向的上下边界作为回归目标。这里有一个容易犯的错如果文本行是倾斜的直接把四边形取外接矩形会带进来大量背景区域导致训练时正样本 anchor 覆盖的区域不只是文字本身。我的做法是训练前先对整张图做轻度旋转矫正把文本行尽量摆正或者对倾斜文本单独扩展样本让模型学会区分“倾斜文字”和“背景”。公开数据集方面最常用的有场景文本检测的标注数据比如水平文本为主的数据集、合成文本数据集用字体渲染生成的百万级样本以及自己标注的业务数据。合成数据对提升首轮训练的基准效果特别好因为你可以无限生成字型、颜色、背景的排列组合。但合成数据和真实数据的分布差异很大工业落地时一定要用真实数据做微调不然模型在简单背景上很准一到真实弱纹理背景上就疯狂漏检。多尺度训练方面我建议把输入图像高度随机缩放到 600 到 900 之间宽度等比缩放同时限制最长边不超过 1200。这样模型能适应不同尺寸的文字。需要特别注意的是anchor 的原图尺寸是在模型输入时确定的多尺度训练必须在每个 epoch 动态调整 anchor 的尺度范围或者把 anchor 定义在特征图坐标系上从而随输入尺度自动伸缩。工程里建议用后者代码更统一也避免版本管理时出现边界不符。5.3 推理加速与模型压缩CTPN 在推理阶段其实不慢因为整张图只需要过一次 VGG16 前向Bilstm 虽然后处理里有依赖但序列长度就是特征图的宽度计算量不大。在普通桌面级显卡上720p 的图片推理一次大约 20 到 30 毫秒足以应对不少实时场景。落地时比较麻烦的是模型转换。Bilstm 在转 ONNX 或 TensorRT 的时候是个难点很多转换器不支持动态序列长度或者 LSTM 算子。我推荐的做法是转换前先固定输入尺寸把 Bilstm 展开成固定时间步的循环结构或者干脆把它替换成两个方向的一维空洞卷积。一维空洞卷积在等价感受野下能近似模拟 Bilstm 的序列建模能力推理速度更快精度损失通常在 1 到 2 个点以内适合对延迟敏感的场景。另一个压缩思路是把 VGG16 换成一个轻量级分类骨干比如 MobileNetV3 或 ShuffleNetV2接一个相同结构的检测头。实测下来模型体积可以从 100MB 级别降到 20MB 左右推理速度提升 2 到 3 倍精度损失视业务场景在 3 到 6 个点之间。如果业务不需要极高的召回率这种精度换速度的取舍非常划算。6. 常见问题与调优实战6.1 小文字漏检怎么破CTPN 处理小文字困难核心原因在于 stride 16 让特征图上的小文字响应过于稀疏。一个 10 像素高的字在 stride 16 的特征图上可能只覆盖一个像素点即使 VGG 中途的卷积保留了更多信息到了最终检测特征图上这个字的存在感也已经被压得很弱。我常用的方案有三条。第一放大输入图像把高度从 720 提到 1000 以上小文字的像素占比上来后检测难度直接降低代价是显存占用和推理时间上升。第二缩短骨干网络的 stride比如把 VGG 的 conv5 层 stride 改为 8 或者 4这样特征图分辨率更高小文字保留信息更多注意这会改变所有坐标映射关系需要同步调整。第三引入 FPN 结构把高层语义特征和低层高分辨率特征融合让检测头同时看到全局和细节这是目前很多新检测器默认的做法。针对小文字场景最好的办法是三者搭配适度放大输入、降低 stride、加入跨层融合。单纯调阈值是解决不了本质问题的阈值只是后处理信息损失发生在骨干网络前向过程中。6.2 文本行断行与粘连断行和粘连是后处理阶段最常见的两类问题它们往往是同一个参数的两端得分阈值、垂直 IoU 阈值、水平距离阈值。断行最典型的表现是一个完整的文本行被拆成两段甚至多段。原因通常是水平距离阈值设太小行内有空格时就断了或者得分阈值设太高行尾置信度稍低的 anchor 被过滤掉。排查方法很简单在预测结果上把得分低于阈值的 anchor 可视化出来如果行尾明明有连续响应却因为分数不够被掐断降阈值如果中间有空隙导致连接条件不成立调大水平距离阈值。粘连则相反多个文本行或者文本行与背景碎片被连成了一条诡异的长横线。原因通常是垂直 IoU 阈值设太低两个垂直方向有重叠的单行文字被混在一起或者得分阈值太低背景碎片也被当成候选。处理粘连时先收紧垂直 IoU 阈值再调高得分阈值。如果这两个参数已经调得很紧还是粘连就该怀疑你的训练数据里文本行之间的间隔太小导致模型对“行间距离”的敏感度不够这时需要补充该类样本或者加大输入图像分辨率让行间距离在特征图上更明显。行与行间距特别小的票据、表格场景我还会额外加一个后处理对构造出的文本行做一次长宽比检查把明显不正常的长条宽度超过全图 60% 且高度浮动特别大拆开或者丢弃。虽然这个方法不够优雅但能快速清理一大批粘连结果。6.3 旋转与倾斜文本怎么办CTPN 本质上是为水平文本设计的。anchor 竖条只能感知垂直方向和水平方向的偏移无法表达旋转角度。所以遇到倾斜超过 15 度到 20 度的文本哪怕肉眼看起来只有轻微歪斜检测结果也会出现框不够贴边、文本行连接错乱等问题。面对旋转文本最直接的方案是旋转矫正先用一个轻量方向分类或回归模块估计整张图/文本区域的旋转角度再对图像做逆旋转变换让文本变成近似水平最后送进 CTPN。这种方案在文档扫描、身份证拍照这类场景里非常成熟而且因为旋转角度通常在正负 30 度以内角度估计的误差不会对检测造成致命影响。如果文本是任意方向甚至弯曲的比如招牌上的弧形字、商品包装上的环绕文字CTPN 就基本无能为力了。这种情况应该直接上支持四边形输出的检测方案比如 EAST、DBNet 之类。它们通过直接预测文本框四个顶点天然支持旋转和任意四边形但代价是后处理逻辑更复杂、对极长文本的连接能力反而可能不如 CTPN 这种基于竖条连接的方案稳。所以“CTPN 旋转矫正”和“四边形检测器”没有绝对优劣完全取决于你的文本形态分布。7. CTPN 的局限与后续演进7.1 还有哪些坑是绕不开的CTPN 虽然经典但它的边界条件很明确理解这些局限能帮你避免在错误的场景里死磕。垂直方向倾斜过大的文本时CTPN 的 anchor 匹配会出问题。因为真实文本行的 y 区间在倾斜时会“歪”一个垂直竖条的 anchor 很难同时命中倾斜文本的上下边缘导致正样本不足、回归目标不稳定。用 CTPN 检测竖排文字几乎不可行竖排文字本质上是把“行”和“列”交换了CTPN 的序列建模方向是水平方向的完全不适用。曲线文本和环绕文本同样无能为力。文本行构造算法默认行是近似直线无法处理弧形或折线。你可以在后处理里加圆弧拟合但这就不是 CTPN 本身能解决的问题了。超长文本行也容易断裂。虽然 Bilstm 能提供上下文但 anchor 之间的连接条件在超长文本上会因为字符间距、换行、中间插图等干扰而中断。一个文本行超过 80 到 100 个字符时断行概率会明显上升。7.2 从 CTPN 到 EAST、DBNet 的演进逻辑理解 CTPN 之后再去看后来的文本检测方案会发现演进脉络非常清晰。EAST 把检测变成了直接回归文本框四边形的全卷积任务利用特征融合和多方向框回归绕过了 CTPN 里“先检测竖条再连接”的中间步骤速度更快、支持任意四边形。但 EAST 在处理长文本时回归目标包含大量坐标值训练难度和模型对精确边界估计的要求都更高。DBNet 则把文本检测建模成分割任务引入可微分二值化让模型自己学习阈值。它天然适合弯曲文本和任意形状文本语义信息丰富。但分割任务的缺点是容易把相邻文本行粘连成一个掩码需要精细的后处理去分离贴在一起的文字。DBNet 的工程落地比 CTPN 繁琐不少涉及到掩码连通域分析、轮廓提取、四边形拟合等多个环节。CTPN 的思想在这些后来的方案里并没有消失对长文本的序列连接、对 anchor 垂直方向的约束都演变成了各种变体里的“先验知识”。我自己在搭建一个场景文字识别系统的时候最终还是把 CTPN 作为 baseline。它也许不是最先进、最快的方案但它的每一部分都可以单独解释、单独调试这种“我清楚模型在想什么”的可控感在工业项目里非常珍贵。换任何新架构我都知道自己优化的是特征提取、序列建模、还是后处理连接这一步而不是在一个黑盒里反复试参数。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑