丹青识画AI编程实践:使用Python脚本批量处理与评估图像数据集

丹青识画AI编程实践:使用Python脚本批量处理与评估图像数据集 丹青识画AI编程实践使用Python脚本批量处理与评估图像数据集作为一名和图像识别算法打了多年交道的工程师我深知在模型迭代过程中最耗时耗力的往往不是调参而是对大量测试数据进行处理、调用模型、收集结果并计算指标。手动一张张上传图片、记录结果效率低下且容易出错。今天我就来分享一个我们团队内部常用的“效率神器”——一套基于Python的自动化脚本它能帮你把丹青识画这类强大的图像识别系统无缝集成到你的算法工作流中实现数据集的批量处理与评估让模型迭代飞起来。这套脚本的核心思路很简单自动化替代手工并发提升速度结构化输出结果。它特别适合需要频繁验证模型在不同数据集上表现的场景比如新模型上线前的效果评估、不同参数配置下的性能对比或者定期对线上模型进行回归测试。1. 脚本设计思路与核心功能在动手写代码之前我们先明确一下脚本需要完成哪些任务以及为什么要这样设计。1.1 核心需求分析面对一个包含成百上千张图片的数据集我们手动操作丹青识画系统无论是Web界面还是API会面临几个痛点操作重复繁琐上传、等待、记录结果循环往复枯燥且易疲劳。效率瓶颈明显串行处理总耗时是所有图片处理时间的总和。结果难以分析识别结果散落在各处需要手动整理成结构化数据如Excel或JSON才能进行统计分析。缺乏过程记录中间状态、失败案例难以追溯和复现。因此我们的脚本需要瞄准这些痛点实现以下核心功能自动化遍历自动扫描指定文件夹下的所有图片文件。批量处理能够一次性提交多张图片进行识别。并发请求利用多线程或异步IO同时处理多张图片大幅缩短总耗时。结果收集将每张图片的识别结果如标签、置信度、位置框等规整地保存下来。性能评估基于预设的真实标签Ground Truth自动计算准确率、召回率、F1分数等关键指标并生成报告。1.2 技术栈选择为了实现上述功能我们选择以下Python库它们都是数据科学和工程领域的“老朋友”组合起来威力强大requests用于发送HTTP请求调用丹青识画的识别API。concurrent.futures或asyncioaiohttp实现并发请求。对于IO密集型的网络请求并发能极大提升效率。ThreadPoolExecutor简单易用适合入门。PIL(Pillow)或opencv-python用于必要的图像预处理如格式转换、尺寸调整、归一化等。pandas处理表格数据的利器用于整理识别结果、计算指标、生成报表。json/yaml用于管理配置文件如API密钥、服务器地址、请求参数等。argparse或click为脚本添加命令行参数使其更灵活例如指定输入目录、输出路径、并发数等。2. 脚本核心模块实现接下来我们分模块拆解代码。假设丹青识画提供了一个标准的RESTful API接收图片并返回识别结果。2.1 环境准备与配置管理首先安装必要的库并创建一个配置文件来管理敏感信息和通用设置。# 安装核心依赖 pip install requests pillow pandas opencv-python创建一个config.yaml文件或config.json# config.yaml api: base_url: https://api.your-danqing-system.com/v1 # 替换为实际API地址 endpoint: /recognize api_key: your_api_key_here # 你的API密钥 timeout: 30 # 请求超时时间秒 processing: supported_formats: [.jpg, .jpeg, .png, .bmp] max_workers: 10 # 并发线程数根据你的网络和API限制调整 batch_size: 5 # 可选如果API支持批量上传可以设置每批图片数 output: result_dir: ./results raw_result_file: raw_predictions.json evaluation_report_file: evaluation_report.csv在Python脚本中读取配置# config_loader.py import yaml import os def load_config(config_pathconfig.yaml): with open(config_path, r, encodingutf-8) as f: config yaml.safe_load(f) # 确保输出目录存在 os.makedirs(config[output][result_dir], exist_okTrue) return config2.2 图像遍历与预处理模块这个模块负责找到所有需要处理的图片并进行必要的预处理。# image_utils.py import os from PIL import Image import cv2 def find_images(root_dir, supported_formats): 递归查找指定目录下所有支持的图片文件 image_paths [] for root, dirs, files in os.walk(root_dir): for file in files: if any(file.lower().endswith(fmt) for fmt in supported_formats): full_path os.path.join(root, file) image_paths.append(full_path) return image_paths def preprocess_image(image_path, target_size(640, 640)): 简单的图像预处理示例。 根据丹青识画API的要求进行调整可能包括 1. 调整尺寸 2. 格式转换 (BGR-RGB) 3. 归一化 # 使用OpenCV读取 img_cv cv2.imread(image_path) if img_cv is None: raise ValueError(f无法读取图片: {image_path}) # 调整尺寸 (保持宽高比) h, w img_cv.shape[:2] scale min(target_size[0] / w, target_size[1] / h) new_w, new_h int(w * scale), int(h * scale) img_resized cv2.resize(img_cv, (new_w, new_h), interpolationcv2.INTER_LINEAR) # BGR 转 RGB (很多API期望RGB) img_rgb cv2.cvtColor(img_resized, cv2.COLOR_BGR2RGB) # 这里可以添加其他预处理如归一化到[0,1]或减去均值等 # processed_img img_rgb / 255.0 # 对于API调用通常需要将图片编码为bytes或base64 # 方法1: 保存到内存字节流 from io import BytesIO is_success, buffer cv2.imencode(.jpg, cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR)) if not is_success: raise ValueError(f图片编码失败: {image_path}) image_bytes buffer.tobytes() return image_bytes, os.path.basename(image_path)2.3 API调用与并发处理模块这是脚本的核心负责高效地调用识别接口。# api_client.py import requests from concurrent.futures import ThreadPoolExecutor, as_completed import time import json from typing import List, Dict, Any class DanqingAPIClient: def __init__(self, config): self.base_url config[api][base_url] self.endpoint config[api][endpoint] self.api_key config[api][api_key] self.timeout config[api][timeout] self.headers { Authorization: fBearer {self.api_key}, Content-Type: application/json, # 根据API要求调整 } def recognize_single_image(self, image_bytes, image_name): 调用API识别单张图片 api_url f{self.base_url}{self.endpoint} # 根据API要求构建请求体这里假设API接受base64编码 import base64 img_b64 base64.b64encode(image_bytes).decode(utf-8) payload { image: img_b64, image_name: image_name, # 可以添加其他参数如识别阈值、返回top-k结果等 threshold: 0.5, top_k: 3 } try: response requests.post( api_url, headersself.headers, jsonpayload, timeoutself.timeout ) response.raise_for_status() # 如果状态码不是200抛出异常 result response.json() # 将图片名和结果绑定 result[image_name] image_name return result except requests.exceptions.RequestException as e: print(f图片 {image_name} 识别请求失败: {e}) return {image_name: image_name, error: str(e), predictions: []} except json.JSONDecodeError as e: print(f图片 {image_name} 响应解析失败: {e}) return {image_name: image_name, error: Invalid JSON response, predictions: []} def batch_recognize(self, image_data_list, max_workers5): 并发识别多张图片 results [] start_time time.time() with ThreadPoolExecutor(max_workersmax_workers) as executor: # 提交所有任务 future_to_image { executor.submit(self.recognize_single_image, data[0], data[1]): data[1] for data in image_data_list } # 收集完成的任务结果 completed 0 total len(image_data_list) for future in as_completed(future_to_image): image_name future_to_image[future] try: result future.result() results.append(result) except Exception as e: print(f处理图片 {image_name} 时发生异常: {e}) results.append({image_name: image_name, error: str(e), predictions: []}) completed 1 if completed % 10 0 or completed total: print(f处理进度: {completed}/{total} ({completed/total*100:.1f}%)) elapsed time.time() - start_time print(f批量识别完成共处理 {len(results)} 张图片总耗时: {elapsed:.2f} 秒平均每张: {elapsed/len(results):.2f} 秒) return results2.4 结果汇总与评估模块处理完所有图片后我们需要整理结果并与真实标签进行比对计算模型性能。# evaluator.py import pandas as pd import json import os from sklearn.metrics import precision_score, recall_score, f1_score import numpy as np def save_raw_results(results, output_path): 将原始识别结果保存为JSON文件 with open(output_path, w, encodingutf-8) as f: json.dump(results, f, indent2, ensure_asciiFalse) print(f原始结果已保存至: {output_path}) def load_ground_truth(gt_path): 加载真实标签。 假设真实标签是一个CSV文件格式为image_name, true_label 或者是一个JSON文件{image1.jpg: cat, image2.jpg: dog, ...} if gt_path.endswith(.csv): df pd.read_csv(gt_path) # 假设列名为 image_name 和 label gt_dict pd.Series(df[label].values, indexdf[image_name]).to_dict() elif gt_path.endswith(.json): with open(gt_path, r) as f: gt_dict json.load(f) else: raise ValueError(仅支持CSV或JSON格式的真实标签文件。) return gt_dict def evaluate_predictions(raw_results_file, gt_dict, output_report_path): 评估识别结果生成报告 with open(raw_results_file, r) as f: results json.load(f) records [] all_preds [] all_true [] for res in results: img_name res.get(image_name) true_label gt_dict.get(img_name) if true_label is None: print(f警告图片 {img_name} 未找到真实标签已跳过。) continue predictions res.get(predictions, []) # 取置信度最高的预测作为最终结果 pred_label predictions[0].get(label) if predictions else unknown pred_score predictions[0].get(score, 0) if predictions else 0 is_correct (pred_label true_label) records.append({ image_name: img_name, true_label: true_label, pred_label: pred_label, pred_score: pred_score, is_correct: is_correct }) # 为计算总体指标准备数据 all_true.append(true_label) all_preds.append(pred_label) # 创建DataFrame df_report pd.DataFrame(records) # 计算总体指标这里假设是单标签分类 # 注意sklearn的precision/recall需要所有可能标签的列表 unique_labels sorted(set(all_true all_preds)) # 将标签映射为索引以便计算 label_to_idx {label: idx for idx, label in enumerate(unique_labels)} true_indices [label_to_idx[l] for l in all_true] pred_indices [label_to_idx[l] for l in all_preds] precision precision_score(true_indices, pred_indices, averageweighted, zero_division0) recall recall_score(true_indices, pred_indices, averageweighted, zero_division0) f1 f1_score(true_indices, pred_indices, averageweighted, zero_division0) # 计算每个类别的准确率 class_stats df_report.groupby(true_label).agg( total(is_correct, count), correct(is_correct, sum) ).reset_index() class_stats[accuracy] class_stats[correct] / class_stats[total] # 保存详细报告 df_report.to_csv(output_report_path, indexFalse) # 打印评估摘要 print(\n *50) print(模型评估报告) print(*50) print(f评估图片总数: {len(df_report)}) print(f整体准确率: {(df_report[is_correct].sum() / len(df_report) * 100):.2f}%) print(f加权精确率 (Precision): {precision:.4f}) print(f加权召回率 (Recall): {recall:.4f}) print(f加权F1分数: {f1:.4f}) print(\n各类别准确率:) print(class_stats.to_string(indexFalse)) print(*50) # 保存评估摘要到文本文件 summary_path output_report_path.replace(.csv, _summary.txt) with open(summary_path, w) as f: f.write(模型评估报告摘要\n) f.write(*50 \n) f.write(f评估图片总数: {len(df_report)}\n) f.write(f整体准确率: {(df_report[is_correct].sum() / len(df_report) * 100):.2f}%\n) f.write(f加权精确率 (Precision): {precision:.4f}\n) f.write(f加权召回率 (Recall): {recall:.4f}\n) f.write(f加权F1分数: {f1:.4f}\n) return df_report, class_stats3. 主程序与实战演示最后我们将所有模块串联起来并添加命令行参数形成一个完整的、可执行的工具。# main.py import argparse from config_loader import load_config from image_utils import find_images, preprocess_image from api_client import DanqingAPIClient from evaluator import save_raw_results, load_ground_truth, evaluate_predictions def main(): parser argparse.ArgumentParser(description丹青识画批量图像识别与评估脚本) parser.add_argument(--input_dir, -i, requiredTrue, help包含待识别图片的目录) parser.add_argument(--ground_truth, -g, help真实标签文件路径 (CSV/JSON)) parser.add_argument(--config, -c, defaultconfig.yaml, help配置文件路径) parser.add_argument(--skip_eval, actionstore_true, help跳过评估仅进行识别) args parser.parse_args() # 1. 加载配置 print(加载配置...) config load_config(args.config) # 2. 查找并预处理图片 print(f扫描目录: {args.input_dir}) image_paths find_images(args.input_dir, config[processing][supported_formats]) print(f找到 {len(image_paths)} 张待处理图片。) if not image_paths: print(未找到任何图片程序退出。) return print(开始预处理图片...) image_data_list [] for img_path in image_paths: try: img_bytes, img_name preprocess_image(img_path) image_data_list.append((img_bytes, img_name)) except Exception as e: print(f预处理图片 {img_path} 失败: {e}) # 3. 初始化客户端并批量识别 print(初始化API客户端...) client DanqingAPIClient(config) print(f开始批量识别 (并发数: {config[processing][max_workers]})...) raw_results client.batch_recognize( image_data_list, max_workersconfig[processing][max_workers] ) # 4. 保存原始结果 raw_result_path f{config[output][result_dir]}/{config[output][raw_result_file]} save_raw_results(raw_results, raw_result_path) # 5. 评估如果提供了真实标签 if args.ground_truth and not args.skip_eval: print(f加载真实标签: {args.ground_truth}) gt_dict load_ground_truth(args.ground_truth) report_path f{config[output][result_dir]}/{config[output][evaluation_report_file]} print(开始评估模型性能...) evaluate_predictions(raw_result_path, gt_dict, report_path) print(f详细评估报告已生成: {report_path}) else: print(未提供真实标签或已跳过评估步骤。) print(批量处理与评估流程全部完成) if __name__ __main__: main()现在你可以通过命令行轻松运行整个流程# 仅进行批量识别 python main.py -i ./your_dataset/images -c ./config.yaml # 进行批量识别并评估 python main.py -i ./your_dataset/images -g ./your_dataset/labels.csv -c ./config.yaml脚本运行后会在./results目录下生成raw_predictions.json所有图片的原始识别结果和evaluation_report.csv每张图片的详细对错情况以及一个evaluation_report_summary.txt整体性能指标摘要。4. 总结与扩展建议这套脚本用下来最大的感受就是“省心”。以前需要半天手动处理的测试集现在喝杯咖啡的功夫就出报告了。它把我们从重复劳动中解放出来让我们能更专注于模型本身的优化和分析。脚本的核心价值在于标准化和可复用。一旦搭建好它就成了团队的基础设施。无论是新同事接手还是需要对比不同版本的模型都可以用同一套流程来跑结果具有可比性。生成的CSV报告可以直接用Excel或Pandas做进一步分析比如找出模型在哪些类别上表现不佳哪些图片容易识别错误为后续的模型优化提供了非常清晰的方向。当然这只是一个起点。根据实际需求你还可以对它进行很多增强更丰富的评估指标对于目标检测任务可以集成mAP的计算对于分割任务可以计算IoU。错误案例分析自动将识别错误的图片复制到一个单独的文件夹方便人工复查。可视化报告用matplotlib或seaborn生成混淆矩阵、PR曲线等图表让报告更直观。集成到CI/CD将脚本作为自动化测试的一环在模型训练完成后自动进行评估确保性能达标。支持更多API参数根据丹青识画系统的能力增加对识别区域、特定模型版本等参数的控制。工具的价值在于适配业务。建议你先用这个基础版本跑通流程感受一下自动化带来的效率提升。然后再根据你团队的具体工作流和丹青识画系统的特性逐步添加你需要的功能。好的工具是迭代出来的而不是一开始就设计得大而全。希望这个分享能为你和你的团队带来实实在在的效率提升。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。