news 2026/3/1 8:49:10

文字检测框坐标怎么用?JSON输出解析一看就懂

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
文字检测框坐标怎么用?JSON输出解析一看就懂

文字检测框坐标怎么用?JSON输出解析一看就懂

OCR文字检测模型输出的坐标信息,常常让刚接触的朋友一头雾水:那些一长串数字到底代表什么?为什么是8个数?怎么画出框?能不能直接用在其他程序里?今天我们就用科哥开发的cv_resnet18_ocr-detection镜像,把检测框坐标的来龙去脉讲清楚——不讲理论、不堆公式,只说你真正用得上的东西。

这篇文章不是教你怎么训练模型,也不是讲ResNet18的结构原理,而是聚焦一个最实际的问题:拿到JSON里的boxes字段后,下一步该怎么做?从看懂格式,到可视化验证,再到工程化调用,全程手把手,连Python基础一般的同学也能照着操作成功。


1. 先看一眼真实的JSON输出

我们上传一张商品宣传图,点击“开始检测”后,WebUI在下方会显示一段JSON数据。这是最核心的原始结果:

{ "image_path": "/tmp/test_ocr.jpg", "texts": [["100%原装正品提供正规发票"], ["华航数码专营店"]], "boxes": [[21, 732, 782, 735, 780, 786, 20, 783]], "scores": [0.98, 0.95], "success": true, "inference_time": 3.147 }

注意这三行关键字段:

  • "texts":识别出的文字内容,按检测顺序排列
  • "boxes":每个文本框对应的8个坐标值(重点!)
  • "scores":每个框的置信度分数,越高越可靠

现在问题来了:[21, 732, 782, 735, 780, 786, 20, 783]这8个数字,到底怎么对应到图片上那个矩形框?


2. 坐标格式揭秘:不是矩形,是四边形!

很多初学者默认“检测框=矩形”,所以看到8个数就懵了——矩形明明只需要左上角x/y和右下角x/y,也就是4个数啊?

真相是:这个模型输出的是任意四边形(quadrilateral)坐标,不是轴对齐矩形(AABB)。它能精准框住倾斜、弯曲、透视变形的文字区域,比如斜放的广告牌、手机拍歪的发票、带弧度的包装盒文字。

这8个数,就是按顺时针顺序给出的四边形四个顶点的坐标(x, y)

顶点坐标对含义
第1点(21, 732)左上角(或起始点)
第2点(782, 735)右上角
第3点(780, 786)右下角
第4点(20, 783)左下角

你可以把它想象成用四根线段首尾相连画出的一个平行四边形(实际可能是梯形或不规则四边形)。这种表示法比矩形框更灵活,也更贴近真实场景中文字的排布形态。

小贴士:如果你只需要一个粗略的包围矩形(比如做简单裁剪),可以用这4个点算出最小外接矩形:
x_min = min(21, 782, 780, 20) = 20
y_min = min(732, 735, 786, 783) = 732
x_max = max(...) = 782
y_max = max(...) = 786
得到(20, 732, 782, 786)—— 这就是标准的(x1, y1, x2, y2)格式。


3. 动手验证:用OpenCV把框画出来

光看数字不够直观?我们写几行Python代码,把检测框真正在原图上画出来。不需要安装新库,只要你的环境里有OpenCV(WebUI本身已自带):

3.1 准备工作:读取图片和JSON

假设你已将检测结果保存为result.json,图片为test.jpg

import json import cv2 import numpy as np # 读取JSON with open("result.json", "r", encoding="utf-8") as f: data = json.load(f) # 读取原图 img = cv2.imread("test.jpg") # 提取boxes和texts boxes = data["boxes"] # [[x1,y1,x2,y2,x3,y3,x4,y4], ...] texts = data["texts"] # [["文字1"], ["文字2"], ...]

3.2 绘制四边形框 + 标注文字

# 遍历每个检测框 for i, box in enumerate(boxes): # 转换为numpy数组,每两个数一组(x, y) pts = np.array([ [box[0], box[1]], # 点1 [box[2], box[3]], # 点2 [box[4], box[5]], # 点3 [box[6], box[7]] # 点4 ], dtype=np.int32) # 绘制四边形(绿色,线宽2) cv2.polylines(img, [pts], isClosed=True, color=(0, 255, 0), thickness=2) # 在框左上角写文字(白色字体,大小0.6) if i < len(texts) and texts[i]: text = texts[i][0] cv2.putText(img, text, (int(box[0]), int(box[1]) - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 1) # 保存结果图 cv2.imwrite("result_with_boxes.jpg", img) print(" 检测框已绘制完成,保存为 result_with_boxes.jpg")

运行后你会得到一张清晰标注了所有文字区域和内容的图片。你会发现:
每个框都严丝合缝地贴合文字边缘,包括轻微倾斜的标题;
即使两行文字靠得很近,也不会被合并成一个大框;
中文、英文、符号混合时,依然能准确分离。

