news 2026/3/28 8:18:45

YOLO12 API接口文档:POST /predict 的multipart/form-data规范详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLO12 API接口文档:POST /predict 的multipart/form-data规范详解

YOLO12 API接口文档:POST /predict 的multipart/form-data规范详解

1. 为什么你需要读懂这个接口规范

你刚部署好ins-yolo12-independent-v1镜像,WebUI(7860端口)点几下就能看到检测效果——但真正要把YOLO12集成进你的业务系统,靠点鼠标可不行。
你得调API。而/predict这个接口,是整个YOLO12服务对外输出能力的唯一图像入口。它不接受base64、不认JSON body、不解析URL参数里的图片链接——它只认一种格式:multipart/form-data

很多开发者第一次调用失败,不是模型没加载、不是GPU没启动,而是卡在了“传图方式不对”:

  • curl -d发送二进制数据?→ 400 Bad Request
  • 把图片转成base64塞进JSON字段?→ 422 Unprocessable Entity
  • 用Postman选错Body类型(选了raw而非form-data)?→ 返回空响应或500

这不是YOLO12的bug,是HTTP协议层的“语言不通”。本文不讲YOLO原理,不跑训练代码,就聚焦一件事:让你用任意编程语言,100%正确地把一张图送进/predict,拿到结构化检测结果。所有细节,包括字段名、边界符、编码陷阱、常见报错,全部摊开讲。

2. POST /predict 接口核心行为与约束

2.1 接口基础信息

项目
HTTP方法POST
路径/predict
协议HTTP/1.1(支持HTTPS,若反向代理配置了SSL)
响应格式application/json(UTF-8编码)
超时设置默认30秒(从接收到完整请求体开始计时)
最大上传尺寸16MB(由FastAPI默认限制,不可热修改)

关键提醒:该接口不校验文件扩展名,但会尝试用PIL打开图像。上传.txt或损坏的.jpg会导致500错误,日志显示UnidentifiedImageError。务必确保上传的是有效图像文件。

2.2 multipart/form-data 的真实结构

别被“表单数据”这个词骗了——它和网页里填用户名密码的<form>不是一回事。它的本质是:把二进制文件和文本参数,用一串特殊分隔符(boundary)打包成一个HTTP body

一个合法的请求体长这样(已简化,仅保留关键部分):

POST /predict HTTP/1.1 Host: 192.168.1.100:8000 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW Accept: application/json ------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; name="file"; filename="test.jpg" Content-Type: image/jpeg <这里是test.jpg的原始二进制字节流,无任何编码> ------WebKitFormBoundary7MA4YWxkTrZu0gW--

