news 2026/5/1 6:27:07

DAMO-YOLO入门教程:使用requests库编写Python客户端批量调用脚本

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DAMO-YOLO入门教程:使用requests库编写Python客户端批量调用脚本

DAMO-YOLO入门教程:使用requests库编写Python客户端批量调用脚本

1. 为什么需要写一个Python客户端?

你已经把DAMO-YOLO服务跑起来了,打开浏览器访问http://localhost:5000,上传一张图,几秒后看到霓虹绿的检测框——很酷。但如果你手头有300张监控截图要分析,或者每天要处理2000张商品图生成结构化标签,再一张张点上传就太折磨人了。

这时候,你需要的不是UI界面,而是一个能自动干活的“数字员工”。它不眨眼、不喊累、不嫌重复,只要给它指令,就能批量把图片发过去、拿回结果、保存数据。本文就带你从零开始,用最基础的requests库,写出一个真正能落地的Python调用脚本——不依赖任何额外框架,不改一行服务端代码,纯客户端实现,小白也能照着敲完立刻跑通。

你不需要懂TinyNAS怎么搜索网络,也不用研究赛博朋克UI的CSS滤镜怎么写的。你只需要知道三件事:服务地址在哪、图片怎么发、返回的数据长什么样。接下来的内容,全部围绕这三点展开。

2. 理解DAMO-YOLO的API通信逻辑

2.1 它不是一个RESTful API,而是一个表单式接口

先破除一个常见误解:很多新手会默认“Web服务=JSON API”,于是尝试用requests.post(url, json={...})发送数据。但DAMO-YOLO的前端是用HTML<form>提交图片的,后端Flask接收的是multipart/form-data类型的表单数据——就像你在网页上点“选择文件”再点“上传”那样。

你可以打开浏览器开发者工具(F12),切换到 Network 标签页,上传一张图,看抓到的请求:

  • Request URL:http://localhost:5000/upload
  • Request Method:POST
  • Content-Type:multipart/form-data; boundary=----WebKitFormBoundary...
  • Form Data里有一项叫file,值就是你选的图片二进制内容

这个file就是关键字段名。后端Flask代码里一定是类似这样写的:

file = request.files['file']

所以你的Python脚本,也必须模拟这个行为:构造一个带file字段的表单,把图片塞进去发出去。

2.2 返回结果是HTML页面?不,是JSON结构化数据

再看返回内容。界面上显示结果时,你以为它只是渲染了HTML?错。实际是前端用JavaScript解析了后端返回的JSON数据,再动态画框、填统计面板。

你可以在Network里点开刚那个POST请求,切换到 Response 标签页,会看到类似这样的内容:

{ "status": "success", "detections": [ {"label": "person", "score": 0.92, "bbox": [124, 87, 231, 412]}, {"label": "car", "score": 0.86, "bbox": [456, 210, 678, 395]} ], "image_url": "/static/results/20260126_142233_output.jpg" }

这才是你真正要拿的数据。它干净、结构化、可编程。你完全不用管那个炫酷的玻璃拟态UI,直接和这个JSON打交道就行。

3. 编写第一个单图调用脚本

3.1 最简可用版本(5行代码)

新建一个single_call.py,粘贴以下代码(请确保你已启动服务):

import requests url = "http://localhost:5000/upload" with open("test.jpg", "rb") as f: files = {"file": f} response = requests.post(url, files=files) print(response.status_code) print(response.json())

注意事项:

  • test.jpg必须和脚本在同一目录下,且是真实存在的图片文件
  • 不要改files字典的键名,必须是"file",这是后端约定的字段名
  • response.json()会自动解析返回的JSON;如果报错,说明返回的不是合法JSON(比如服务没起来、URL错了、图片格式不支持)

运行它,你应该看到类似这样的输出:

200 {'status': 'success', 'detections': [...], 'image_url': '/static/results/...'}

成功!你已经完成了第一次程序化调用。

3.2 加入错误处理和置信度控制

上面的脚本太“裸”了,实际使用中会遇到各种问题:图片打不开、网络超时、服务崩了、返回非200状态码……我们来加一层健壮性:

