实时口罩检测-通用多图批量检测教程:Python调用+结果导出

张开发
2026/4/15 11:31:15 15 分钟阅读

分享文章

实时口罩检测-通用多图批量检测教程:Python调用+结果导出
实时口罩检测-通用多图批量检测教程Python调用结果导出你是不是遇到过这样的场景需要快速检查一批照片里有多少人戴了口罩一张张手动看太费时间用现成的软件又不够灵活。今天我就来分享一个实用的解决方案如何用Python直接调用“实时口罩检测-通用”模型实现多张图片的批量检测并且把检测结果谁戴了口罩、谁没戴清晰地导出保存。这个教程会带你从零开始即使你之前没怎么接触过模型调用也能跟着一步步做出来。我们会用到ModelScope的模型和Gradio部署的服务但重点不是部署而是怎么用Python代码去调用它、批量处理图片、以及把结果整理成我们想要的格式。1. 准备工作理解我们要做什么在开始写代码之前我们先搞清楚整个流程和目标。1.1 模型能做什么“实时口罩检测-通用”模型是一个专门用来识别图片中的人是否佩戴口罩的工具。你给它一张图片它就能找出图片里所有的人脸然后用框框标出来并且告诉你是“戴了口罩”facemask还是“没戴口罩”no facemask。这个模型本身已经用Gradio部署好了有一个Web界面可以上传单张图片查看结果。但我们的目标是超越这个Web界面实现批量处理一次性传入多张图片而不是一张张上传。程序化调用用Python代码控制整个过程方便集成到其他自动化流程里。结果导出把检测结果图片中每个框的位置、类别保存下来比如存成JSON文件或者Excel表格。1.2 你需要准备什么一个可访问的模型服务地址假设你已经通过Gradio部署好了“实时口罩检测-通用”模型并且知道它的服务地址例如http://localhost:7860或某个在线服务的URL。这是我们的API端点。Python环境你的电脑上需要安装Python建议3.7及以上版本。几个Python库我们主要通过requests库来发送HTTP请求调用模型用PILPillow或opencv-python来处理图片。还需要os,json,time等标准库。一堆待检测的图片把你想要检测的图片放在一个文件夹里。2. 核心步骤用Python调用检测APIGradio部署的应用通常会提供一个API接口。虽然模型介绍里没直接说但Gradio应用默认支持通过/api/predict这个路径来以编程方式调用。我们的核心就是向这个地址发送图片数据并获取结果。2.1 单张图片检测函数我们先写一个函数实现调用模型检测单张图片。import requests import json import base64 from PIL import Image import io import time def detect_single_image(image_path, api_url): 调用口罩检测API检测单张图片。 参数: image_path (str): 图片文件的路径。 api_url (str): Gradio应用API的完整URL例如 http://localhost:7860/api/predict。 返回: dict: API返回的JSON结果通常包含检测框、标签等信息。 如果失败返回None。 # 1. 准备图片数据将图片转换为base64编码的字符串 try: with open(image_path, rb) as f: image_bytes f.read() # 对字节进行base64编码并解码为字符串因为JSON需要字符串 image_b64 base64.b64encode(image_bytes).decode(utf-8) except Exception as e: print(f读取图片失败 {image_path}: {e}) return None # 2. 构造请求数据 # Gradio API通常期望一个包含输入数据的列表顺序与Web界面的输入组件一致。 # 对于这个模型输入可能是一个图片文件。我们以base64形式传递。 # 注意具体格式可能需要根据实际Gradio应用的输入组件调整。 payload { data: [ # 这里假设API接受一个包含图片数据的字典键名可能是image或data # 一种常见格式是传递一个包含mime类型和数据的字典 { name: image_path.split(/)[-1], # 可选传递文件名 data: fdata:image/jpeg;base64,{image_b64} # 数据URI格式 } ] } # 另一种更通用的方式如果上一种不行是直接模仿Gradio客户端的行为 # payload { # data: [image_b64] # 直接传递base64字符串 # } # 你需要查看Gradio应用的源码或通过浏览器开发者工具观察网络请求来确定格式。 headers { Content-Type: application/json } # 3. 发送POST请求 try: response requests.post(api_url, datajson.dumps(payload), headersheaders, timeout30) response.raise_for_status() # 如果状态码不是200抛出异常 result response.json() return result except requests.exceptions.RequestException as e: print(fAPI请求失败: {e}) if hasattr(e.response, text): print(f错误响应: {e.response.text}) return None except json.JSONDecodeError as e: print(f解析API响应失败: {e}) print(f原始响应: {response.text}) return None # 使用示例 if __name__ __main__: # 替换成你的Gradio应用API地址 API_URL http://localhost:7860/api/predict test_image ./test_photo.jpg result detect_single_image(test_image, API_URL) if result: print(检测成功) print(json.dumps(result, indent2, ensure_asciiFalse)) else: print(检测失败。)关键点解释数据格式最难的一步是搞清楚API到底期望什么格式的数据。Gradio的API通常返回一个列表列表中的项对应Web界面上每个输出组件的结果。我们的输入图片需要放在data字段的一个列表里。图片通常以base64编码的字符串传递有时需要包装成data:image/...;base64,...这种数据URI格式。最准确的方法是运行Gradio应用后用浏览器开发者工具F12 - 网络查看当你通过网页上传图片时浏览器发送了什么请求然后模仿那个格式。错误处理网络请求可能失败API格式可能不对所以代码里加了try...except来捕获异常并打印有用的错误信息方便你调试。2.2 处理API返回结果模型返回的结果结构需要你根据实际输出来解析。通常目标检测模型的API会返回一个列表列表里每个元素代表一个检测到的物体包含边界框坐标(x1, y1, x2, y2)或(x_center, y_center, width, height)、置信度confidence、类别标签label或class_id。假设API返回格式如下这是一个示例你需要根据实际输出调整解析代码{ data: [ [ { bbox: [100, 150, 200, 250], // x1, y1, x2, y2 label: facemask, confidence: 0.98 }, { bbox: [300, 180, 380, 280], label: no facemask, confidence: 0.92 } ] ] }我们可以写一个函数来解析这个结果def parse_detection_result(api_result): 解析API返回的检测结果。 参数: api_result (dict): detect_single_image函数返回的字典。 返回: list: 一个列表每个元素是一个字典包含bbox, label, confidence。 如果解析失败或没有检测到目标返回空列表[]。 detections [] if not api_result: return detections try: # 根据上面假设的API返回结构提取数据 # 实际结构需要你根据API的真实响应来调整 data_list api_result.get(data, []) if not data_list: return detections # 通常第一个元素就是检测结果列表 detection_items data_list[0] for item in detection_items: det { bbox: item.get(bbox, []), # [x1, y1, x2, y2] label: item.get(label, unknown), confidence: float(item.get(confidence, 0.0)) } # 确保bbox是列表且长度正确 if isinstance(det[bbox], list) and len(det[bbox]) 4: detections.append(det) except Exception as e: print(f解析检测结果时出错: {e}) print(f原始结果: {api_result}) return detections # 结合使用 result detect_single_image(./test.jpg, API_URL) parsed_dets parse_detection_result(result) for i, det in enumerate(parsed_dets): print(f目标{i1}: 标签{det[label]}, 置信度{det[confidence]:.2f}, 框{det[bbox]})3. 实现多图批量检测与结果导出有了单张图片检测的能力批量处理就很简单了遍历文件夹里的所有图片对每张图片调用检测函数然后把结果收集起来。3.1 批量检测函数import os from glob import glob def batch_detect_images(image_folder, api_url, image_extensions(*.jpg, *.jpeg, *.png, *.bmp)): 批量检测一个文件夹下的所有图片。 参数: image_folder (str): 存放图片的文件夹路径。 api_url (str): Gradio应用API的URL。 image_extensions (tuple): 要处理的图片文件扩展名通配符。 返回: dict: 一个字典键为图片文件名值为该图片的解析后检测结果列表。 all_results {} # 获取文件夹下所有指定格式的图片路径 image_paths [] for ext in image_extensions: image_paths.extend(glob(os.path.join(image_folder, ext))) print(f在文件夹 {image_folder} 中找到 {len(image_paths)} 张图片。) for i, img_path in enumerate(image_paths): filename os.path.basename(img_path) print(f正在处理 ({i1}/{len(image_paths)}): {filename}) # 调用单张图片检测 api_result detect_single_image(img_path, api_url) if api_result is None: print(f - 检测失败跳过。) all_results[filename] [] continue # 解析结果 detections parse_detection_result(api_result) print(f - 检测到 {len(detections)} 个人脸。) all_results[filename] detections # 可选添加一点延迟避免对服务器请求过于频繁 time.sleep(0.1) return all_results # 使用示例 if __name__ __main__: IMAGE_FOLDER ./my_photos # 你的图片文件夹 API_URL http://localhost:7860/api/predict batch_results batch_detect_images(IMAGE_FOLDER, API_URL) print(f\n批量检测完成。共处理 {len(batch_results)} 张图片。)3.2 将结果导出为JSON文件JSON格式灵活易于被其他程序读取。import json def save_results_to_json(results_dict, output_json_path): 将批量检测结果保存为JSON文件。 参数: results_dict (dict): batch_detect_images函数返回的结果字典。 output_json_path (str): 输出的JSON文件路径。 # 为了更好的可读性我们可以稍微整理一下数据结构 export_data { detection_summary: { total_images: len(results_dict), total_faces_detected: sum(len(dets) for dets in results_dict.values()), facemask_count: sum(1 for dets in results_dict.values() for d in dets if d.get(label) facemask), no_facemask_count: sum(1 for dets in results_dict.values() for d in dets if d.get(label) no facemask), }, image_details: [] } for filename, detections in results_dict.items(): img_info { filename: filename, face_count: len(detections), detections: detections # 直接包含原始检测信息列表 } export_data[image_details].append(img_info) try: with open(output_json_path, w, encodingutf-8) as f: # indent参数让JSON文件有缩进更易读 json.dump(export_data, f, indent2, ensure_asciiFalse) print(f结果已成功导出到: {output_json_path}) except Exception as e: print(f保存JSON文件失败: {e}) # 使用示例 output_json ./mask_detection_results.json save_results_to_json(batch_results, output_json)3.3 将结果导出为CSV/Excel文件如果你习惯用表格软件如Excel查看和分析数据CSV格式是更好的选择。我们可以用Python内置的csv模块或者更强大的pandas库。使用pandas推荐需要安装pandas库:import pandas as pd def save_results_to_csv(results_dict, output_csv_path): 将批量检测结果保存为CSV文件。 参数: results_dict (dict): batch_detect_images函数返回的结果字典。 output_csv_path (str): 输出的CSV文件路径。 rows [] for filename, detections in results_dict.items(): for det in detections: bbox det.get(bbox, []) row { image_filename: filename, label: det.get(label, ), confidence: det.get(confidence, 0), bbox_x1: bbox[0] if len(bbox) 0 else , bbox_y1: bbox[1] if len(bbox) 1 else , bbox_x2: bbox[2] if len(bbox) 2 else , bbox_y2: bbox[3] if len(bbox) 3 else , } rows.append(row) if rows: df pd.DataFrame(rows) # 调整列的顺序让文件名在前 column_order [image_filename, label, confidence, bbox_x1, bbox_y1, bbox_x2, bbox_y2] df df[column_order] df.to_csv(output_csv_path, indexFalse, encodingutf-8-sig) # utf-8-sig方便Excel直接打开显示中文 print(f结果已成功导出到CSV: {output_csv_path}) print(df.head()) # 打印前几行看看 else: print(没有检测到任何人脸未生成CSV文件。) # 使用示例 output_csv ./mask_detection_results.csv save_results_to_csv(batch_results, output_csv)4. 完整脚本与使用流程把上面的代码块组合起来就是一个完整的脚本。这里提供一个整合后的版本框架和清晰的使用步骤。完整脚本batch_mask_detector.py框架# batch_mask_detector.py import requests import json import base64 import os import time from glob import glob import pandas as pd # ... (将上面所有函数定义 copy 到这里) ... def main(): # 配置部分 IMAGE_FOLDER ./images_to_check # 替换为你的图片文件夹路径 API_URL http://localhost:7860/api/predict # 替换为你的模型API地址 OUTPUT_JSON ./detection_results.json OUTPUT_CSV ./detection_results.csv # 执行批量检测 print(开始批量口罩检测...) all_results batch_detect_images(IMAGE_FOLDER, API_URL) if not all_results: print(未处理任何图片或所有图片检测失败。请检查配置和图片文件夹。) return # 导出结果 save_results_to_json(all_results, OUTPUT_JSON) save_results_to_csv(all_results, OUTPUT_CSV) print(\n所有操作完成) if __name__ __main__: main()使用流程环境准备确保Python已安装并通过pip install requests pandas Pillow安装必要的库。启动模型服务在你的服务器或本地按照模型说明启动Gradio应用例如运行python /usr/local/bin/webui.py记下服务地址如http://127.0.0.1:7860。准备图片把所有需要检测的图片放到一个文件夹里例如./my_photos。修改配置打开上面的脚本修改IMAGE_FOLDER和API_URL变量为你自己的路径和地址。运行脚本在终端或命令行中进入脚本所在目录运行python batch_mask_detector.py。查看结果脚本运行完毕后会在当前目录生成detection_results.json和detection_results.csv两个文件。用文本编辑器查看JSON用Excel或Numbers打开CSV你就能清晰地看到每张图片的检测统计和每个检测框的详细信息了。5. 总结与进阶建议通过这个教程我们成功地将一个Web界面的口罩检测模型变成了一个可以通过Python代码批量调用、并灵活导出结果的自动化工具。这个过程的核心思路——通过HTTP API调用模型服务并处理返回的结构化数据——可以应用到许多其他AI模型上。几个进阶方向供你探索性能优化如果需要处理成百上千张图片可以考虑使用异步请求如aiohttp库来并发调用API大幅缩短总耗时。结果可视化在导出数据的同时也可以让脚本在原图上画出检测框并保存为新图片这样更直观。可以使用PIL或opencv的绘图功能。集成到工作流将这个脚本作为你自动化流程中的一个环节。例如监控一个文件夹一旦有新图片放入就自动触发检测。错误重试与日志为网络不稳定的情况添加重试机制并配置更完善的日志记录方便排查问题。希望这个教程能帮你高效地完成口罩检测任务。动手试试吧从处理第一张图片开始你会发现自己搭建的自动化工具用起来格外顺手。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

更多文章