注意三个硬性要求:

  • Content-Type必须包含boundary=参数,且值要与body中实际使用的分隔符完全一致;
  • name="file"固定字段名,不能写成imageimgupload
  • filename属性可有可无,但若存在,其值不应影响处理逻辑(YOLO12只读取二进制内容);
  • Content-Type子部分(即image/jpeg建议填写准确MIME类型,但非强制;传application/octet-stream也能成功。

2.3 支持的图像格式与预处理规则

YOLO12 API接收图像后,会自动执行以下标准化流程:

步骤操作说明
1. 解码使用PIL.Image.open()支持JPG/JPEG、PNG、WEBP;BMP需额外安装pillow-simd,不推荐
2. 转模式.convert('RGB')灰度图、RGBA图均转为3通道RGB,避免通道数不匹配
3. Resize等比缩放+补黑边 →640×640保持宽高比,短边缩至640,长边超出部分用黑色填充(YOLO标准letterbox)
4. 归一化pixel / 255.0输入张量值域变为[0,1],符合PyTorch模型预期

实测验证:上传一张1920×1080的PNG人像图,返回的bbox坐标是基于640×640推理分辨率的。如需映射回原图坐标,需按比例反算(见第4节)。

3. 各语言调用示例:避开最常见坑

3.1 Python(requests库)——最简可靠版

import requests url = "http://192.168.1.100:8000/predict" # 替换为你的实例IP image_path = "/path/to/test.jpg" # 正确:直接传file对象,requests自动构造multipart with open(image_path, "rb") as f: files = {"file": ("test.jpg", f, "image/jpeg")} # (filename, file_obj, mime_type) response = requests.post(url, files=files, timeout=30) # 错误示范(常见): # files = {"file": f.read()} # 传bytes会丢失filename和mime,导致422 # files = {"file": open(image_path, "rb")} # 缺少filename,某些旧版requests会失败 if response.status_code == 200: result = response.json() print(f"检测到 {len(result['predictions'])} 个目标") for pred in result["predictions"]: print(f"- {pred['class_name']}: {pred['confidence']:.2f} @ [{pred['x1']}, {pred['y1']}, {pred['x2']}, {pred['y2']}]") else: print(f"请求失败: {response.status_code} - {response.text}")

3.2 JavaScript(Fetch API)——浏览器/Node.js通用

async function predictImage(fileInput) { const url = "http://192.168.1.100:8000/predict"; const formData = new FormData(); // 正确:使用input.files[0],保留原始文件名和类型 formData.append("file", fileInput.files[0]); try { const response = await fetch(url, { method: "POST", body: formData, // 自动设置Content-Type和boundary // 不要手动设置headers!否则会覆盖boundary }); if (!response.ok) throw new Error(`HTTP ${response.status}`); const result = await response.json(); console.log("检测结果:", result); return result; } catch (err) { console.error("调用失败:", err); } } // 调用示例(绑定到HTML <input type="file">) document.getElementById("upload").addEventListener("change", (e) => { predictImage(e.target); });

3.3 cURL命令行——调试黄金组合

# 终极可靠写法(显式指定boundary,兼容所有curl版本) curl -X POST "http://192.168.1.100:8000/predict" \ -H "accept: application/json" \ -F "file=@/path/to/test.jpg;type=image/jpeg" \ -v # 加-v看详细请求头和body # 危险写法(易出错): # curl -X POST ... -d "@test.jpg" # 传的是raw body,不是multipart # curl -X POST ... -H "Content-Type: multipart/form-data" # 缺少boundary,服务无法解析

调试技巧:加-v参数后,curl会打印完整的请求头和body。重点检查:

  • Content-Type: multipart/form-data; boundary=------------------------...是否存在
  • body中是否有Content-Disposition: form-data; name="file"; filename="test.jpg"
  • 二进制数据前是否有空行(\r\n\r\n

4. 响应JSON结构详解与坐标映射指南

4.1 标准响应字段说明

成功响应(HTTP 200)返回标准JSON,结构如下:

{ "status": "success", "predictions": [ { "class_id": 0, "class_name": "person", "confidence": 0.924, "x1": 128.3, "y1": 45.7, "x2": 210.8, "y2": 320.1 }, { "class_id": 2, "class_name": "car", "confidence": 0.871, "x1": 412.5, "y1": 288.9, "x2": 598.2, "y2": 375.6 } ], "input_size": { "width": 640, "height": 640 } }
字段类型说明
statusstring固定为"success",失败时返回其他状态码(如400/500)
predictionsarray检测到的所有目标列表,按置信度降序排列
class_idintegerCOCO类别ID(0=person, 1=bicycle, 2=car...)
class_namestring对应的英文类别名(小写,无空格)
confidencefloat检测置信度(0.0~1.0),受请求时conf参数影响
x1,y1,x2,y2float边界框左上角(x1,y1)和右下角(x2,y2)坐标,单位:像素
input_sizeobject模型实际接收的输入尺寸(恒为{"width":640,"height":640}

4.2 如何把640×640坐标映射回原图

YOLO12返回的坐标是基于640×640推理图的。如果你的原图是1280×720,需要做逆letterbox变换

def map_bbox_to_original(pred, orig_w, orig_h): # 1. 计算letterbox填充比例 r = min(640 / orig_w, 640 / orig_h) # 缩放比例 new_unpad_w = int(round(orig_w * r)) new_unpad_h = int(round(orig_h * r)) pad_w = 640 - new_unpad_w # 左右总填充 pad_h = 640 - new_unpad_h # 上下总填充 # 2. 去除填充(坐标平移) x1 = max(0, (pred["x1"] - pad_w / 2) / r) y1 = max(0, (pred["y1"] - pad_h / 2) / r) x2 = min(orig_w, (pred["x2"] - pad_w / 2) / r) y2 = min(orig_h, (pred["y2"] - pad_h / 2) / r) return {"x1": x1, "y1": y1, "x2": x2, "y2": y2} # 示例:原图1280×720,预测框在640×640图上是[100,50,200,150] orig_bbox = map_bbox_to_original( {"x1":100, "y1":50, "x2":200, "y2":150}, orig_w=1280, orig_h=720 ) print(orig_bbox) # {'x1': 200.0, 'y1': 100.0, 'x2': 400.0, 'y2': 300.0}

关键结论:YOLO12不做“智能缩放”,它严格遵循YOLO标准letterbox流程。只要按此公式反算,100%还原原图坐标。

5. 高级用法:置信度阈值与模型切换控制

5.1 动态调整置信度阈值(conf)

虽然WebUI提供滑块,但API也支持运行时控制——通过URL查询参数

# 将置信度阈值设为0.4(更严格,减少误检) curl -X POST "http://192.168.1.100:8000/predict?conf=0.4" \ -F "file=@test.jpg" # 设为0.1(更宽松,召回更多目标) curl -X POST "http://192.168.1.100:8000/predict?conf=0.1" \ -F "file=@test.jpg"
  • conf参数范围:0.01~0.99(超出范围将被截断为最近合法值)
  • 未提供时,默认值为0.25(与WebUI初始值一致)
  • 该参数不影响模型加载或显存占用,纯CPU侧过滤,无性能损耗

5.2 模型规格切换(需重启服务)

注意:模型切换不是API参数,而是服务启动时的环境变量配置。这意味着:

  • 你不能在一次API请求中指定“这次用nano,下次用xlarge”;
  • 所有API请求共享同一个已加载的模型实例;
  • 切换模型必须:修改环境变量 → 重启服务 → 等待权重加载完成(约3-5秒)。

操作步骤(在镜像内终端执行):

# 1. 设置新模型(例如切到small版) export YOLO_MODEL=yolov12s.pt # 2. 重启服务(自动加载新权重) bash /root/start.sh # 3. 验证是否生效(查看日志末尾) tail -n 10 /root/logs/start.log # 成功日志:"Loaded model: yolov12s.pt (19.2MB) on cuda:0"

验证技巧:调用API后检查响应中的input_size不变,但predictions数量和置信度分布会变化——small版通常比nano版多检出10%~15%的低置信目标。

6. 故障排查清单:5分钟定位90%问题

遇到调用失败?按此顺序快速检查:

现象可能原因快速验证方法解决方案
HTTP 400 Bad Requestfile字段名拼错、未传文件、文件为空curl -v看请求体是否含name="file"检查代码中files键名,确认文件对象非None
HTTP 422 Unprocessable EntityContent-Type头缺失或错误、boundary不匹配curl -v确认header含multipart/form-data; boundary=删除手动设置的Content-Type头,让客户端自动生成
HTTP 500 Internal Server Error图片损坏、非支持格式、内存不足查看/root/logs/api.log末尾错误栈file test.jpg确认格式;换一张已知正常的图重试
响应为空或超时实例未启动、端口被防火墙拦截、GPU显存不足curl -I http://IP:8000/docs看是否返回200检查实例状态;nvidia-smi看GPU内存;netstat -tuln | grep 8000
检测结果为空([])图像全黑/全白、目标过小(<16px)、置信度过高降低conf参数至0.1重试;用WebUI上传同一张图对比调整conf;确认图像内容符合COCO类别

🛠终极诊断命令(在镜像内执行):

# 查看API服务实时日志(滚动跟踪) tail -f /root/logs/api.log # 检查模型是否加载成功 grep "Loaded model" /root/logs/start.log # 测试本地API连通性(绕过网络) curl -X POST "http://localhost:8000/predict" -F "file=@/root/test.jpg"

7. 总结:掌握接口规范就是掌握集成主动权

你不需要成为YOLO专家,也能把目标检测能力稳稳接入自己的系统。本文拆解的不是抽象概念,而是可立即验证、可逐行调试、可跨语言复用的具体规范

  • multipart/form-data不是玄学,它就是带boundary的二进制包裹,name="file"是唯一钥匙;
  • 所有坐标都基于640×640,但逆letterbox公式给你原图精度;
  • conf参数让你在灵敏度和准确率间自由滑动,无需改一行模型代码;
  • 模型切换虽需重启,但5秒加载+软链设计,让A/B测试成本趋近于零。

当你下次面对安防摄像头流、电商商品图、工业质检样本时,心里清楚:
只要构造对那个file字段,剩下的,交给YOLO12。


获取更多AI镜像

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

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

Chord在教育场景的应用:课堂视频关键动作识别与时间戳标注实践

Chord在教育场景的应用&#xff1a;课堂视频关键动作识别与时间戳标注实践 1. 为什么课堂视频分析需要“时空定位”能力&#xff1f; 传统教学视频分析工具大多停留在“看完了再总结”的层面——要么靠人工反复拖动进度条标记重点&#xff0c;要么用通用视频理解模型生成一段…

作者头像 李华
网站建设 2026/3/20 0:39:15

前端调试新利器:Midscene.js自动化测试与浏览器工具实战指南

前端调试新利器&#xff1a;Midscene.js自动化测试与浏览器工具实战指南 【免费下载链接】midscene Let AI be your browser operator. 项目地址: https://gitcode.com/GitHub_Trending/mid/midscene 你是否也曾遇到这样的困扰&#xff1a;辛辛苦苦写的自动化脚本&#…

作者头像 李华
网站建设 2026/3/20 7:04:56

Qwen3-ASR-0.6B方言识别效果展示:22种中文方言测试报告

Qwen3-ASR-0.6B方言识别效果展示&#xff1a;22种中文方言测试报告 1. 这个模型到底能听懂多少种“家乡话” 第一次听到Qwen3-ASR-0.6B支持22种中文方言时&#xff0c;我下意识地翻了翻自己的老家录音——一段用闽南语讲的春节拜年话。说实话&#xff0c;当时心里是打鼓的。毕…

作者头像 李华
网站建设 2026/3/27 21:17:41

ChatGLM-6B在物联网中的应用:智能设备控制中心开发

ChatGLM-6B在物联网中的应用&#xff1a;智能设备控制中心开发 1. 当智能家居遇上大模型&#xff1a;为什么需要自然语言控制 你有没有过这样的体验&#xff1a;晚上躺在沙发上&#xff0c;想关掉客厅的灯&#xff0c;却要摸黑找手机、解锁、打开APP、点开智能家居应用、找到…

作者头像 李华
网站建设 2026/3/26 17:52:47

HY-Motion 1.0基础教程:从Git克隆→模型加载→Gradio启动全流程详解

HY-Motion 1.0基础教程&#xff1a;从Git克隆→模型加载→Gradio启动全流程详解 1. 为什么你需要这个教程&#xff1f; 你是不是也遇到过这样的问题&#xff1a; 想试试最新的文生动作模型&#xff0c;但看到“十亿参数”“DiT架构”“Flow Matching”这些词就头皮发紧&#…

作者头像 李华
网站建设 2026/3/24 20:15:55

Arduino-ESP32版本升级实战解决指南:从依赖困境到安全通信

Arduino-ESP32版本升级实战解决指南&#xff1a;从依赖困境到安全通信 【免费下载链接】arduino-esp32 Arduino core for the ESP32 项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32 一、你是否遇到这些升级难题&#xff1f;两个真实开发场景直击痛点 …

作者头像 李华