拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

【论文笔记】R2CNN 旋转区域 CNN 在场景文本检测中的配置与验证

【论文笔记】R2CNN 旋转区域 CNN 在场景文本检测中的配置与验证

1. 场景文本检测里,R2CNN 到底解决了什么麻烦

场景文本检测和普通目标检测最大的区别在于:文字框很少是水平正放的。路牌、商品包装、广告牌上的文字经常带角度,用水平 bbox 去框,要么框进大量背景,要么把文字切掉一截。R2CNN(Rotational Region CNN)这篇论文的核心思路,就是在 Faster R-CNN 的 RPN 之后,把 RROI(Rotated ROI)阶段做得更细:一方面用多尺度 pooling 适配不同长宽比的文字,另一方面在常规水平框回归之外,额外加一路倾斜框(inclined box)回归,用(x1, y1, x2, y2, h)五个量描述一个带方向的矩形。

如果你正在复现这篇论文,或者想在自己的场景文本检测任务里验证旋转框效果,真正卡住人的往往不是论文公式,而是工程落地:配置文件怎么写、RROI pooling 的三个尺度怎么设、倾斜框的五个参数怎么解码、跑完之后怎么确认检测框真的带角度而不是退化成水平框。这篇就围绕这些可复制的动作展开,配置骨架和验证步骤都会给全,工具接入部分统一走 TaoToken 的 Key/API 通道,方便你把调用链路先跑通再调模型。

适合谁看:做过基础目标检测、想上手旋转框检测的工程同学;正在复现 R2CNN 但被配置和验证卡住的人;以及需要一套统一 API 通道来管理模型调用和调试的开发者。下面从配置骨架开始,一步步给到能直接抄的片段。

2. 前置准备:用 TaoToken 统一 Key 打通调用通道

复现 R2CNN 这类论文,通常要跑两类东西:一类是本地训练/推理脚本,另一类是调用外部模型服务做对比验证或辅助标注。后者如果每个服务都单独申请 Key、单独记 endpoint,调试起来会很碎。我习惯把这类调用统一到一个通道上,TaoToken 就是干这个的:一个 Key 覆盖多种模型对话和编码能力,接入文档里给了标准的 OpenAI 兼容格式,改 base_url 和 api_key 就能用。

先拿到 Key。打开控制台页面,登录后在 API Keys 里创建一个新 Key,复制出来存好,后面配置里要用:

https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite

创建完 Key,接入文档在这里,里面有 base_url、鉴权头、请求体的完整说明,建议先扫一遍再动手:

https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite

API 的基础地址是https://taotoken.net/api,注意这个地址不带任何查询参数,直接作为 base_url 用。如果你要验证某个模型对旋转框坐标的理解能力,可以先用模型对话页面快速试一条 prompt,确认返回格式符合预期再写进脚本:

https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite

如果你打算长期跑编码类任务、让 Agent 反复调用,用 Coding Plan 更划算,额度模型和按量调用不一样:

https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite

Key 拿到后,先别急着写 R2CNN 的配置,用一条最小请求确认通道是通的。这一步能省掉后面大量「到底是模型问题还是网络问题」的排查时间。

3. 可复制配置:config.toml 与 settings.json 骨架

R2CNN 的配置分两块:一块是模型和训练相关的config.toml,一块是调用外部服务用的settings.json。先给config.toml,重点在 RROI pooling 的多尺度和倾斜框回归的开关。

