适用练习:3.2.1 图像识别(ResNet)、3.2.2 手写数字识别(MNIST)、3.2.3 面部表情识别(emotion-ferplus)、3.2.4 花朵识别(flower-detection)、3.2.5 人脸检测(version-RFB-320) 目标:零基础学员也能填对所有下划线,理解 ONNX 模型推理的完整流程


📖 一、填空题通用解题心法(速查表)

下表总结了 3.2.1 ~ 3.2.5 中出现的所有填空类型,并给出 可以直接照抄的代码模板出现的练习编号

任务类型 典型填空位置 正确代码模板(直接照抄) 出现在哪个练习
🔌 加载 ONNX 模型 session = _________________ ort.InferenceSession('模型文件名.onnx') 3.2.1, 3.2.2, 3.2.3, 3.2.4, 3.2.5
🏷️ 加载类别标签文件 with _________________ as f: open('labels.txt', 'r') 3.2.1, 3.2.4
📁 读取标签文件所有行 class_names = [_______________ for name in open(...)] name.strip() 3.2.5
🖼️ 加载图片(PIL) image = _________________('RGB')('L') Image.open('img_test.jpg').convert('RGB') 3.2.1, 3.2.2, 3.2.3, 3.2.4
🔧 预处理图片(调用函数) processed_image = _________________ preprocess_image(image) 3.2.1, 3.2.4
📐 调整图片尺寸(PIL) image = _________________((28, 28)) image.resize((28, 28)) 3.2.2
🔢 图片转 numpy 数组 image_array = _________________(_________________, dtype=np.float32) np.array(image, dtype=np.float32) 3.2.2
➕ 添加 batch 维度 image_array = _________________(_________________, axis=0) np.expand_dims(image_array, axis=0) 3.2.2, 3.2.5
🎨 添加通道维度 image_array = _________________(_________________, axis=0)(第二次) np.expand_dims(image_array, axis=0) 3.2.2
🧠 获取模型输入名 input_name = _________________()[0].name session.get_inputs() 3.2.1, 3.2.4, 3.2.5
🔮 执行推理 output = _________________([output_name], {input_name: processed_image})[0] session.run([output_name], {input_name: processed_image}) 3.2.1, 3.2.2, 3.2.3, 3.2.4
📊 应用 softmax probabilities = _________________(output, axis=-1) scipy.special.softmax(output, axis=-1) 3.2.1, 3.2.4
🏆 获取 top5 索引 top5_idx = _________________[-5:][::-1] np.argsort(probabilities[0]) 3.2.1
🏆 获取 top5 概率 top5_prob = _________________ np.sort(probabilities[0])[-5:][::-1] 3.2.1
🎯 获取预测类别(argmax) predicted_class = _________________ np.argmax(ort_outs[0]) 3.2.2, 3.2.3
🗺️ 定义情感映射表 emotion_table = {____________} {'neutral':0, 'happiness':1, 'surprise':2, 'sadness':3, 'anger':4, 'disgust':5, 'fear':6, 'contempt':7} 3.2.3
📁 创建输出目录 os._______________ os.makedirs(result_path) 3.2.5
🖼️ 使用 OpenCV 读取图片 orig_image = _______________ cv2.imread(img_path) 3.2.5
📏 调整图片尺寸(cv2) image = _______________(_______________, (320, 240)) cv2.resize(image, (320, 240)) 3.2.5
📊 定义归一化均值数组 image_mean = _______________([127, 127, 127]) np.array([127, 127, 127]) 3.2.5
➕ 添加 batch 维度(np.newaxis) image = _______________(image, axis=0) np.expand_dims(image, axis=0) 3.2.5
🔮 推理获取 confidences, boxes confidences, boxes = _______________(None, {input_name: image}) ort_session.run(None, {input_name: image}) 3.2.5

记忆口诀: 加载模型用 InferenceSession,读取标签用 open strip; 图片预处理三步走:打开 → 转数组 → 加维度; 运行推理用 session.run,后处理 softmax 或 argmax。


🧠 二、每个函数的“人话解释”(生活类比 + 示例)

