ARTICLE DETAIL

资讯详情

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

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

【论文笔记】R2CNN 旋转区域 CNN 在场景文本检测中的配置与验证 1. 场景文本检测里R2CNN 到底解决了什么麻烦场景文本检测和普通目标检测最大的区别在于文字框很少是水平正放的。路牌、商品包装、广告牌上的文字经常带角度用水平 bbox 去框要么框进大量背景要么把文字切掉一截。R2CNNRotational Region CNN这篇论文的核心思路就是在 Faster R-CNN 的 RPN 之后把 RROIRotated 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_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite创建完 Key接入文档在这里里面有 base_url、鉴权头、请求体的完整说明建议先扫一遍再动手https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewriteAPI 的基础地址是https://taotoken.net/api注意这个地址不带任何查询参数直接作为 base_url 用。如果你要验证某个模型对旋转框坐标的理解能力可以先用模型对话页面快速试一条 prompt确认返回格式符合预期再写进脚本https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite如果你打算长期跑编码类任务、让 Agent 反复调用用 Coding Plan 更划算额度模型和按量调用不一样https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewriteKey 拿到后先别急着写 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( obbbox[:5] ) }], temperature: 0.0 } r requests.post( f{cfg[api_base]}/chat/completions, headers{Authorization: fBearer {cfg[api_key]}, Content-Type: application/json}, jsonpayload, timeoutcfg[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 最省事。工具接入这块统一走一个通道比每个服务单独配要省心得多尤其是当你同时要调多个模型做对比验证的时候。
返回列表