# config.toml - R2CNN 复现配置骨架 [model] backbone = "resnet50" pretrained = true # RPN 阶段保持水平 anchor,旋转在 RROI 阶段处理 rpn_anchor_scales = [4, 8, 16, 32] rpn_anchor_ratios = [0.5, 1.0, 2.0] [rroi] # 论文核心:多尺度 pooling,适配横排/竖排/斜排文字 pool_scales = [[7, 7], [3, 11], [11, 3]] pool_mode = "avg" spatial_scale = 0.0625 # 1/16,与 feature map 步长对齐 [bbox_head] # 水平框回归分支 reg_hbb = true # 倾斜框回归分支,输出 (x1, y1, x2, y2, h) reg_obb = true obb_dim = 5 # 倾斜框回归损失权重,论文里与 hbb 联合训练 loss_weight_hbb = 1.0 loss_weight_obb = 1.0 [train] dataset = "icdar15" batch_size = 2 lr = 0.001 lr_step = [80000, 110000] max_iter = 140000 # 论文用了 1000 训练图 + 2000 自采集 + 增强,共约 39000 augment = true augment_scale = [0.5, 2.0] augment_rotate = [-30, 30] [test] score_thresh = 0.7 nms_thresh = 0.3 # 倾斜框 NMS 用多边形 IoU,不是水平框 IoU obb_nms = true

几个参数值得单独说。pool_scales里的[3, 11]和[11, 3]是论文针对长条形文字设计的,横排文字用[3, 11]更贴合,竖排用[11, 3],[7, 7]兜底。obb_dim = 5对应(x1, y1, x2, y2, h),其中x1, y1, x2, y2是 bbox 按顺时针方向定义的两个角点,h是倾斜框的高度。obb_nms = true很关键,如果这里用水平框 IoU 做 NMS,倾斜框会被错误抑制。

再给settings.json,用于统一调用通道:

{ "api_base": "https://taotoken.net/api", "api_key": "sk-你的Key填这里", "model": "gpt-4o", "timeout": 60, "max_retries": 3, "headers": { "Content-Type": "application/json" }, "tasks": { "coord_verify": { "prompt_template": "给定倾斜框五点坐标 {obb},判断是否构成有效旋转矩形,返回 true/false 和理由。", "temperature": 0.0 }, "label_check": { "prompt_template": "以下文本检测结果 {boxes},检查是否存在重叠超过 0.5 的框,列出冲突对。", "temperature": 0.0 } } }

api_base用https://taotoken.net/api,不要在后面拼多余路径。temperature设 0.0 是因为坐标校验这类任务要的是确定性输出,不是创意。tasks里预置了两个模板,后面验证阶段会用到。

4. 验证请求:确认旋转框真的带角度

配置写完,先做通道验证,再做模型验证。通道验证用一条最小请求:

curl -s https://taotoken.net/api/chat/completions \ -H "Authorization: Bearer sk-你的Key" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o", "messages": [{"role": "user", "content": "回复 ok"}], "temperature": 0 }'

返回里有choices[0].message.content且内容为ok,说明通道通了。如果返回 401,检查 Key 是否复制完整;返回 404,检查 base_url 是否写成了带路径的形式。

通道通了之后,验证 R2CNN 的旋转框输出。假设你的推理脚本输出了检测结果,格式是每行一个框:

x1 y1 x2 y2 h score

写个校验脚本,确认框不是退化成水平的:

import json import math import requests with open("settings.json") as f: cfg = json.load(f) def is_rotated(box): x1, y1, x2, y2, h = box[:5] # 两个角点连线与水平轴夹角 angle = math.degrees(math.atan2(y2 - y1, x2 - x1)) return abs(angle) > 1.0, angle def verify_with_api(box): payload = { "model": cfg["model"], "messages": [{ "role": "user", "content": cfg["tasks"]["coord_verify"]["prompt_template"].format( obb=box[:5] ) }], "temperature": 0.0 } r = requests.post( f"{cfg['api_base']}/chat/completions", headers={"Authorization": f"Bearer {cfg['api_key']}", "Content-Type": "application/json"}, json=payload, timeout=cfg["timeout"] ) return r.json()["choices"][0]["message"]["content"] # 读检测结果 with open("det_result.txt") as f: lines = [list(map(float, l.split())) for l in f if l.strip()] rotated_count = 0 for box in lines: rotated, angle = is_rotated(box) if rotated: rotated_count += 1 print(f"框 {box[:5]} 角度 {angle:.2f} 度,调用校验:{verify_with_api(box)}") print(f"共 {len(lines)} 个框,其中 {rotated_count} 个带角度")