import requests import time def call_damoyolo(image_path, timeout=30): url = "http://localhost:5000/upload" # 构造带置信度参数的表单(如果后端支持) # 注意:DAMO-YOLO UI里滑块控制的是Confidence Threshold, # 但默认接口可能不接收该参数。我们先尝试加,失败再删。 data = {"confidence": "0.4"} # 设为0.4,比默认0.5更宽松 try: with open(image_path, "rb") as f: files = {"file": f} response = requests.post(url, files=files, data=data, timeout=timeout) if response.status_code == 200: result = response.json() if result.get("status") == "success": return result else: print(f"服务返回异常状态: {result.get('message', '未知错误')}") return None else: print(f"HTTP错误: {response.status_code} - {response.reason}") return None except FileNotFoundError: print(f"错误:找不到图片文件 '{image_path}'") return None except requests.exceptions.Timeout: print("错误:请求超时,请检查服务是否正常运行") return None except requests.exceptions.ConnectionError: print("错误:无法连接到服务,请确认 http://localhost:5000 是否可访问") return None except Exception as e: print(f"未知错误: {e}") return None # 调用示例 if __name__ == "__main__": result = call_damoyolo("test.jpg") if result: print(f"检测到 {len(result['detections'])} 个目标") for det in result["detections"][:3]: # 只打印前3个 print(f" {det['label']} ({det['score']:.2f}) @ {det['bbox']}")

