适用练习: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,减均值等) | 数据没归一化,模型直接“爆炸” |
调试三板斧:
-
打印形状:
print(image_array.shape)– 确认尺寸和维度正确。 -
打印模型输入信息:
print(session.get_inputs()[0])– 看期望的 shape 和 dtype。 -
打印输出值范围:
print(output.min(), output.max())– 检查是否有异常值。
🎉 结语
恭喜你!你已经掌握了 ONNX 模型推理的完整流程:加载模型 → 读取图片 → 预处理 → 推理 → 后处理 → 输出结果。 这个流程就像用微波炉热饭:打开微波炉门(加载模型)→ 把饭放进去(输入数据)→ 设置时间(预处理)→ 按开始(推理)→ 叮!拿出来(输出结果)。
通关咒语:
加载模型用 InferenceSession, 图片预处理要 resize 和归一化, 添加 batch 维度别忘啦, session.run 喂数据, softmax 或 argmax 把结果拿! 🧙♂️
祝你顺利通过人工智能训练师考试! 🚀