跑完你会看到两类输出:一类是角度接近 0 的框,说明模型在这个区域没检测出倾斜;一类是角度明显非零的框,会带上 API 返回的校验结论。如果rotated_count为 0,说明倾斜框回归分支没生效,回去检查reg_obb是否为 true、obb_dim是否为 5、以及训练时loss_weight_obb是否被置零。

成功的结果长这样:

框 [120.5, 88.3, 210.7, 130.2, 24.6] 角度 23.41 度,调用校验:true,构成有效旋转矩形 框 [340.1, 200.8, 420.3, 205.1, 18.2] 角度 3.21 度,调用校验:true,构成有效旋转矩形 共 156 个框,其中 89 个带角度

89/156 这个比例在 ICDAR15 上属于正常范围,场景文本里确实有相当一部分是接近水平的。如果比例异常高(比如 150/156),要怀疑是不是把噪声框也算进去了,回去调score_thresh。

5. 本篇常见错排查

报错一:RROI pooling 输出维度不匹配。典型信息是RuntimeError: expected 4D input或通道数对不上。原因通常是pool_scales里某个尺度算出来的输出尺寸和后续全连接层不匹配。检查[3, 11]和[11, 3]是否被正确拼接,三个尺度的输出应该 concat 后送入 head,总维度是7*7 + 3*11 + 11*3 = 49 + 33 + 33 = 115每通道。如果 head 的输入维度写成了 49 或 121,就会报错。

报错二:倾斜框解码出 NaN。多半是h参数在训练早期为负或极小,开方时出问题。在解码函数里加个保护:

h = max(h, 1e-6)

同时检查loss_weight_obb是不是设得过大,导致梯度爆炸。论文里 hbb 和 obb 是联合训练,权重一般 1:1,不要随意放大 obb 的权重。

报错三:NMS 后框大量消失。如果obb_nms没开,用水平框 IoU 去抑制倾斜框,两个角度差 30 度但中心接近的框会被误判为高重叠。确认obb_nms = true,并且 NMS 实现用的是多边形 IoU。多边形 IoU 计算比水平框慢,但这是旋转框检测必须付的代价。

报错四:API 调用返回 429。说明请求频率超了。settings.json里的max_retries设成 3,配合指数退避。如果批量校验几千个框,建议先在本地用几何方法过滤掉明显水平的框,只把带角度的框送去 API 校验,能省大量调用。

报错五:ICDAR15 评测脚本报格式错误。R2CNN 输出的是五点格式,但有些评测脚本要的是四点多边形或cx cy w h angle。转换时注意(x1, y1, x2, y2, h)里h是框高,不是对角线长度。转四点多边形要先根据两个角点和 h 算出另外两个角点。

6. 接入与验证的收尾动作

把上面几步串起来,完整链路是:TaoToken 控制台拿 Key,接入文档确认请求格式,settings.json配好 base_url 和模板,config.toml配好 RROI 多尺度和倾斜框回归,跑推理脚本输出五点格式结果,再用校验脚本确认旋转框比例正常。这条链路跑通一次,后面换数据集或换 backbone 都只是改配置的事。

如果你在排障阶段卡在接入或鉴权上,优先看 API Keys 和接入文档这两个页面,大部分 401/404/429 都能在里面找到对应说明。需要长期跑编码和 Agent 任务的话,Coding Plan 的额度模型更适合反复调用。验证模型对坐标和格式的理解能力,用模型对话页面快速试 prompt 最省事。工具接入这块,统一走一个通道比每个服务单独配要省心得多,尤其是当你同时要调多个模型做对比验证的时候。

返回列表