2026/4/20 6:10:31
网站建设
项目流程
百度微信网站,新手学做网站,万全孔家庄做网站,网站项目建设背景批量识别多张图片#xff1f;Python脚本扩展教程来了
1. 为什么单张识别不够用#xff1a;从“能跑通”到“真可用”的关键一步
你已经成功运行了推理.py#xff0c;看到终端输出“白领女性”“办公室工作场景”这些中文标签时#xff0c;心里一定很踏实——模型确实能工…批量识别多张图片Python脚本扩展教程来了1. 为什么单张识别不够用从“能跑通”到“真可用”的关键一步你已经成功运行了推理.py看到终端输出“白领女性”“办公室工作场景”这些中文标签时心里一定很踏实——模型确实能工作。但很快你会发现现实中的需求从来不是一张图、一次识别。电商运营要审核上千张商品图教育平台需自动标注学生上传的实验照片内容社区每天收到数万张用户投稿……这些场景下手动改一次路径、运行一次脚本不仅效率低得让人抓狂还极易出错漏改路径、忘记保存、结果混在一起分不清哪张对应哪个输出。真正的工程落地不看“能不能识别一张”而看“能不能稳稳识别一百张、一千张”。本文不重复讲环境怎么装、模型怎么加载——那些你已经会了。我们直接聚焦如何把单图识别脚本变成一个可靠、可复用、能处理真实业务数据的批量识别工具。全程基于你已有的镜像环境PyTorch 2.5 py311wwtsconda 环境无需额外安装复杂依赖所有代码均可直接复制粘贴运行。你会学到怎么让脚本自动扫描整个文件夹里的图片不用再手动改路径怎么把每次识别的结果清晰记录下来避免结果堆在终端里找不到怎么跳过损坏图片、跳过非支持格式让批量任务不因一张坏图就中断怎么控制识别速度和显存占用让老显卡也能扛住百图连跑这不是理论推演而是你明天就能用上的实操方案。2. 批量识别核心改造四步重构原脚本原推理.py是为单图设计的硬编码路径、单次执行、结果只打印到屏幕。我们要让它“长大”支撑真实工作流。改造不追求大动干戈而是精准替换四个关键环节。2.1 第一步从固定路径到动态遍历原脚本中这行代码是瓶颈image_path /root/workspace/bailing.png它把脚本锁死在一张图上。我们需要它能“自己找图”。改造方案使用glob模块匹配指定目录下所有常见图片格式并加入容错检查import glob import os # 定义图片搜索目录你可按需修改 input_dir /root/workspace/test_images # 支持的图片格式小写大写都覆盖 supported_exts [*.png, *.jpg, *.jpeg, *.bmp, *.tiff, *.webp] image_paths [] for ext in supported_exts: image_paths.extend(glob.glob(os.path.join(input_dir, ext))) image_paths.extend(glob.glob(os.path.join(input_dir, ext.upper()))) # 去重并排序确保顺序一致 image_paths sorted(list(set(image_paths))) print(f共找到 {len(image_paths)} 张待识别图片) if not image_paths: print( 警告未找到任何图片请检查目录路径和文件格式) exit(1)效果脚本启动后自动列出/root/workspace/test_images下所有图片无论你放1张还是100张它都“看得见”。2.2 第二步从屏幕打印到结构化记录原脚本把结果全打在终端里100张图的输出就是一长串滚动文字根本没法查。我们需要结果“落盘”且格式清晰。改造方案用CSV文件记录每张图的Top-5结果包含文件名、识别标签、置信度、处理时间import csv import time # 创建结果CSV文件 output_csv /root/workspace/batch_results.csv with open(output_csv, w, newline, encodingutf-8) as f: writer csv.writer(f) # 写入表头 writer.writerow([文件名, 排名, 中文标签, 置信度(%), 处理耗时(秒)]) # 在循环处理每张图时追加写入 for i, img_path in enumerate(image_paths): start_time time.time() try: # 【此处插入原推理逻辑加载图、预处理、模型推理、获取top5】 # 具体代码见2.4节完整脚本 # 记录结果 with open(output_csv, a, newline, encodingutf-8) as f: writer csv.writer(f) for rank, (label, prob) in enumerate(zip(top5_labels, top5_probs), 1): writer.writerow([ os.path.basename(img_path), rank, label, f{prob:.1f}, f{time.time() - start_time:.2f} ]) print(f 已处理 {i1}/{len(image_paths)}: {os.path.basename(img_path)}) except Exception as e: # 关键单张失败不中断整体流程 error_msg str(e)[:100] # 截断过长错误信息 print(f 处理失败 {os.path.basename(img_path)}: {error_msg}) with open(output_csv, a, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([os.path.basename(img_path), ERROR, str(e), , ])效果运行结束后batch_results.csv里是一张清晰表格Excel双击就能打开按“文件名”筛选、按“置信度”排序一目了然。2.3 第三步从硬编码标签到动态加载中文词表原脚本示例里labels是写死的列表labels [白领女性, 办公室工作场景, ...]这完全不可靠。真实模型的中文标签有上万个必须从官方配套文件读取。改造方案检查镜像中是否存在label_map_zh.json或label_map_zh.csv优先加载JSON更通用import json # 尝试加载中文标签映射文件 label_file None for candidate in [/root/label_map_zh.json, /root/workspace/label_map_zh.json]: if os.path.exists(candidate): label_file candidate break if label_file: with open(label_file, r, encodingutf-8) as f: label_map json.load(f) # 假设JSON结构为 { 0: 盆栽植物, 1: 笔记本电脑, ... } # 将数字ID转为中文标签 top5_labels [label_map.get(str(idx.item()), f未知类别{idx.item()}) for idx in top5_catid] else: print( 未找到中文标签文件将使用模型内置默认标签可能为英文) # 回退到模型自带方法如 model.get_labels() top5_labels [model.get_label(idx.item()) for idx in top5_catid]效果你的结果永远是准确的中文不会因为忘了更新硬编码列表而出现“potted plant”这种尴尬输出。2.4 第四步从单次执行到可控批量——添加实用开关真实场景需要灵活性有时只想试跑前10张有时要跳过低置信度结果有时显存紧张得降分辨率。改造方案在脚本开头添加配置区用变量控制行为# 批量识别配置区按需修改 BATCH_SIZE 1 # 每次送入模型的图片数1逐张1需改代码适配batch推理 MAX_IMAGES 100 # 最多处理多少张设为None则处理全部 MIN_CONFIDENCE 0.5 # 低于此置信度的标签不写入结果0.0~1.0 RESIZE_SHORTER_SIDE 256 # 图像短边缩放尺寸原256显存紧可设128 # # 在图像预处理部分应用缩放 preprocess transforms.Compose([ transforms.Resize(RESIZE_SHORTER_SIDE), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ])效果只需改几个数字就能适应不同硬件和业务需求不用每次重写逻辑。3. 完整可运行脚本复制即用开箱批量识别下面是你可以直接保存为batch_inference.py并运行的完整代码。它整合了上述所有改造已通过镜像环境实测。# -*- coding: utf-8 -*- # batch_inference.py - 万物识别中文版批量处理脚本 import torch import glob import os import csv import time import json from PIL import Image from torchvision import transforms import numpy as np # 批量识别配置区按需修改 input_dir /root/workspace/test_images # 待识别图片所在文件夹 output_csv /root/workspace/batch_results.csv # 结果保存路径 BATCH_SIZE 1 MAX_IMAGES None # 设为数字如50只处理前50张设为None处理全部 MIN_CONFIDENCE 0.3 RESIZE_SHORTER_SIDE 256 # def load_chinese_labels(): 尝试加载中文标签映射文件 for candidate in [ /root/label_map_zh.json, /root/workspace/label_map_zh.json, /root/label_map_zh.csv ]: if os.path.exists(candidate): if candidate.endswith(.json): with open(candidate, r, encodingutf-8) as f: return json.load(f) else: # CSV格式假设第一列是ID第二列是中文标签 import csv labels {} with open(candidate, r, encodingutf-8) as f: reader csv.reader(f) for row in reader: if len(row) 2: labels[row[0].strip()] row[1].strip() return labels return None def main(): print( 正在搜索图片...) supported_exts [*.png, *.jpg, *.jpeg, *.bmp, *.tiff, *.webp] image_paths [] for ext in supported_exts: image_paths.extend(glob.glob(os.path.join(input_dir, ext))) image_paths.extend(glob.glob(os.path.join(input_dir, ext.upper()))) image_paths sorted(list(set(image_paths))) if not image_paths: print( 错误未在, input_dir, 中找到任何图片文件) return if MAX_IMAGES: image_paths image_paths[:MAX_IMAGES] print(f 共找到 {len(image_paths)} 张图片开始批量识别...) # 加载模型 print(⏳ 正在加载模型...) device torch.device(cuda if torch.cuda.is_available() else cpu) try: model torch.hub.load(alibaba-damo-academy/vision, universal_image_recognition, sourcegithub) model.to(device).eval() print( 模型加载完成) except Exception as e: print( 模型加载失败:, e) return # 加载中文标签 label_map load_chinese_labels() if label_map is None: print( 未找到中文标签文件将使用模型内置标签可能为英文) # 创建CSV文件并写入表头 with open(output_csv, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([文件名, 排名, 中文标签, 置信度(%), 处理耗时(秒)]) # 图像预处理 preprocess transforms.Compose([ transforms.Resize(RESIZE_SHORTER_SIDE), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ]) # 逐张处理 for i, img_path in enumerate(image_paths): start_time time.time() try: # 加载并预处理图像 image Image.open(img_path).convert(RGB) input_tensor preprocess(image) input_batch input_tensor.unsqueeze(0).to(device) # 推理 with torch.no_grad(): output model(input_batch) # 后处理 probabilities torch.nn.functional.softmax(output[0], dim0) top5_prob, top5_catid torch.topk(probabilities, 5) # 获取中文标签 if label_map: top5_labels [] for idx in top5_catid: key str(idx.item()) label label_map.get(key, f未知类别{key}) top5_labels.append(label) else: # 回退尝试用模型方法若模型支持 try: top5_labels [model.get_label(idx.item()) for idx in top5_catid] except: top5_labels [f类别{idx.item()} for idx in top5_catid] # 写入CSV with open(output_csv, a, newline, encodingutf-8) as f: writer csv.writer(f) for rank, (label, prob) in enumerate(zip(top5_labels, top5_prob), 1): if prob.item() MIN_CONFIDENCE: writer.writerow([ os.path.basename(img_path), rank, label, f{prob.item()*100:.1f}, f{time.time() - start_time:.2f} ]) print(f [{i1}/{len(image_paths)}] {os.path.basename(img_path)} - {top5_labels[0]} ({top5_prob[0].item()*100:.0f}%)) except Exception as e: error_msg str(e)[:80] print(f [{i1}/{len(image_paths)}] {os.path.basename(img_path)} 处理失败: {error_msg}) with open(output_csv, a, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([os.path.basename(img_path), ERROR, str(e), , ]) print(f\n 批量识别完成结果已保存至 {output_csv}) print( 提示用Excel打开CSV按文件名列筛选可快速查看某张图的全部结果) if __name__ __main__: main()使用步骤确保你的镜像已激活conda activate py311wwts创建测试图片文件夹mkdir -p /root/workspace/test_images将你要识别的图片PNG/JPG等放入该文件夹将上面完整代码保存为/root/workspace/batch_inference.py运行cd /root/workspace python batch_inference.py预期输出正在搜索图片... 共找到 42 张图片开始批量识别... ⏳ 正在加载模型... 模型加载完成 [1/42] product_001.jpg - 无线蓝牙耳机 (97%) [2/42] scene_002.png - 城市街景 (94%) ... 批量识别完成结果已保存至 /root/workspace/batch_results.csv4. 实战技巧与避坑指南让批量更稳、更快、更准脚本跑通只是起点。在真实数据上长期使用你会遇到各种“意料之外但情理之中”的问题。以下是基于镜像环境反复验证的实战经验。4.1 图片损坏自动跳过不中断流程网络下载或手机拍摄的图片常有损坏如截断的JPG原生PIL打开会直接报错退出。我们的脚本已内置防护try: image Image.open(img_path).convert(RGB) except Exception as e: print(f 跳过损坏图片 {os.path.basename(img_path)}: {e}) continue # 直接进入下一张不终止整个批次价值100张图里哪怕有3张打不开其余97张照常识别结果CSV里会明确标记为ERROR你一眼就能定位问题源。4.2 显存爆了一键切换CPU模式不改代码当GPU显存不足尤其处理高分辨率图时不必重装环境或改脚本。只需在运行命令后加一个环境变量# 强制使用CPU适合显存紧张或无GPU环境 CUDA_VISIBLE_DEVICES python batch_inference.py # 或者限制只用第一块GPU如果有多卡 CUDA_VISIBLE_DEVICES0 python batch_inference.py脚本中的torch.device(cuda if torch.cuda.is_available() else cpu)会自动响应。4.3 结果太多用Excel快速分析Top-Nbatch_results.csv导出后在Excel里筛选高频标签对“中文标签”列使用“数据透视表”看哪些标签出现最多反推数据集共性定位低质结果筛选“置信度(%)” 60 的行集中检查这些图片——是模糊角度怪还是模型真不擅长统计处理效率对“处理耗时(秒)”列求平均值就知道你的硬件每秒能处理几张图4.4 想加水印或自动归档两行代码搞定批量识别后常需对原图做后续操作。利用Python的shutil和PIL轻松扩展# 在识别成功后自动复制原图到high_conf文件夹 if top5_prob[0].item() 0.8: # 置信度80% import shutil shutil.copy2(img_path, /root/workspace/high_conf/) # 或者给原图加识别结果水印需安装PIL from PIL import ImageDraw, ImageFont draw ImageDraw.Draw(image) font ImageFont.load_default() draw.text((10, 10), f{top5_labels[0]} ({top5_prob[0].item()*100:.0f}%), fillred) image.save(/root/workspace/annotated/ os.path.basename(img_path))5. 总结批量不是功能而是生产就绪的标志当你能把一个单图识别脚本稳稳地扩展成处理上百张真实业务图片的工具时你就跨过了从“技术验证”到“工程落地”的关键门槛。本文没有教你新模型、新算法而是聚焦于如何让已有的强大能力在真实场景中真正发挥价值。你掌握的不仅是几行代码更是鲁棒性思维不假设数据完美主动处理异常工程化习惯结果必须可追溯、可分析、可集成用户视角CSV比终端打印友好配置变量比改代码安全现在你的batch_inference.py已经就位。下一步就是把它用起来把竞品官网的商品图扒下来批量识别看他们主打什么品类上传自己手机相册里的100张生活照看看AI眼中的你是什么标签和同事共享这个脚本让他也试试识别他收藏的宠物图技术的温度不在参数多高而在它是否伸手可及、触手可用。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。