这段代码做了四件事:

  • 把调用逻辑封装成函数,方便复用
  • 加入try/except捕获常见异常(文件不存在、超时、连接失败)
  • 检查HTTP状态码和业务状态码(status: success
  • 对返回结果做基础校验,避免后续处理空数据出错

4. 批量处理:一次调用多张图片

4.1 基础批量循环(顺序执行)

现在把单图脚本升级为批量版。假设你有一个images/文件夹,里面全是.jpg.png图片:

import os import glob import time def batch_process_folder(folder_path, output_file="results.json"): """批量处理指定文件夹下的所有图片""" # 支持的图片格式 image_extensions = ["*.jpg", "*.jpeg", "*.png", "*.bmp"] image_files = [] for ext in image_extensions: image_files.extend(glob.glob(os.path.join(folder_path, ext))) image_files.extend(glob.glob(os.path.join(folder_path, ext.upper()))) if not image_files: print(f"警告:在 '{folder_path}' 中未找到任何图片文件") return print(f"发现 {len(image_files)} 张图片,开始批量处理...") all_results = [] start_time = time.time() for i, img_path in enumerate(image_files, 1): print(f"[{i}/{len(image_files)}] 正在处理: {os.path.basename(img_path)}") result = call_damoyolo(img_path) if result: # 添加原始文件名便于追溯 result["source_image"] = os.path.basename(img_path) all_results.append(result) else: # 记录失败项 all_results.append({ "source_image": os.path.basename(img_path), "status": "failed", "error": "调用失败" }) # 避免请求过于密集,加个小小延迟(可选) time.sleep(0.1) # 保存所有结果到JSON文件 import json with open(output_file, "w", encoding="utf-8") as f: json.dump(all_results, f, ensure_ascii=False, indent=2) end_time = time.time() print(f"\n 批量处理完成!共处理 {len(image_files)} 张,耗时 {end_time - start_time:.1f} 秒") print(f"结果已保存至: {output_file}") # 使用示例 if __name__ == "__main__": batch_process_folder("images/", "batch_results.json")

这个脚本会:

  • 自动扫描images/目录下所有常见图片格式
  • 逐张调用call_damoyolo()函数
  • 把每张图的结果(包括成功和失败)都存进一个大列表
  • 最终导出为batch_results.json,结构清晰,方便后续用Pandas分析或导入数据库

4.2 进阶:并发加速(使用ThreadPoolExecutor)

顺序处理100张图可能要等十几秒。我们可以用线程池并发发送请求,把时间压缩到3-5秒(取决于你的CPU和网络)。注意:这不是“多进程”,因为IO等待是瓶颈,线程足够:

from concurrent.futures import ThreadPoolExecutor, as_completed import threading def batch_process_concurrent(folder_path, max_workers=5, output_file="results_concurrent.json"): """并发批量处理,max_workers 控制同时请求数""" image_extensions = ["*.jpg", "*.jpeg", "*.png", "*.bmp"] image_files = [] for ext in image_extensions: image_files.extend(glob.glob(os.path.join(folder_path, ext))) image_files.extend(glob.glob(os.path.join(folder_path, ext.upper()))) if not image_files: print(f"警告:在 '{folder_path}' 中未找到任何图片文件") return print(f"发现 {len(image_files)} 张图片,启用 {max_workers} 线程并发处理...") # 用线程安全的列表收集结果 results_lock = threading.Lock() all_results = [] def process_single(img_path): result = call_damoyolo(img_path) if result: result["source_image"] = os.path.basename(img_path) else: result = { "source_image": os.path.basename(img_path), "status": "failed", "error": "调用失败" } with results_lock: all_results.append(result) return result start_time = time.time() with ThreadPoolExecutor(max_workers=max_workers) as executor: # 提交所有任务 future_to_img = {executor.submit(process_single, img): img for img in image_files} # 实时打印进度(可选) completed = 0 for future in as_completed(future_to_img): completed += 1 print(f"\r 已完成 {completed}/{len(image_files)}", end="", flush=True) end_time = time.time() # 保存结果 import json with open(output_file, "w", encoding="utf-8") as f: json.dump(all_results, f, ensure_ascii=False, indent=2) print(f"\n\n 并发处理完成!耗时 {end_time - start_time:.1f} 秒") print(f"结果已保存至: {output_file}") # 使用示例(取消注释下面这行来运行) # batch_process_concurrent("images/", max_workers=8)

关键点说明:

  • max_workers=5是推荐起始值。设太高(如20)反而可能因服务端连接数限制导致失败
  • as_completed()让你按完成顺序获取结果,配合\r实现进度条效果
  • threading.Lock()保证多线程写入all_results列表时线程安全

5. 结果解析与实用技巧

5.1 把JSON结果转成Excel报表(一行代码)

你拿到results.json后,想快速看统计?用Pandas两行搞定:

import pandas as pd # 读取结果 df = pd.read_json("batch_results.json") # 展开detections列表,每行一个检测框 rows = [] for _, row in df.iterrows(): if row.get("status") == "success": for det in row["detections"]: rows.append({ "image": row["source_image"], "label": det["label"], "score": det["score"], "x1": det["bbox"][0], "y1": det["bbox"][1], "x2": det["bbox"][2], "y2": det["bbox"][3] }) result_df = pd.DataFrame(rows) result_df.to_excel("detection_summary.xlsx", index=False) print(" Excel报表已生成!")

生成的Excel里,每行是一个检测框,你可以轻松用Excel筛选:“只看person”、“score>0.8的car”、“所有图片中出现最多的类别”。

5.2 保存带框图(可选增强)

DAMO-YOLO返回的image_url是服务端生成的带框图路径(如/static/results/xxx.jpg)。你可以在本地用requests.get()下载它:

def download_annotated_image(result, save_dir="annotated"): """下载带检测框的图片到本地""" if not os.path.exists(save_dir): os.makedirs(save_dir) image_url = result.get("image_url") if not image_url or not image_url.startswith("/static/"): return False # 构造完整URL full_url = f"http://localhost:5000{image_url}" try: response = requests.get(full_url, timeout=10) if response.status_code == 200: filename = os.path.join(save_dir, result["source_image"]) with open(filename, "wb") as f: f.write(response.content) return True except Exception as e: print(f"下载失败 {result['source_image']}: {e}") return False # 在 batch_process_folder 循环里调用 # download_annotated_image(result)

这样你就能得到一份“原始图 + 带框图 + JSON数据”三位一体的交付包。

6. 常见问题与避坑指南

6.1 “Connection refused” 错误

  • 检查服务是否真的在运行:ps aux | grep flaskcurl http://localhost:5000看能否返回HTML
  • 确认启动命令是bash /root/build/start.sh,不是streamlit run app.py
  • 如果你在Docker里运行,确保端口映射正确:-p 5000:5000

6.2 “Unsupported image format”

  • DAMO-YOLO后端用OpenCV/Pillow加载图片,只支持常见格式(JPG/PNG/BMP)
  • 检查图片是否损坏:用系统看图软件能打开吗?
  • 避免使用WebP、HEIC等新格式,先用Photoshop或在线工具转成JPG

6.3 返回的JSON里没有detections字段

  • 先确认图片里确实有目标(用UI界面试传同一张图)
  • 检查置信度阈值是否设得太高(比如传了{"confidence": "0.9"},但图中目标置信度只有0.7)
  • 查看服务端日志:tail -f /root/build/logs/app.log,找报错信息

6.4 批量时部分请求失败,但其他成功

  • 这是正常现象。网络抖动、瞬时负载高都可能导致个别请求失败
  • 我们的脚本已记录失败项,你可以单独重试这些图片
  • 不要盲目加大max_workers,5-8 是大多数场景的甜点值

7. 总结:你已经掌握的核心能力

1. 理清了通信本质

你不再把DAMO-YOLO当成一个“黑盒网页”,而是清楚知道:它接收multipart/form-data表单,返回标准JSON,file是唯一必需字段。

2. 写出了生产级调用函数

call_damoyolo()函数具备完整的异常捕获、超时控制、状态校验,可直接集成进你的项目。

3. 实现了两种批量模式

顺序版脚本适合调试和小批量;并发版脚本让你处理千张图片只需几秒,效率提升立竿见影。

4. 掌握了结果后处理方法

从JSON解析、Excel导出,到带框图下载,你已具备端到端的数据闭环能力。

下一步,你可以:

  • 把这个脚本包装成命令行工具(用argparse
  • 接入定时任务(Linux cron / Windows Task Scheduler),每天凌晨自动处理昨日监控图
  • 把结果推送到企业微信/钉钉机器人,关键目标出现时实时告警

技术的价值,从来不在炫酷的UI,而在于它能不能安静地、可靠地,帮你把重复的事做完。


获取更多AI镜像

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

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

YOLOv12官版镜像发布,支持Flash Attention加速

YOLOv12官版镜像发布&#xff0c;支持Flash Attention加速 YOLO系列目标检测模型的每一次迭代&#xff0c;都在重新定义“实时”与“精准”的边界。当行业还在为YOLOv10的Anchor-Free设计和YOLOv11的动态标签分配机制津津乐道时&#xff0c;一个更根本性的跃迁已经悄然落地——…

作者头像 李华
网站建设 2026/4/30 2:02:26

Ollama平台上的translategemma-27b-it:从安装到实战应用

Ollama平台上的translategemma-27b-it&#xff1a;从安装到实战应用 1. 为什么你需要一个图文双模翻译模型 你有没有遇到过这样的场景&#xff1a; 看到一张中文菜单照片&#xff0c;想立刻知道每道菜的英文名&#xff1b;收到朋友发来的手写笔记截图&#xff0c;内容全是中…

作者头像 李华
网站建设 2026/4/18 13:33:41

Z-Image-ComfyUI API调用教程,实现批量生成

Z-Image-ComfyUI API调用教程&#xff0c;实现批量生成 Z-Image-ComfyUI不是又一个“能出图”的玩具&#xff0c;而是一套真正面向工程落地的文生图生产系统。当你需要每天生成上百张商品图、为营销活动批量产出不同风格的海报、或为AI训练集自动构建带标注的图像样本时&#x…

作者头像 李华
网站建设 2026/4/7 6:26:14

Face3D.ai Pro惊艳效果:眼窝/鼻翼/唇线等微结构几何还原精度展示

Face3D.ai Pro惊艳效果&#xff1a;眼窝/鼻翼/唇线等微结构几何还原精度展示 1. 为什么微结构精度才是3D人脸重建的真正分水岭 很多人第一次听说“AI生成3D人脸”&#xff0c;脑海里浮现的是旋转的卡通头像、模糊的轮廓线&#xff0c;或者动画电影里那种“差不多就行”的建模…

作者头像 李华
网站建设 2026/4/17 5:48:12

EagleEye部署案例:智慧校园周界入侵检测系统低误报率调优实践

EagleEye部署案例&#xff1a;智慧校园周界入侵检测系统低误报率调优实践 1. 项目背景与需求痛点 校园安全是教育管理的底线&#xff0c;而周界防控又是第一道防线。传统红外对射、电子围栏等方案存在明显短板&#xff1a;无法识别入侵者身份、易受天气干扰、无法区分人与动物、…

作者头像 李华
网站建设 2026/4/28 17:35:01

EasyAnimateV5-7b-zh-InP应用案例:教学视频自动生成方案

EasyAnimateV5-7b-zh-InP应用案例&#xff1a;教学视频自动生成方案 教育工作者每天要花大量时间制作课程视频——写脚本、找素材、剪辑、配音、加字幕……一个5分钟的教学短视频&#xff0c;往往需要3-5小时才能完成。当AI能直接把一张教学示意图变成一段自然流畅的讲解动画时…

作者头像 李华