
实时口罩检测-通用模型批量图片处理脚本命令行高效调用教程1. 引言告别手动上传拥抱批量处理如果你用过实时口罩检测-通用模型的Web界面可能会觉得它很方便上传一张图片点击按钮就能看到检测结果。但当你需要处理几十张、甚至上百张图片时这种手动操作就显得力不从心了。想象一下一个社区需要批量检查出入人员的口罩佩戴情况或者一个工厂要审核大量监控截图一张张上传不仅效率低下还容易出错。这就是我们今天要解决的问题。本文将带你绕过Web界面直接通过命令行调用模型服务并编写一个Python脚本实现一键批量处理整个文件夹的图片。你将学到如何用几行代码让模型自动识别图片中的人脸并判断是否佩戴口罩最后将结果保存到指定位置。学习目标理解如何通过命令行调用已部署的模型服务掌握编写Python脚本进行批量图片处理的方法学会解析和处理模型的返回结果前置知识基础的Python编程知识了解如何使用命令行终端知道如何安装Python第三方库如requests教程价值 本教程将手把手教你从零开始构建一个高效、可复用的批量处理工具。无论你是开发者、运维人员还是需要处理大量图片的普通用户都能从中受益。我们将用最少的代码实现最强大的功能。2. 环境准备与核心思路在开始编写脚本之前我们需要先理清思路。模型服务已经通过Gradio部署好了它本质上是一个运行在服务器上的Web应用提供了一个我们可以访问的接口API。我们的目标不是重新训练或部署模型而是如何高效地、自动化地向这个接口发送数据并获取结果。2.1 理解模型服务的调用方式根据提供的资料模型服务是通过/usr/local/bin/webui.py这个脚本启动的。Gradio框架在启动后会在本地创建一个Web服务器并暴露一个可供HTTP请求访问的端点Endpoint。虽然资料中未明确给出API的具体URL但Gradio的接口通常有固定的模式。核心思路定位接口找到Gradio服务提供的用于接收图片和返回结果的API地址。模拟请求用Python的requests库模拟浏览器上传图片的行为向这个地址发送HTTP POST请求。处理响应接收服务器返回的JSON格式的检测结果。批量循环将上述步骤套在一个循环里遍历指定文件夹下的所有图片文件。保存结果将检测结果如带标注框的图片、或文本报告保存下来。2.2 安装必要的Python库我们需要一个库来发送网络请求。打开你的终端命令行执行以下命令安装requests库。如果你还需要在图片上画框可以一并安装PillowPIL库。pip install requests Pillow如果安装速度慢可以使用国内镜像源例如pip install requests Pillow -i https://pypi.tuna.tsinghua.edu.cn/simple安装成功后我们就可以开始编写脚本了。3. 分步实践编写批量处理脚本我们将脚本的编写分为几个清晰的步骤确保每一步你都能理解。3.1 第一步探索并确定API地址首先我们需要知道模型服务的具体访问地址。根据常规的Gradio部署当我们运行webui.py后它会在本地启动一个服务默认地址通常是http://127.0.0.1:7860。这个服务会提供两个重要的接口一个用户界面UI就是我们之前用的Web页面。一个应用程序接口API供程序调用的后端地址。Gradio为每个通过gr.Interface创建的界面都会自动生成一个API。假设我们的模型函数名为predict那么它的API端点通常是http://127.0.0.1:7860/api/predict。如何确认确保你的模型服务正在运行即webui.py已启动。打开浏览器访问http://127.0.0.1:7860你应该能看到熟悉的Web界面。打开浏览器的“开发者工具”按F12切换到“网络”(Network)标签页。在Web界面上传一张图片并点击“开始检测”。在“网络”标签页中你会看到一条名为predict或api/predict的请求记录。点击它查看它的“请求URL”这就是我们要找的API地址。为了教程的通用性我们假设API地址为http://127.0.0.1:7860/api/predict。如果你的服务运行在其他机器或端口上请相应修改地址例如http://你的服务器IP:7860/api/predict。3.2 第二步编写单张图片测试脚本在批量处理之前我们先写一个脚本测试单张图片的调用是否成功。创建一个名为test_single_image.py的文件。import requests import json # 1. 设置API地址 API_URL http://127.0.0.1:7860/api/predict # 2. 准备要上传的图片文件 image_path ./test_image.jpg # 替换成你的测试图片路径 # 3. 以二进制形式读取图片 with open(image_path, rb) as f: image_data f.read() # 4. 构建请求数据。Gradio API通常期望一个包含文件的字典。 # 键名如‘image’需要与Gradio接口定义的输入组件名匹配这里我们假设为‘image’。 files { image: (image_path, image_data, image/jpeg) # (文件名, 文件数据, 文件类型) } # 5. 发送POST请求 print(f正在向 {API_URL} 发送请求...) response requests.post(API_URL, filesfiles) # 6. 检查响应 if response.status_code 200: print(请求成功) result response.json() print(原始返回结果) print(json.dumps(result, indent2, ensure_asciiFalse)) # 美化打印JSON else: print(f请求失败状态码{response.status_code}) print(response.text)运行这个脚本python test_single_image.py如果一切正常你会看到服务器返回了一大段JSON数据。这段数据里就包含了检测到的所有框的坐标、类别和置信度。我们的下一步就是解析它。3.3 第三步解析返回结果并可视化Gradio返回的数据结构可能比较复杂通常是一个列表里面包含模型输出的各种信息。对于检测任务我们最关心的是“检测框”。根据资料模型会输出两类facemask戴口罩和no facemask未戴口罩。我们需要从返回的JSON中找到这些数据并把它画到图片上。修改我们的脚本增加解析和画图功能。创建一个新文件batch_process.py。import requests import json import os from PIL import Image, ImageDraw, ImageFont import time # 1. 设置API地址 API_URL http://127.0.0.1:7860/api/predict def detect_single_image(image_path): 检测单张图片并返回结果 with open(image_path, rb) as f: image_data f.read() files {image: (os.path.basename(image_path), image_data, image/jpeg)} try: response requests.post(API_URL, filesfiles, timeout30) # 设置超时时间 response.raise_for_status() # 如果状态码不是200抛出异常 return response.json() except requests.exceptions.RequestException as e: print(f 请求出错{e}) return None def parse_detection_result(result_data, image_size): 解析检测结果。 result_data: 从API返回的JSON数据 image_size: 图片的宽度高度元组 返回一个列表每个元素是 [x1, y1, x2, y2, label, confidence] boxes [] # 注意这里需要根据实际API返回的数据结构来解析 # Gradio的输出可能是嵌套的。假设结果是一个列表第一个元素是包含检测信息的字典或列表 if isinstance(result_data, list) and len(result_data) 0: # 尝试常见的输出格式可能包含‘boxes’, ‘labels’, ‘scores’等键 # 或者是Gradio默认的(output_image, json_data)格式 for item in result_data: if isinstance(item, dict): # 情况1直接是包含检测框的字典 if boxes in item: for box, label, score in zip(item[boxes], item[labels], item[scores]): # 将归一化坐标 [x_center, y_center, width, height] 或 [x1, y1, x2, y2] 转换为像素坐标 # 这里需要你根据实际返回的box格式调整 # 假设box是[x1, y1, x2, y2]且是归一化坐标0-1之间 img_w, img_h image_size x1 int(box[0] * img_w) y1 int(box[1] * img_h) x2 int(box[2] * img_w) y2 int(box[3] * img_h) label_name facemask if label 1 else no facemask boxes.append([x1, y1, x2, y2, label_name, float(score)]) # 情况2Gradio常见的输出格式第一个元素可能是图片第二个是数据 # 我们需要的是数据部分 # 由于API返回结构不确定这里是一个关键调试点。 # 如果上面的解析不成功请先打印出 result_data 的结构然后调整此函数。 print(f 解析到 {len(boxes)} 个检测框。) return boxes def draw_boxes_on_image(image_path, boxes, output_path): 在图片上绘制检测框和标签 img Image.open(image_path) draw ImageDraw.Draw(img) # 定义颜色和字体 color_map {facemask: green, no facemask: red} for box in boxes: x1, y1, x2, y2, label, confidence box color color_map.get(label, blue) # 画矩形框 draw.rectangle([x1, y1, x2, y2], outlinecolor, width3) # 准备标签文本 label_text f{label}: {confidence:.2f} # 计算文本背景框的位置在矩形框上方 try: font ImageFont.truetype(arial.ttf, 20) except IOError: font ImageFont.load_default() text_bbox draw.textbbox((x1, y1-25), label_text, fontfont) # 画文本背景 draw.rectangle(text_bbox, fillcolor) # 画文本 draw.text((x1, y1-25), label_text, fillwhite, fontfont) img.save(output_path) print(f 结果图片已保存至{output_path}) def process_and_save(image_path, output_dir): 处理单张图片检测、解析、画图、保存 print(f处理图片{image_path}) # 1. 调用API检测 result detect_single_image(image_path) if result is None: return # 2. 获取图片尺寸用于坐标解析 with Image.open(image_path) as img: img_size img.size # 3. 解析检测结果 (这里需要你根据实际API返回调整parse_detection_result函数) boxes parse_detection_result(result, img_size) if boxes: # 4. 生成输出路径 base_name os.path.basename(image_path) name_without_ext, ext os.path.splitext(base_name) output_image_path os.path.join(output_dir, f{name_without_ext}_detected{ext}) # 5. 画图并保存 draw_boxes_on_image(image_path, boxes, output_image_path) # 6. (可选) 保存检测结果的文本文件 txt_output_path os.path.join(output_dir, f{name_without_ext}_result.txt) with open(txt_output_path, w) as f: for box in boxes: f.write(f{box}\n) print(f 检测数据已保存至{txt_output_path}) else: print(f 未检测到目标。) # 主函数用于测试单张图片 if __name__ __main__: # 设置输入图片和输出目录 input_image ./test_image.jpg # 你的测试图片 output_directory ./output # 创建输出目录 os.makedirs(output_directory, exist_okTrue) # 处理单张图片 process_and_save(input_image, output_directory)重要提示parse_detection_result函数是本教程最关键也是最需要你调试的部分。因为Gradio API返回的数据格式取决于webui.py中接口的定义。你需要运行test_single_image.py仔细查看打印出的result结构然后修改parse_detection_result函数中的解析逻辑使其能正确提取出boxes框坐标、labels类别ID和scores置信度。常见的返回格式可能是一个列表里面第一个元素是处理后的图片base64编码第二个元素是检测数据。一个字典直接包含boxes、labels、scores等键。其他嵌套结构。调试技巧在parse_detection_result函数开头添加print(“调试:”, result_data)然后处理一张图片根据打印出的实际数据结构来调整代码。3.4 第四步实现批量处理功能单张图片处理成功后批量功能就水到渠成了。我们只需要遍历一个文件夹下的所有图片文件然后对每张图片调用process_and_save函数。在batch_process.py脚本中我们添加一个批量处理的函数并修改主函数。def batch_process_images(input_dir, output_dir, supported_extensions(.jpg, .jpeg, .png, .bmp)): 批量处理一个文件夹中的所有图片 input_dir: 输入图片文件夹路径 output_dir: 输出结果文件夹路径 supported_extensions: 支持的图片文件后缀 # 创建输出目录 os.makedirs(output_dir, exist_okTrue) # 获取所有图片文件 image_files [] for file in os.listdir(input_dir): if file.lower().endswith(supported_extensions): image_files.append(os.path.join(input_dir, file)) if not image_files: print(f在目录 {input_dir} 中未找到支持的图片文件。) return print(f找到 {len(image_files)} 张待处理图片。) print(开始批量处理...) print(- * 50) # 遍历处理每张图片 for i, img_path in enumerate(image_files, 1): print(f[{i}/{len(image_files)}] , end) process_and_save(img_path, output_dir) time.sleep(0.5) # 添加短暂延迟避免对服务器造成过大压力 print(- * 50) print(批量处理完成) print(f所有结果已保存至{output_dir}) # 修改主函数用于批量处理 if __name__ __main__: # 设置输入和输出目录 INPUT_DIRECTORY ./input_images # 存放待检测图片的文件夹 OUTPUT_DIRECTORY ./detection_results # 存放检测结果的文件夹 # 确保输入目录存在 if not os.path.exists(INPUT_DIRECTORY): print(f错误输入目录 {INPUT_DIRECTORY} 不存在。) print(f请创建该目录并将待检测的图片放入其中。) else: # 开始批量处理 batch_process_images(INPUT_DIRECTORY, OUTPUT_DIRECTORY)现在你的完整batch_process.py脚本就具备了批量处理能力。4. 快速上手使用脚本进行批量检测让我们来实际操作一下看看如何用这个脚本处理一个文件夹里的所有图片。4.1 准备工作确保模型服务运行在终端中确保你的webui.py服务正在后台运行。准备图片文件夹在你的项目目录下创建一个名为input_images的文件夹并把所有需要检测的图片.jpg, .png等格式放进去。确认API地址根据第一步的探索确认batch_process.py脚本中API_URL变量的值是正确的。调试解析函数运行一次test_single_image.py根据实际返回的JSON结构调整batch_process.py中的parse_detection_result函数。这是成功的关键。4.2 运行脚本在终端中切换到你的脚本所在目录运行python batch_process.py你会看到类似下面的输出找到 5 张待处理图片。 开始批量处理... -------------------------------------------------- [1/5] 处理图片./input_images/pic1.jpg 解析到 3 个检测框。 结果图片已保存至./detection_results/pic1_detected.jpg 检测数据已保存至./detection_results/pic1_result.txt [2/5] 处理图片./input_images/pic2.jpg ... -------------------------------------------------- 批量处理完成 所有结果已保存至./detection_results4.3 查看结果打开detection_results文件夹你会看到xxx_detected.jpg画上了检测框的结果图片。戴口罩的人脸框是绿色的未戴口罩的是红色的。xxx_result.txt文本文件里面记录了每个检测框的精确坐标、类别和置信度。5. 实用技巧与进阶5.1 处理API返回格式的通用方法如果parse_detection_result函数一直无法正确解析这里提供一个更通用的调试和解析方法def debug_and_parse(result_data, image_size): 一个更健壮的解析函数包含调试信息 print( 开始解析API返回数据 ) print(f数据类型{type(result_data)}) print(f数据内容) # 使用一个辅助函数来打印嵌套结构 def print_data(data, indent0): if isinstance(data, dict): for key, value in data.items(): print( * indent f{key}: , end) if isinstance(value, (dict, list)) and key not in [boxes, labels, scores]: # 对于复杂结构只打印类型和长度 print(f{type(value).__name__} (len{len(value) if isinstance(value, list) else N/A})) if indent 2: # 控制递归深度避免打印过多 print_data(value, indent1) else: print_data(value, indent1) elif isinstance(data, list): print(fList of {len(data)} items) if len(data) 0 and indent 2: print_data(data[0], indent1) # 打印第一个元素的结构 else: print(f{data}) print_data(result_data) print( 结束解析 ) # 根据打印出的结构手动编写提取boxes的代码 # 例如如果发现 boxes 在 result_data[1][boxes] 里 # boxes result_data[1][boxes] # labels result_data[1][labels] # ... 以此类推在process_and_save函数中先用debug_and_parse(result, img_size)替换对parse_detection_result的调用运行一次仔细观察控制台输出就能清晰地看到数据结构。5.2 脚本优化建议错误重试网络请求可能偶尔失败可以添加重试机制。进度保存如果处理大量图片可以记录已处理的文件列表避免脚本中断后从头开始。并发处理使用concurrent.futures模块进行多线程或异步请求可以极大提升处理速度注意服务器负载。配置文件将API地址、输入输出目录等参数写入一个配置文件如config.ini方便修改。6. 总结通过本教程我们成功地将一个需要通过Web界面交互的口罩检测模型转变为一个可以通过命令行批量调用的自动化工具。我们经历了几个关键步骤理解原理明白了模型服务通过HTTP API提供功能我们的脚本就是API的客户端。探索接口学会了如何定位和确认Gradio服务的API端点。编写核心掌握了使用requests库发送图片数据并接收、解析JSON格式的检测结果。结果可视化利用Pillow库将检测框和标签绘制到原图上并保存下来。实现批量通过遍历文件夹和循环调用实现了对大量图片的一键式处理。这个脚本的价值在于其可复用性和高效性。一旦调试成功你可以将其用于任何类似的、基于Gradio部署的视觉检测模型只需调整API地址和结果解析逻辑。它把繁琐的人工操作变成了静默的自动化流程特别适合集成到更大的系统或定期的巡检任务中。下一步建议尝试用这个脚本处理你手头的真实图片集验证其效果和稳定性。探索将输出结果如未戴口罩的图片列表汇总生成一份报告。考虑将脚本打包成更易用的命令行工具支持更多参数。希望这个教程能为你打开一扇门让你看到将AI模型能力与自动化脚本结合所带来的巨大效率提升。动手试试吧你会发现批量处理图片原来可以如此简单。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。