1. 基于TensorFlow Lite的图像分类器部署
任务目标
在树莓派(Raspberry Pi 4B/5,64位系统)上部署TensorFlow Lite运行时,加载预训练的MobileNetV2图像分类模型,通过摄像头或静态图片输入,实时输出Top-5类别名称及置信度分数。
环境与依赖
- 硬件:树莓派4B/5(建议2GB+内存),USB摄像头或静态图片
- 系统:Raspberry Pi OS (64-bit) Bookworm 或更新版本
- Python:3.9+
- 安装依赖:
pip install tflite-runtime numpy pillow - 模型文件:从官方链接下载,解压得到
mobilenet_v2_1.0_224_quantized.tflite(约3.5MB) - 标签文件:同一压缩包内的
labels_mobilenet_v2.txt(含1001个类别,索引0为"background")
完整实现代码
将以下代码保存为 classifier.py。代码支持两种输入模式:--image 处理单张图片,--camera 实时摄像头推理(按Ctrl+C退出)。
import argparse
import time
import numpy as np
from PIL import Image
import tflite_runtime.interpreter as tflite
# 模型与标签路径
MODEL_PATH = "mobilenet_v2_1.0_224_quantized.tflite"
LABEL_PATH = "labels_mobilenet_v2.txt"
def load_labels(path):
with open(path, "r") as f:
return [line.strip() for line in f.readlines()]
def load_model(model_path):
interpreter = tflite.Interpreter(model_path=model_path)
interpreter.allocate_tensors()
return interpreter
def preprocess_image(image, input_size):
"""将PIL图像缩放到模型输入尺寸并转为uint8数组"""
image = image.resize((input_size, input_size), Image.Resampling.LANCZOS)
# 量化模型输入为uint8,范围[0,255]
return np.expand_dims(np.array(image, dtype=np.uint8), axis=0)
def classify_image(interpreter, image_array):
"""执行推理并返回Top-5 (索引, 标签, 置信度)"""
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
interpreter.set_tensor(input_details[0]["index"], image_array)
interpreter.invoke()
output = interpreter.get_tensor(output_details[0]["index"])[0]
# 量化模型输出为uint8,需除以255得到0~1置信度
scores = output.astype(np.float32) / 255.0
top5_idx = np.argsort(scores)[::-1][:5]
return [(idx, labels[idx], float(scores[idx])) for idx in top5_idx]
def print_results(results, inference_ms):
print(f"\n推理耗时: {inference_ms:.1f} ms")
print("Top-5 预测结果:")
for rank, (idx, label, score) in enumerate(results, 1):
print(f" {rank}. [{idx}] {label}: {score:.4f}")
def run_on_image(interpreter, image_path):
image = Image.open(image_path).convert("RGB")
input_size = interpreter.get_input_details()[0]["shape"][1]
input_array = preprocess_image(image, input_size)
start = time.perf_counter()
results = classify_image(interpreter, input_array)
elapsed_ms = (time.perf_counter() - start) * 1000
print_results(results, elapsed_ms)
def run_on_camera(interpreter):
try:
from picamera2 import Picamera2
except ImportError:
print("需要安装 picamera2: sudo apt install python3-picamera2")
return
picam2 = Picamera2()
config = picam2.create_preview_configuration(
main={"size": (640, 480)}, format="RGB888")
picam2.configure(config)
picam2.start()
input_size = interpreter.get_input_details()[0]["shape"][1]
print("摄像头推理中... 按 Ctrl+C 退出")
try:
while True:
frame = picam2.capture_array()
image = Image.fromarray(frame).convert("RGB")
input_array = preprocess_image(image, input_size)
start = time.perf_counter()
results = classify_image(interpreter, input_array)
elapsed_ms = (time.perf_counter() - start) * 1000
# 清屏并输出当前帧结果
print("\033[2J\033[H", end="")
print(f"FPS: {1000/elapsed_ms:.1f}")
print_results(results, elapsed_ms)
time.sleep(0.05)
except KeyboardInterrupt:
print("\n已退出")
finally:
picam2.stop()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="树莓派TFLite图像分类器")
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--image", type=str, help="静态图片路径")
group.add_argument("--camera", action="store_true", help="使用摄像头实时推理")
args = parser.parse_args()
labels = load_labels(LABEL_PATH)
interpreter = load_model(MODEL_PATH)
print(f"模型加载完成,输入尺寸: {interpreter.get_input_details()[0]['shape']}")
if args.image:
run_on_image(interpreter, args.image)
elif args.camera:
run_on_camera(interpreter)
运行与验证
- 下载模型与标签(与代码同目录):
wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/mobilenet_v2_1.0_224_quantized.tgz && tar -xzf mobilenet_v2_1.0_224_quantized.tgz - 静态图片测试:
python3 classifier.py --image test.jpg
预期输出:打印5行结果,每行包含索引、标签和0~1之间的置信度,且所有置信度之和接近1(因softmax归一化)。例如对一张狗的照片,Top-1应为"golden retriever"或类似犬种。 - 摄像头实时测试:
python3 classifier.py --camera
预期输出:终端每秒刷新约10~20次,每次显示当前画面的Top-5结果和推理耗时。将物体移入画面,观察类别标签随之变化。
通过判定标准
- 静态图片模式:程序无报错退出,输出的Top-5标签与图片内容明显相关(如风景图出现"seashore"、"alp"等),置信度数值在0~1之间且Top-1置信度通常大于0.3。
- 摄像头模式:画面刷新率不低于5 FPS,移动物体时Top-1标签能正确跟随变化(如举起手机时出现"cellular telephone")。
- 推理耗时:树莓派4B上单次推理约80~150ms,5上约40~80ms(量化模型)。若耗时超过500ms,检查是否启用了CPU频率调节或系统负载过高。
常见问题
- 模型加载失败:确认tflite文件与代码在同一目录,且路径拼写正确。
- 摄像头无法打开:执行
sudo apt install python3-picamera2,并确认摄像头已通过raspi-config启用。 - 输出全为0或全为1:检查输入图像是否成功resize到224×224,且未做错误归一化(uint8输入不应除以255)。