这就是四边形坐标的价值——它不只是“能用”,而是“用得准”。


4. 工程化使用:如何在自己的项目里调用?

你可能并不想每次手动保存JSON再读取,而是希望把检测能力集成进自己的业务系统。cv_resnet18_ocr-detection提供了两种主流方式:

4.1 方式一:调用WebUI API(推荐给快速验证)

WebUI本质是一个Gradio服务,它暴露了标准HTTP接口。你无需启动完整界面,直接发POST请求即可:

curl -X POST "http://localhost:7860/api/predict/" \ -H "Content-Type: multipart/form-data" \ -F "data=[\"/path/to/your/image.jpg\", 0.25]" \ -F "fn_index=0"

返回的就是上面看到的JSON结构。在Python中用requests调用更简洁:

import requests url = "http://localhost:7860/api/predict/" files = {"file": open("invoice.jpg", "rb")} data = {"data": '["/tmp/invoice.jpg", 0.25]', "fn_index": "0"} response = requests.post(url, files=files, data=data) result = response.json() print(result["data"][0]) # 就是那个带boxes的JSON字典

注意:fn_index=0对应“单图检测”功能;批量检测是fn_index=1;ONNX导出是fn_index=3。具体可查看WebUI源码或Network面板。

4.2 方式二:本地Python函数调用(适合生产部署)

镜像内部封装了可直接导入的检测器模块。进入容器后执行:

from detector import OCRDetector # 初始化检测器(自动加载模型) detector = OCRDetector() # 直接传入cv2读取的图像(BGR格式) img = cv2.imread("receipt.png") result = detector.detect(img, threshold=0.2) print("检测到", len(result["boxes"]), "处文字") for i, (box, text, score) in enumerate(zip(result["boxes"], result["texts"], result["scores"])): print(f"[{i+1}] '{text[0]}' (置信度: {score:.2f}) -> 坐标: {box}")

这种方式绕过HTTP开销,延迟更低,适合高并发场景。detector.detect()返回的就是标准字典,结构与WebUI完全一致,你之前的解析逻辑可直接复用。


5. 常见误区与避坑指南

刚上手时容易踩的几个“隐形坑”,帮你省下调试半天的时间:

5.1 坐标原点在哪?单位是什么?

  • 原点:图片左上角(0, 0),x向右增长,y向下增长(OpenCV/PyTorch通用约定)
  • 单位:像素(pixel),不是毫米或英寸
  • 验证方法:用画图工具打开原图,量一下第一个点(21, 732)是否真的在文字左上角附近

5.2 为什么有的框坐标超出图片范围?

比如出现x = -5y = 1200(而图片高度只有1080)?
→ 这是模型在边界处的预测溢出,属于正常现象。处理建议

  • 绘图前加截断:np.clip(x, 0, img_width-1)
  • 业务逻辑中过滤掉面积过小(<10×10)或坐标异常的框

5.3texts里为什么是[["文字"]]而不是["文字"]

这是为兼容多语言、多行文本设计的嵌套结构。当前版本每行文字单独成项,所以是二维列表。
正确取法:text = texts[i][0]
❌ 错误写法:text = texts[i](会得到一个列表,不是字符串)

5.4 置信度scores低于多少该丢弃?

参考科哥文档建议:

  • 通用场景:保留score >= 0.2的结果(默认阈值)
  • 高精度需求(如合同关键字段):>= 0.5
  • 容错型场景(如社交媒体截图):>= 0.1
    但注意:单纯提高阈值不一定提升准确率,有时会漏掉低对比度但正确的文字。

6. 实战延伸:三个马上能用的小技巧

学会解析坐标只是起点,下面这些技巧能立刻提升你的工作效率:

6.1 技巧一:按位置排序,还原阅读顺序

检测结果默认按模型内部优先级返回,不一定是从左到右、从上到下。要生成可读报告,需重排序:

def sort_boxes_by_position(boxes, texts): # 按y中心坐标分组(行),再按x中心排序(列) lines = {} for i, (box, text) in enumerate(zip(boxes, texts)): y_center = (box[1] + box[3] + box[5] + box[7]) / 4 x_center = (box[0] + box[2] + box[4] + box[6]) / 4 line_key = round(y_center / 20) # 每20像素为一行 if line_key not in lines: lines[line_key] = [] lines[line_key].append((x_center, i, text[0])) # 合并结果 sorted_texts = [] for line_key in sorted(lines.keys()): line = sorted(lines[line_key], key=lambda x: x[0]) sorted_texts.extend([item[2] for item in line]) return sorted_texts # 使用 ordered = sort_boxes_by_position(boxes, texts) print("阅读顺序:", " | ".join(ordered))

6.2 技巧二:提取指定区域文字(如只读发票金额)

你想只获取图片右下角“金额:¥1280.00”这一块?可以设定坐标筛选规则:

def extract_region(boxes, texts, x_min=600, x_max=800, y_min=900, y_max=1000): results = [] for i, box in enumerate(boxes): # 计算四边形中心点 cx = sum(box[::2]) / 4 # 所有x坐标平均 cy = sum(box[1::2]) / 4 # 所有y坐标平均 if x_min <= cx <= x_max and y_min <= cy <= y_max: results.append(texts[i][0]) return results amount_text = extract_region(boxes, texts, 600, 800, 900, 1000) print("检测到金额:", amount_text)

6.3 技巧三:批量导出为CSV,对接Excel分析

把所有检测结果整理成表格,方便业务同事查看:

import csv with open("ocr_results.csv", "w", newline="", encoding="utf-8-sig") as f: writer = csv.writer(f) writer.writerow(["序号", "文字内容", "x1", "y1", "x2", "y2", "x3", "y3", "x4", "y4", "置信度"]) for i, (box, text, score) in enumerate(zip(boxes, texts, scores)): row = [i+1, text[0]] + box + [f"{score:.3f}"] writer.writerow(row) print(" CSV已导出,可用Excel直接打开分析")

7. 总结:坐标不是终点,而是自动化流程的起点

今天我们拆解了OCR检测框坐标的全部秘密:

  • 看懂8位数组:它是四边形四个顶点的(x, y)坐标,不是矩形;
  • 亲手画出来:用OpenCV几行代码验证结果可靠性;
  • 接入自己系统:API调用或本地函数,无缝集成;
  • 避开常见坑:原点、单位、嵌套结构、置信度过滤;
  • 延伸实用技巧:排序、区域筛选、CSV导出。

记住:坐标本身没有意义,有意义的是你用它做了什么。它可以是自动填写表单的输入,是电子合同的关键字段定位器,是电商后台批量审核商品图的质检员,也可以是你下一个AI应用的第一步数据源。

别再把JSON当成黑盒输出——现在,你已经掌握了打开它的钥匙。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/27 17:52:47

从0开始学大模型部署:gpt-oss+WEBUI新手教程

从0开始学大模型部署&#xff1a;gpt-ossWEBUI新手教程 你是不是也想过——不用注册、不依赖网络、不看广告&#xff0c;就能在自己电脑上和OpenAI最新开源的大模型面对面聊天&#xff1f;不是调API&#xff0c;不是用网页版&#xff0c;而是真真正正把模型“请进”本地&#…

作者头像 李华
网站建设 2026/2/25 15:36:22

verl + Ray 架构解析:分布式任务调度机制

verl Ray 架构解析&#xff1a;分布式任务调度机制 verl 作为专为大语言模型后训练设计的强化学习框架&#xff0c;其核心竞争力不仅在于算法表达能力&#xff0c;更在于底层分布式执行引擎的工程深度。在实际生产环境中&#xff0c;一个 RL 训练任务往往涉及 Actor 模型生成…

作者头像 李华
网站建设 2026/2/24 17:12:07

unet image Face Fusion保姆级教程:从零开始部署WebUI界面

unet image Face Fusion保姆级教程&#xff1a;从零开始部署WebUI界面 你是不是也试过各种人脸融合工具&#xff0c;结果不是安装失败&#xff0c;就是界面卡顿&#xff0c;要么就是效果生硬、边缘发虚&#xff1f;今天这篇教程&#xff0c;不讲原理、不堆参数&#xff0c;就带…

作者头像 李华
网站建设 2026/2/27 23:01:42

Z-Image-Turbo文旅宣传案例:景区海报智能生成部署教程

Z-Image-Turbo文旅宣传案例&#xff1a;景区海报智能生成部署教程 1. 为什么文旅行业需要这张“秒出图”的海报生成工具&#xff1f; 你有没有遇到过这样的场景&#xff1a;五一假期前两天&#xff0c;景区运营团队突然接到通知——要为新开的非遗体验馆制作一组高清宣传海报…

作者头像 李华
网站建设 2026/3/1 3:59:25

PyTorch-2.x镜像实测报告:pandas+matplotlib无缝集成

PyTorch-2.x镜像实测报告&#xff1a;pandasmatplotlib无缝集成 1. 开箱即用的深度学习开发环境到底有多省心&#xff1f; 你有没有过这样的经历&#xff1a;花两小时配环境&#xff0c;结果卡在CUDA版本不兼容上&#xff1f;好不容易装好PyTorch&#xff0c;发现pandas报错“…

作者头像 李华
网站建设 2026/2/25 7:04:08

小白也能懂的Qwen3-Embedding入门:零基础实现文本向量化

小白也能懂的Qwen3-Embedding入门&#xff1a;零基础实现文本向量化 1. 什么是文本向量化&#xff1f;先别急着写代码&#xff0c;咱们先搞懂它能干啥 你有没有遇到过这些场景&#xff1a; 想从几百篇产品文档里快速找到和“支付失败”相关的段落&#xff0c;但关键词搜索总…

作者头像 李华