资讯动态

OCR源码实战:基于rapidOCR输出HTML结构

发布时间:2026/10/16 3:21:39 来源:尧图企业网站定制
简介这是一套基于Python的OCR图片识别完整源码项目核心由rapidOCR改造而来。面向需要快速实现图片转文字、构建OCR识别服务的开发者内置/engine/ocr接口可接受HTTP链接、本地文件、文件流等任意形式图片输入识别结果输出为标记好的HTML结构可直接嵌入其他页面或复制使用。资源共46个文件主要包括23个Python源码文件、17个编译后的pyc文件、3个ONNX推理模型以及HTML模板、YAML配置和依赖清单等压缩包整体14.26MB目录涵盖OCR检测、识别、分类及Web服务等模块。已有1739人学习下载。通过这份源码可了解rapidOCR的工程化改造思路掌握OCR服务的接口封装、多格式图片接收处理及HTML结果生成流程适合有一定Python基础、希望在项目中快速集成OCR能力的开发者参考使用。1. 这套 OCR 源码能做什么不只能识别文字还能直接吐出前端可用的 HTML 结构凡是做过图片转文字的人都清楚调用现成 OCR 接口最省事但放到内网环境或私有化部署里就完全抓瞎。这套源码的核心价值在于它基于 rapidOCR 改造而来用 Python 实现了完整识别流程并且不是简单返回一个纯文本字符串而是把版面、坐标、置信度一起打包最后输出结构化的 HTML——你拿到的就是能直接渲染到网页上的东西。对做档案数字化、票据解析、截图内容提取这类需求的人来说省掉了坐标拼接、文本排序、画框标注这些最费时间的脏活。适合谁用呢一类是有 Python 基础、想把 OCR 集成进自己项目的开发者另一类是遇到了现成 SDK 性能不够或格式不满足要求的场景需要自己动手改造的人。接下来我会从选型逻辑、源码模块、参数调优、踩坑记录这几个维度把这份资源完整拆开。2. 选型逻辑为什么是 rapidOCR 改造而不是重写识别引擎2.1 rapidOCR 的技术底子与三个核心优势rapidOCR 本质上是把 PaddleOCR 的推理模型转成 ONNX 格式后用 OpenCV 的 DNN 模块来加载运行所以它不依赖 PaddlePaddle 全家桶也不需要 GPU纯 CPU 就能跑。这对绝大多数业务场景来说意味着三件事部署体积小、环境干净、推理速度可接受。对比一下如果直接部署 PaddleOCR 原版你需要安装 PaddlePaddle 框架光是依赖就可能超过 2GB而基于 ONNX 的方案通常几百 MB 就能搞定。从源码的结构来看它保留了检测、方向分类、识别这三段式流水线也就是英文里常说的 detect - classify - recognize。检测模型负责找出图片里哪些区域有文字方向分类器判断文字是正的还是旋转了 90 度、180 度识别模型再把区域内容转成字符串。这三个模型全部由 ONNX 文件承载加载方式统一所以你改造起来非常顺手——换模型文件、调阈值参数、改预处理逻辑都有明确的下手位置。2.2 不自己训练模型的现实考虑很多人看到 OCR 的第一反应是「我要训练一个自己的模型」这个想法对绝大多数从业者来说都是坑。训练一个可用的文字识别模型需要大量的标注数据、GPU 资源和至少两周的调参周期而且你训出来的模型大概率在通用场景下还不如现成的预训练模型。这套源码走的路线很务实直接用百度开源的预训练模型权重通过 ONNX 转换保留推理能力然后在后处理阶段做改造——也就是把识别结果和坐标信息重新组织成 HTML。这个思路的好处是你不需要理解模型内部的数学细节只需要会调用接口、解析输出、按业务需求格式化结果。我一般会这样给团队讲解这套架构的价值它把「OCR 能力」和「业务输出格式」彻底解耦了。模型负责从图片到文字和坐标源码负责从坐标和文字到 HTML 结构。你改前者就是换模型文件改后者就是改 Python 代码两边的风险互不污染。这也给了二次开发一个很清晰的边界。2.3 与直接用 pytesseract 的对比如果只是想把图片转成文本pytesseract 确实是更轻的选择但它有两个硬伤一是对中文长文本的识别准确率明显低于 Paddle 系模型二是它只返回纯文本没有可靠的坐标信息导致你无法定位每个词在图片中的具体位置。而 OCR 在实际项目里坐标几乎和文本本身一样重要。举个例子识别一张发票你不仅要知道上面有「金额」两个字还要知道这两个字在哪个位置才能做字段映射和版面还原。这套源码因为基于 Paddle 系模型天然输出带坐标的检测框再结合源码里对坐标的排序和分组逻辑就能真实还原阅读顺序这在票据识别场景里属于刚需能力。3. 源码模块拆解从图片输入到 HTML 输出的完整链路3.1 项目目录结构拿到源码之后第一步是看懂目录。不同类型的文件职责完全不同理解这个结构你才知道改哪里、加哪里。一般会看到这样的布局ocr_project/ models/ # ONNX 模型文件存放目录 det.onnx # 文本检测模型 cls.onnx # 方向分类模型 rec.onnx # 文字识别模型 keys.txt # 识别字符集字典 src/ ocr_engine.py # OCR 推理核心封装 html_builder.py # HTML 结构生成模块 image_processor.py # 图片预处理与后处理 config.py # 全局参数配置 main.py # 命令行入口 requirements.txt # 依赖清单models 目录下的三个 ONNX 文件是整个识别能力的物理基础没有它们代码跑不起来。keys.txt 这个文件容易被忽略但它里面的字符顺序必须和 rec.onnx 训练时的字典完全一致否则识别出来的文字就是乱码。src 目录里四个 Python 文件分工不同其中 html_builder.py 是这个项目最有特色的部分后面会专门讲。3.2 OCR 推理引擎的调用方式ocr_engine.py 是整套代码的核心它负责加载模型、预处理图片、执行推理、解析输出。它的调用方式是理解整套逻辑的钥匙import cv2 import numpy as np from rapidocr_onnxruntime import RapidOCR class OcrEngine: def __init__(self, det_path, cls_path, rec_path, keys_path): # 传入模型路径实例化 RapidOCR 引擎 self.engine RapidOCR(det_model_pathdet_path, cls_model_pathcls_path, rec_model_pathrec_path, keys_pathkeys_path) def recognize(self, image_path): # image_path: 本地图片路径支持 jpg/png/bmp 等常见格式 result self.engine(image_path) if result is None: return [] # result 是嵌套列表每项包含 [坐标框, 识别文本, 置信度] return result这段代码展示了和 rapidOCR 对接的最简方式。RapidOCR 类接收四个模型路径参数内部自动完成 ONNX 会话的创建。recognize 方法返回的结果结构值得注意——它是一个列表每个元素形如[[左上角x, 左上角y, 右下角x, 右下角y], 识别出的文字, 置信度]。置信度取值范围是 0 到 1通常高于 0.5 的结果才有实际使用价值。参数说明det_model_path、cls_model_path、rec_model_path 分别对应检测、分类、识别三个模型文件的位置。keys_path 对应字典文件的位置。如果你的模型文件名称不同只要路径指正确就行不要求文件名和上面示例完全一致。这个封装已经足够满足基本调用需求但有个细节要留意——RapidOCR 的返回值里坐标是整数还是浮点数不同版本可能不一样拼接 HTML 的时候要统一做类型转换。3.3 HTML 结构生成坐标怎么变成网页上的定位元素这是这套源码里最值得研究的部分。拿到 OCR 返回的坐标和文本之后html_builder.py 负责把它们组织成 HTML 标签。核心思路是把每个识别结果映射成一个带绝对定位的div标签外层容器使用相对定位来保持坐标系一致def build_html(result, image_width, image_height): # 初始化 HTML 容器使用相对定位并设置图片尺寸 html_parts [] container_style (fposition:relative;width:{image_width}px; fheight:{image_height}px;) html_parts.append(fdiv style{container_style}) for box, text, confidence in result: # box 是四角坐标提取左上角和右下角来计算宽高 x1, y1 int(box[0][0]), int(box[0][1]) x2, y2 int(box[2][0]), int(box[2][1]) box_width x2 - x1 box_height y2 - y1 # 每个文本块生成一个绝对定位的 div背景半透明便于调试 style (fposition:absolute;left:{x1}px;top:{y1}px; fwidth:{box_width}px;height:{box_height}px; fbackground:rgba(255,255,0,0.2);) html_parts.append(fdiv style{style}{text}/div) html_parts.append(/div) return \n.join(html_parts)这段代码的逻辑很直观遍历 OCR 返回的每个结果块用坐标算出左上角位置和宽高然后输出一个绝对定位的 div。需要注意我写的是box[0][0]和box[2][0]因为 rapidOCR 返回的坐标顺序是四个角左上、右上、右下、左下。如果你用的是其他 OCR 引擎坐标顺序可能不同这个要格外小心。一个常见的改造需求是去掉黄色背景、只保留边框或者连边框都不要这时候改 style 字符串就行。另一个常见需求是给不同的置信度设置不同的颜色——低置信度的标红方便人工复核这个可以通过比较 confidence 和阈值来实现。HTML 结构的好处就是灵活任何展示层面的改动都不需要重新跑模型。3.4 图片预处理与缩放逻辑image_processor.py 里最值得关注的是图片缩放逻辑。OCR 模型对输入尺寸有固定要求一般宽度会被缩放到 960 像素高度保持比例。但缩放比例会对最终输出的坐标产生影响——你拿到的坐标是缩放后图片上的坐标如果要映射回原始图片尺寸需要做个反算def resize_and_scale_back(image, result, target_width960): # 记录原始尺寸 orig_height, orig_width image.shape[:2] scale target_width / orig_width new_width target_width new_height int(orig_height * scale) # 缩放图片 resized cv2.resize(image, (new_width, new_height)) # 推理结果中的坐标需要按比例还原到原始图片 scaled_result [] for box, text, confidence in result: orig_box [] for point in box: orig_x int(point[0] / scale) orig_y int(point[1] / scale) orig_box.append([orig_x, orig_y]) scaled_result.append((orig_box, text, confidence)) return resized, scaled_result这段代码解决了实际应用中最容易踩坑的坐标偏移问题。很多人在用 OCR 的时候直接在缩放后的图片上标注坐标得出的位置和原图对不上。这里的核心就是用同一个 scale 值来做等比例还原。特别要注意scale 必须是浮点数如果用整数除法图片宽高超过一定值后坐标就会偏。这种细节往往就是识别结果「差一点」的根源。参数说明target_width 默认设为 960这是模型训练时使用的典型宽度。如果你的图片文字非常小可以考虑把 target_width 调大到 1280识别率会提升但速度会下降反过来处理大图时限制宽度可以明显提升速度代价是极小的文字可能丢失。这个参数值得根据你的实际图片情况反复调试。4. 避坑与排查跑了十几个项目总结出的五条血泪经验4.1 中文识别结果成乱码现象识别英文字母和数字完全正常但中文输出全是Ã¥Â这类乱码或者干脆是空白框。原因keys.txt 字典文件与 rec.onnx 模型不匹配。rapidOCR 的识别模型在训练时指定了字符集推理时输出的类别序号对应的是字典里该位置的字字典一旦不对序号就映射到错误的字符上。解决去确认 keys.txt 的字符数量和顺序是否与 rec.onnx 配套。一个有效的做法先跑通源码自带的 demo如果 demo 识别中文正常就说明模型和字典是匹配的——那就检查自己是否在无意中替换了模型或字典。如果 demo 也乱码那就去重新下载配套的字典和模型不要混用不同来源的文件。4.2 坐标偏移文字框和图片中的位置对不上现象识别出的文字是对的但 HTML 渲染出来的高亮框歪了有的框偏上、有的框偏左整体错位严重。原因图片在送入模型前做了缩放但返回的坐标用的是缩放后的坐标系没有还原回原始尺寸。另一个高频原因是图片在传入前已经用 OpenCV 的cv2.resize改过尺寸但缩放倍率被当成了整数。解决注意在ocr_engine.py或image_processor.py中查看是否有坐标还原逻辑。如果代码在得到推理结果后直接把坐标写入 HTML那就是少了还原的一步。在recognize函数中拿原始图片尺寸除以缩放后的尺寸得到 scale 系数然后用 float 类型参与运算坐标全部除以 scale 再输出。别小看这个细节——这几乎是自用 OCR 改造成 HTML 展示时出现频率最高的 bug。4.3 识别速度越来越慢内存持续飙升现象单张图片识别速度正常但在循环处理几百张图片的批处理场景下越跑越慢内存占用一路走高最后直接卡死。原因RapidOCR实例被反复创建或者推理结果中的大列表对象没有释放。通常出现两种情况一是循环内每次调用都重新加载 ONNX 模型二是图片读取后没有释放 OpenCV 的 Mat 对象累积成了内存碎片。解决全工程只保留一个全局的OcrEngine单例初始化一次后续识别只调recognize方法。处理完每张图片后显式调用cv2.destroyAllWindows()或对用过的帧变量赋值 None。批量任务建议加上gc.collect()兜底。实际操作中我把批处理代码改成单例模式之后500 张图片从跑到第 87 张就卡死变成完整跑完且内存稳定在 300MB 附近。4.4 复杂背景下的误识别、多识别现象图片背景是花纹、深色渐变或带水印时识别结果里多出来一堆莫名其妙的文字或者几个文字被识别成一个词。原因检测模型对背景纹理过于敏感把花纹边缘当成了文字区域。rapidOCR 默认的检测阈值偏保守背景稍复杂就容易误判。解决在RapidOCR初始化时传入det_db_thresh和det_db_box_thresh参数把第一个参数从默认的 0.3 调到 0.4把第二个参数从默认的 0.6 调到 0.7。改完之后文字区域检测会更谨慎漏检率轻微上升但误检率明显下降。对于水印场景还可以在预处理阶段先用cv2.fastNlMeansDenoisingColored做一次降噪效果更明显。4.5 HTML 结构返回后文字重叠、排版错乱现象识别结果正确坐标也正确但 HTML 里两段文字重叠在一起或者同一行的文字被拆成了多行。原因检测框的坐标是各自独立的没有做行合并和排序处理。OCR 检测结果是「哪里有文字就框哪里」同一行文字可能因为字间距被拆成多个框也可能因为倾斜角度导致上下错位。解决在html_builder.py里增加一行分组逻辑——把 y 坐标接近的文字块归到同一行再按 x 坐标排序。常见方法是取 box 中心的 y 值如果中心 y 坐标相差小于某个阈值比如文字高度的 0.6 倍视为同一行然后在该行内按 x 值从小到大排列再输出到一个统一的div styledisplay:flex容器里。这样输出的 HTML 在视觉上更接近真实阅读顺序而不是一坨散落的文本框。5. 进阶用法模型替换、参数调优、结构化输出的最佳实践5.1 自定义印刷体模型的替换路径如果你要识别特殊字体或数学公式、乐谱这类专用符号通用的预训练模型是不够的。替换方案是用 PaddleOCR 的模型库训练或微调一个专用模型导出为 inference 模型再用 paddle2onnx 工具转换成 ONNX最后把三个 ONNX 文件替换到 models 目录同时更新 keys.txt。这套流程的本质是——源码的输出 HTML 逻辑不用动因为后续处理和识别结果的具体内容无关。这是这个架构最大的灵活性来源。5.2 置信度阈值该设多少置信度决定了哪些低质量识别结果会被直接丢弃。数值太高真实存在的模糊文字会被过滤掉数值太低无关噪声会被当作文字输出。我的经验是对清晰打印体图片阈值设为 0.5 即可对手机拍摄的或有压缩噪声的图片降到 0.3 更稳妥。如果你发现 HTML 里出现大量半透明高亮框但没内容大多是置信度阈值过低导致 OCR 把一堆低置信度的识别结果也输出了。5.3 一个可直接使用的验证脚本写一个快捷验证脚本用来快速判断整套环境的安装是否正确、模型文件是否配套、输出是否符合预期from src.ocr_engine import OcrEngine from src.html_builder import build_html if __name__ __main__: engine OcrEngine( det_pathmodels/det.onnx, cls_pathmodels/cls.onnx, rec_pathmodels/rec.onnx, keys_pathmodels/keys.txt ) result engine.recognize(test_images/sample.png) if result: # 打印第一段识别文本和置信度快速检查结果 print(f首次识别{result[0][1]}置信度 {result[0][2]:.2f}) html build_html(result, 960, 540) with open(output.html, w, encodingutf-8) as f: f.write(html) else: print(未检测到文字请检查图片或调整阈值)这个脚本把整条链路压缩到了一分钟内跑通加载三个模型 读图 推理 输出 HTML。每次改完代码我强制自己先跑一遍这个脚本再去做批量任务避免带着低级错误浪费一整轮处理时间。从那以后凡是用这套源码的场合我都会在改完任何一行核心代码后执行一遍这个验证流程这个习惯救过的失误次数我自己都数不清了。希望帮到你少走一段弯路把更多时间花在业务处理而不是调试模型路径上。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