函数 / 方法 生活类比 代码示例(小白版)
ort.InferenceSession('model.onnx') 打开一个已经训练好的“模型文件”,准备用它做预测。 session = ort.InferenceSession('resnet.onnx')
Image.open('test.jpg').convert('RGB') 打开一张图片,并确保它是彩色格式(RGB)。 img = Image.open('img_test.jpg').convert('RGB')
img.resize((224, 224)) 把图片缩放到模型要求的尺寸,就像把照片洗成标准证件照大小。 img = img.resize((224, 224))
np.array(img, dtype=np.float32) 把图片转换成计算机能计算的数字矩阵。 arr = np.array(img, dtype=np.float32)
np.expand_dims(arr, axis=0) 给矩阵外面再套一层括号,表示“一批图片中的第一张”。 batch = np.expand_dims(arr, axis=0)
session.get_inputs()[0].name 问模型:“你的第一个输入口叫什么名字?” input_name = session.get_inputs()[0].name
session.run([output_name], {input_name: data}) 把数据喂给模型,让模型计算输出结果。 output = session.run(['output'], {'input': data})[0]
scipy.special.softmax(output, axis=-1) 把模型的原始输出转换成概率(0~1之间,总和为1)。 probs = softmax(output, axis=-1)
np.argmax(probs) 找出概率最大的那个类别的索引(比如第 5 类)。 pred = np.argmax(probs)
cv2.imread(img_path) 用 OpenCV 读取图片(返回 BGR 格式)。 img = cv2.imread('face.jpg')
cv2.resize(img, (320, 240)) 把图片缩放到指定尺寸。 img = cv2.resize(img, (320, 240))
cv2.rectangle(img, (x1,y1), (x2,y2), color, thickness) 在图片上画一个矩形框(用来标记人脸)。 cv2.rectangle(img, (10,10), (100,100), (0,255,0), 2)

⚠️ 三、常见错误 & 调试技巧(小白救急版)

错误现象 最可能的原因 解决办法 幽默提醒
FileNotFoundError: [Errno 2] No such file or directory: 'resnet.onnx' 模型文件路径不对 确认模型文件在 onnx 文件夹下,或使用绝对路径 'D:/jupyter_notebook/onnx/resnet.onnx' Python 找不到模型,就像你喊“小明”但他不在教室 😅
onnxruntime.capi.onnxruntime_pybind11_state.InvalidArgument 输入数据的形状与模型要求不符 打印 session.get_inputs()[0].shape 查看期望形状,然后调整预处理 你给模型喂了 224x224 的图片,但它要 256x256 – 尺寸对不上
Image.open 报错 UnidentifiedImageError 图片文件损坏或不是图片格式 检查文件是否真的是图片,用 cv2.imread 试试 你把一个文本文件假装成图片,模型不傻
cv2.imread 返回 None 图片路径错误或文件不存在 打印 img_path 确认路径正确 OpenCV 没找到图片,默默返回 None,不报错 – 最坑
np.expand_dims 后形状不对 维度添加顺序或次数错误 打印 image_array.shape 检查 给矩阵套了太多层括号,模型都懵了
session.run 报错 Expected input name 'input' missing 输入字典的 key 与模型输入名不匹配 session.get_inputs()[0].name 获取正确名称 你喊“小王”,但模型输入口叫“小李”
输出概率全是 NaN softmax 前数值太大或太小 检查输入数据是否归一化(除以 255,减均值等) 数据没归一化,模型直接“爆炸”

调试三板斧

  1. 打印形状print(image_array.shape) – 确认尺寸和维度正确。

  2. 打印模型输入信息print(session.get_inputs()[0]) – 看期望的 shape 和 dtype。

  3. 打印输出值范围print(output.min(), output.max()) – 检查是否有异常值。


🎉 结语

恭喜你!你已经掌握了 ONNX 模型推理的完整流程:加载模型 → 读取图片 → 预处理 → 推理 → 后处理 → 输出结果。 这个流程就像用微波炉热饭:打开微波炉门(加载模型)→ 把饭放进去(输入数据)→ 设置时间(预处理)→ 按开始(推理)→ 叮!拿出来(输出结果)。

通关咒语

加载模型用 InferenceSession, 图片预处理要 resize 和归一化, 添加 batch 维度别忘啦, session.run 喂数据, softmax 或 argmax 把结果拿! 🧙‍♂️

祝你顺利通过人工智能训练师考试! 🚀