资讯动态

EAST文本检测实战:从票据识别到四边形解码与后处理调优

发布时间:2026/10/26 2:05:46 来源:尧图企业网站定制
简介面向计算机视觉学习者与文本检测实践者的EAST模型资源包聚焦自然场景文字检测任务的复现与调试适合已具备一定深度学习基础、希望跑通EAST训练与推理流程的开发者参考使用。压缩包共约2000个文件、整体461.7MB以4019张jpg图像样本和2000个npy标注数据为核心辅以1006个txt说明与标签文件、12个Python脚本及多个h5模型权重文件另含少量xml、png与配置文件覆盖数据、代码、权重三类要素便于直接搭建实验环境。资源已有352人学习下载作者提供了可跑通的实现路径读者可据此理解EAST的标注组织方式、权重加载与检测输出流程并对照排查训练与推理中的常见问题快速完成从数据准备到结果可视化的完整验证。1. 从一张歪斜的票据照片说起EAST 文本检测能解决什么上周帮朋友处理一批手机拍的报销单据照片里发票被手指捏得歪七扭八背景还有桌面纹理和阴影。他原本想用通用 OCR 直接识别结果十张里有六张因为文本区域倾斜、粘连而识别失败。这类问题的根子不在识别模型而在检测环节——没有先把文本区域框准、框正后面的识别再强也白搭。EASTEfficient and Accurate Scene Text Detector就是专门啃这块硬骨头的它把任意四边形的文本区域检测压缩成一次前向推理不依赖候选框生成和逐像素后处理在自然场景、票据、路牌、包装盒这类文本方向不固定的图上表现稳定。这份「旷世east文本检测.zip」把模型推理、四边形解码、可视化输出串成了一条能直接跑的链路适合两类人一是想快速验证场景文本检测效果、拿结果去接下游 OCR 的开发者二是想读懂 EAST 后处理逻辑、准备在自家数据上微调或改结构的熟手。下面我按「能干什么 → 怎么跑 → 核心代码长什么样 → 怎么改」的顺序把这份资源拆开讲。2. 项目定位与技术选型为什么是 EAST 而不是通用检测框2.1 场景文本检测和通用目标检测的差别通用目标检测比如检测猫狗车辆输出的是水平矩形框但文本有个要命的特性它是有阅读方向的。一张倾斜 30 度的招牌用水平框去套框里会混进大量背景像素框外的文字又被切掉。EAST 的核心设计就是直接回归任意四边形或旋转矩形的四个顶点配合一个角度参数让框贴着文字走向走。这份资源沿用的正是这个思路网络输出一张 score map每个像素是不是文本加一组几何参数到四条边的距离和角度后处理阶段用 locality-aware NMS 把像素级预测合并成完整文本框。相比先做分割再找连通域的老办法它省掉了对阈值极其敏感的连通域分析速度也更容易做上去。技术栈上这类项目常见做法是 Python OpenCV 做图像读写和可视化深度学习框架用 PyTorch 或 TensorFlow 二选一。从「旷世」这个命名和国内工程习惯看PyTorch 版本更常见模型权重一般是.pth或.pt推理脚本里用torch.no_grad()包住前向。图像预处理走cv2.resize加均值方差归一化后处理用pyclipper做多边形偏移、用shapely算 IoU 做 NMS。这些依赖不是花架子缺一个后处理就跑不通后面避坑章节会细说。2.2 目录结构拿到压缩包先看哪几个文件解压后别急着python xxx.py先花两分钟把结构摸清。这类 EAST 推理项目通常长这样east_text_detection/ ├── model/ │ ├── east_model.py # 网络结构定义 │ └── east_weights.pth # 预训练权重 ├── utils/ │ ├── preprocess.py # 图像缩放、归一化 │ ├── postprocess.py # score map 解码、NMS │ └── visualize.py # 画框、保存结果 ├── config.py # 阈值、输入尺寸等参数 ├── detect.py # 单图推理入口 ├── detect_batch.py # 批量推理入口 ├── requirements.txt └── test_images/ # 示例图判断一个 EAST 项目是否完整我一般看三处postprocess.py里有没有restore_rectangle或restore_polygon这类函数没有说明只输出了 score map等于半成品config.py里有没有pixel_threshold和box_threshold两个独立阈值只有一个说明后处理被简化了detect.py里有没有把原图尺寸传进后处理做坐标还原漏了这步框会整体偏移。这三点齐了基本能跑出像样的结果。2.3 环境准备依赖装不对后面全是玄学先把虚拟环境建起来别在系统 Python 里直接装EAST 这类项目对 OpenCV 和 numpy 版本比较挑python -m venv east_env source east_env/bin/activate # Windows 用 east_env\Scripts\activate pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu pip install opencv-python numpy pyclipper shapely这里几个点值得说清楚。torch的 CPU 版就够跑推理除非你要批量处理上万张图再考虑 GPUpyclipper是 C 扩展Windows 上如果 pip 装失败多半是缺 Visual C Build Tools装一个再重试shapely用来算多边形 IoU版本 2.x 和 1.x 的 API 有差异如果代码里报shapely.geometry.polygon相关错误先看版本。装完用下面这段自检能 import 且打印出版本号环境就算过关import cv2, torch, numpy as np, pyclipper, shapely print(cv2, cv2.__version__) print(torch, torch.__version__) print(numpy, np.__version__)如果cv2导入报libGL.so.1找不到Linux 服务器常见装libgl1系统包即可这不是代码问题是 OpenCV 的图形依赖没带上。3. 推理链路拆解一张图从读入到画出四边形的完整过程3.1 预处理尺寸对齐和归一化为什么不能省EAST 网络对输入尺寸有要求通常是 32 的倍数因为网络里有多次下采样再上采样。直接把原图塞进去特征图尺寸对不上后处理解码会错位。常见做法是保持长宽比缩放到目标尺寸附近再 pad 到 32 的倍数import cv2 import numpy as np def preprocess(image, target_size1024): h, w image.shape[:2] scale min(target_size / max(h, w), 1.0) new_h, new_w int(h * scale), int(w * scale) resized cv2.resize(image, (new_w, new_h)) # pad 到 32 的倍数右下角补 0 pad_h (32 - new_h % 32) % 32 pad_w (32 - new_w % 32) % 32 padded cv2.copyMakeBorder(resized, 0, pad_h, 0, pad_w, cv2.BORDER_CONSTANT, value(0, 0, 0)) # BGR 转 RGB减均值除方差ImageNet 统计量 rgb cv2.cvtColor(padded, cv2.COLOR_BGR2RGB).astype(np.float32) mean np.array([123.68, 116.78, 103.94]) normalized (rgb - mean) / 255.0 tensor normalized.transpose(2, 0, 1)[np.newaxis, ...] return tensor, scale, (h, w)这段的关键在返回值除了张量还要把scale和原图尺寸(h, w)带出去。因为后处理解出来的坐标是在缩放pad 后的图上必须按scale除回去才能画到原图上。我见过不少翻车案例就是漏了这步框整体缩小一圈还以为是模型不准。mean用的是 ImageNet 统计量如果你的权重训练时用了别的均值这里要跟着改否则 score map 会整体偏暗、阈值失效。3.2 前向推理与输出解读score map 和几何图各管什么模型前向本身很简单难在理解输出。EAST 的输出一般是一个 5 通道的张量第 0 通道是 score map0~1 的文本概率第 1~4 通道是每个像素到文本框上、右、下、左四条边的距离有的实现还会多一个角度通道。推理代码import torch def infer(model, tensor): model.eval() with torch.no_grad(): input_tensor torch.from_numpy(tensor).float() score_map, geo_map model(input_tensor) # 去掉 batch 维转 numpy score score_map[0, 0].cpu().numpy() geo geo_map[0].cpu().numpy() # shape: (4 或 5, H, W) return score, geoscore里每个值代表该像素属于文本的概率geo里前四通道是距离单位是像素在特征图尺度上。这里有个容易忽略的点特征图尺寸通常是输入尺寸的 1/4所以距离值要乘 4 再还原到输入图尺度。如果你的实现里网络没有下采样这个系数就是 1具体看east_model.py里上采样层的倍数。判断方法很简单拿一张已知文本框的图看解出来的坐标和肉眼位置差多少差 4 倍就是漏乘了。3.3 后处理从像素概率到四边形框的三步走后处理是 EAST 的灵魂也是最容易出问题的地方。完整流程分三步先按pixel_threshold二值化 score map 得到文本区域再对每个文本像素用几何图算出四边形的四个顶点最后用 locality-aware NMS 合并重叠框。import numpy as np import pyclipper from shapely.geometry import Polygon def decode_boxes(score, geo, pixel_threshold0.8, scale4): # 第一步二值化拿到文本像素坐标 text_mask score pixel_threshold ys, xs np.where(text_mask) boxes [] for y, x in zip(ys, xs): # 第二步用距离图算四个顶点特征图尺度 - 输入图尺度 d_top, d_right, d_bottom, d_left geo[:4, y, x] * scale if min(d_top, d_right, d_bottom, d_left) 0: continue # 像素中心在输入图上的坐标 cx, cy x * scale, y * scale box np.array([ [cx - d_left, cy - d_top], [cx d_right, cy - d_top], [cx d_right, cy d_bottom], [cx - d_left, cy d_bottom], ]) boxes.append(box) return boxes这段是简化版真实实现里还会用pyclipper.PyclipperOffset对每个像素生成的微小四边形做膨胀让相邻像素的框能连成一片再用shapely算 IoU 做 NMS。参数上pixel_threshold控制哪些像素算文本调高会漏检小字调低会引入背景噪声NMS 的iou_threshold一般设 0.3~0.4太高会把相邻的两行字合并成一个框。这两个阈值是调参的主战场后面避坑章节会讲怎么定。3.4 坐标还原与可视化框画歪了先查这里解出来的框是在缩放pad 后的图上画回原图要做逆变换def restore_to_original(boxes, scale, orig_size): h, w orig_size restored [] for box in boxes: box box / scale # 先除缩放系数 box[:, 0] np.clip(box[:, 0], 0, w) box[:, 1] np.clip(box[:, 1], 0, h) restored.append(box.astype(np.int32)) return restored def draw_boxes(image, boxes): vis image.copy() for box in boxes: cv2.polylines(vis, [box], isClosedTrue, color(0, 255, 0), thickness2) return visnp.clip那两行别省pad 区域解出来的框可能超出原图边界不裁剪的话cv2.polylines画出来会有一条线飞到图外。可视化只用来肉眼验证真正接下游 OCR 时应该把boxes按四点坐标做透视变换裁出文本块再送识别模型这样倾斜文字也能摆正。4. 常见问题排查跑不通时先看这五条4.1 报错ModuleNotFoundError: No module named pyclipper现象是后处理一执行就崩提示找不到 pyclipper。原因多半是 pip 装的时候编译失败但没报错退出或者装到了别的 Python 环境。先pip show pyclipper看装没装上再看which python和which pip是不是同一个环境。Windows 上编译失败通常是缺 C 构建工具装 Visual Studio Build Tools 后重装实在装不上可以退而用纯 numpy 实现多边形偏移但速度会慢不少只适合验证。4.2 检测结果全是空框或框巨大现象是 score map 看着有响应但解出来的框要么没有要么覆盖整张图。原因通常是几何图的距离值没乘下采样倍数或者pixel_threshold设得太极端。先打印score.max()和geo.min()/max()正常 score 最大值应接近 1geo 距离值应在几十到几百像素量级。如果 geo 全是 0 或负数说明权重加载错了或者输入归一化方式不对如果框巨大检查scale系数是不是漏乘把scale4改成 1 试试对比。4.3 框的位置整体偏移现象是框的形状对但整体往一个方向偏了几十像素。血泪经验九成是预处理 pad 的方向和后处理还原时假设的 pad 方向不一致。上面代码是右下角 pad如果模型训练时用的是居中 pad还原时就要减去左上角的偏移量。查preprocess.py里copyMakeBorder的参数top和left不为 0 就要在还原时补上。这个 bug 很隐蔽因为框本身没错只是坐标系错了。4.4 相邻文本被合并成一个大框现象是两行紧挨着的字被一个框套住。原因是 NMS 的 IoU 阈值太高或者像素级膨胀做得太狠。先把 NMS 的iou_threshold从 0.5 降到 0.3 试再把pyclipper的 offset 值从 0.5 降到 0.3。如果还不行说明 score map 本身就把两行连成一片了这时候要回到pixel_threshold适当调高让文本区域收缩。调参顺序建议是先定 pixel_threshold 看 score map 分割干不干净再定 NMS 阈值看合并效果别两个一起动。4.5 GPU 上跑正常、CPU 上结果不一致现象是同一张图GPU 推理和 CPU 推理框的位置差几个像素。这通常是浮点精度差异导致的score map 在阈值边缘的像素会翻转。解决办法是把pixel_threshold从 0.8 这种整值改成 0.75 或 0.85避开概率密集区或者在 CPU 上强制用torch.set_num_threads(1)减少并行归约的顺序差异。如果差异大到框完全对不上那就不是精度问题检查权重是不是同一份、输入尺寸是不是被动态改了。5. 二次开发换数据微调和改后处理的几个实操方向拿到这份资源多数人最终会走到两条路上一是用自己的数据微调模型二是改后处理适配特定场景。先说微调。EAST 的训练标签是 score map 加几何图标注格式通常是每张图一个 txt每行是八个坐标加一个文本内容。自己标数据的话用四点标注工具导出再写个脚本转成 score map 和距离图。损失函数一般是分类损失score map 的交叉熵加回归损失几何图的 IoU loss 或 smooth L1两者加权权重比常见是 1:1 或 1:2具体看你的数据里小字多不多小字多就把回归损失权重调高。改后处理更常见也更容易见效。比如你的场景是票据文字基本水平那可以把四边形解码简化成水平矩形省掉角度计算速度快一截如果是路牌这种大角度倾斜就要确保几何图里的角度通道被正确使用别在解码时把角度丢了。我一般会先写一个可视化脚本把 score map、四个距离图分别存成灰度图看一遍哪张图有问题一目了然比盲调阈值高效得多。验证改造效果别只看几张图的肉眼效果准备一个小测试集人工标 50 张图的文本框算一下召回率和精确率。EAST 这类检测器对pixel_threshold很敏感建议扫一遍 0.6 到 0.9 的阈值画一条 precision-recall 曲线选拐点。这个习惯是我踩过坑之后养成的有次为了赶进度只看了三张图就定了阈值上线后小字漏检率飙到 40%返工重调花了两天。从那以后我每次改后处理参数都强制走一遍小测试集的指标对比哪怕只改 0.05 的阈值。希望这份拆解能帮你少走几步弯路把这份 EAST 检测资源真正跑成自己项目里的一环。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