简介 MobileNetV2 是由谷歌团队于 2018 年提出的一种轻量级卷积神经网络模型,是 MobileNetV1 的改进版本,旨在在保持准确性的前提下,极大地减少模型的参数数量和计算复杂度,从而适用于移动设备和嵌入式系统等资源受限的场景。
为什么使用MobileNetV2模型?
轻量级模型,运行速度快
在ImageNet数据集上预训练,识别准确度高
适合移动设备和普通电脑使用
目标 使用 python 和深度学习框架,利用 MobileNetV2 模型,完成猫图像的识别;最后完成网页端部署。
实现 环境配置 推荐虚拟环境
1 2 virtualenv venv .\venv\Scripts\activate
创建 requirements.txt, pip install -r requirements.txt 安装相关依赖
1 2 3 4 tensorflow>=2.8.0 opencv-python>=4.5.5 numpy>=1.21.0 pillow>=8.3.0
主程序编写 调包 1 2 3 4 5 import tensorflow as tfimport cv2import numpy as npfrom PIL import Imageimport os
tensorflow: 用于加载和使用预训练模型
cv2: 用于图像处理
numpy: 用于数组操作
PIL: 用于图像加载和预处理
创建加载模型函数 1 2 3 4 5 6 7 8 9 10 11 12 def load_model (): """ 加载预训练的MobileNetV2模型 Returns: model: 加载好的MobileNetV2模型 """ print ("开始加载模型..." ) model = tf.keras.applications.MobileNetV2(weights='imagenet' ) return model
创建图像预处理函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 def preprocess_image (image_path ): """ 预处理图片,使其符合模型输入要求 Args: image_path: 图片文件路径 Returns: processed_image: 预处理后的图片数组,形状为(1, 224, 224, 3) """ print ("开始预处理图片..." ) img = Image.open (image_path) print ("图片打开成功" ) img = img.resize((224 , 224 )) print ("图片调整大小完成" ) img_array = np.array(img) print ("转换为numpy数组完成" ) img_array = tf.keras.applications.mobilenet_v2.preprocess_input(img_array) print ("预处理完成" ) return np.expand_dims(img_array, axis=0 )
创建猫检测函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 def detect_cat (image_path, model, confidence_threshold=0.5 ): """ 检测图片中是否有猫 Args: image_path: 图片文件路径 model: 预训练的MobileNetV2模型 confidence_threshold: 置信度阈值,默认0.5 Returns: tuple: (是否检测到猫, 检测结果描述) """ print (f"开始检测 {image_path} " ) processed_image = preprocess_image(image_path) predictions = model.predict(processed_image) decoded_predictions = tf.keras.applications.mobilenet_v2.decode_predictions(predictions, top=5 )[0 ] print ("解码预测结果完成\n\n" ) cat_labels = ['tabby' , 'tiger_cat' , 'Persian_cat' , 'Siamese_cat' , 'Egyptian_cat' ] for _, label, prob in decoded_predictions: if any (cat in label for cat in cat_labels) and prob >= confidence_threshold: return True , f"检测到猫 ({label} , 置信度: {prob:.2 f} ) \n\n" return False , "未检测到猫\n\n"
实现主函数 在实现主函数前,我创建了两个函数来分别处理单个文件和多个文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 def detect_file (model, confidence=0.5 ): image_path = input ("请输入图片路径:" ) print ("\n\n" ) try : is_cat, result = detect_cat(image_path, model) print (result) except Exception as e: print (f"错误: {str (e)} " ) def detect_folder (model, confidence=0.5 ): folder_path = input ("请输入测试文件夹路径: " ) print ("\n\n" ) all_items = os.listdir(folder_path) files = [folder_path+"\\" + f for f in all_items if os.path.isfile(os.path.join(folder_path, f))] for image_path in files: try : is_cat, result = detect_cat(image_path, model) print (result) except Exception as e: print (f"发生错误: {str (e)} " ) def set_confidence (): try : confidence = float (input ("请输入置信度阈值(0-1之间,默认0.5): " ) or 0.5 ) if confidence < 0 or confidence > 1 : print ("置信度必须在0-1之间,使用默认值0.5" ) confidence = 0.5 except ValueError: print ("输入无效,使用默认值0.5" ) confidence = 0.5 return confidence
注:置信度阈值决定了模型预测结果的可接受最低置信水平,即判断模型是否可靠。
串起来上面的函数,实现主函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def main (): """ 主函数,程序的入口点 """ try : model = load_model() print ("模型加载完成" ) except Exception as e: print ("模型加载失败\n" ,e) confidence = set_confidence() detect_folder(model, confidence)
测试 先拿一张猫猫的图片来测试
==》
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 开始加载模型... 2025-04-12 16:03:42.296507: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations. To enable the following instructions: SSE3 SSE4.1 SSE4.2 AVX AVX2 AVX512F AVX512_VNNI AVX512_BF16 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags. 模型加载完成 请输入置信度阈值(0-1之间,默认0.5): 请输入图片路径:test\cat2.png 开始检测 test\cat2.png 开始预处理图片... 图片打开成功 图片调整大小完成 转换为numpy数组完成 预处理完成 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 448ms/step 解码预测结果完成 检测到猫 (Egyptian_cat, 置信度: 0.74)
虽然检测出了猫,但是类别上非常错。
再检测一下人。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 模型加载完成 请输入置信度阈值(0 -1 之间,默认0.5 ): 请输入图片路径:test\human.png 开始检测 test\human.png 开始预处理图片... 图片打开成功 图片调整大小完成 转换为numpy数组完成 预处理完成 1 /1 ━━━━━━━━━━━━━━━━━━━━ 0s 436ms/step解码预测结果完成 未检测到猫
可以看出他基本特征还是能够提取的,再测试一组数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 模型加载完成 请输入置信度阈值(0-1之间,默认0.5): 0.3 请输入测试文件夹路径: test 开始检测 test\cat1.png 开始预处理图片... 图片打开成功 图片调整大小完成 转换为numpy数组完成 预处理完成 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 447ms/step 解码预测结果完成 未检测到猫 开始检测 test\cat2.png 开始预处理图片... 图片打开成功 图片调整大小完成 转换为numpy数组完成 预处理完成 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 31ms/step 解码预测结果完成 检测到猫 (Egyptian_cat, 置信度: 0.74) 开始检测 test\cat3.png 开始预处理图片... 图片打开成功 图片调整大小完成 转换为numpy数组完成 预处理完成 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step 解码预测结果完成 未检测到猫 开始检测 test\cat4.png 开始预处理图片... 图片打开成功 图片调整大小完成 转换为numpy数组完成 预处理完成 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 35ms/step 解码预测结果完成 检测到猫 (tabby, 置信度: 0.58) 开始检测 test\cat5.png 开始预处理图片... 图片打开成功 图片调整大小完成 转换为numpy数组完成 预处理完成 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step 解码预测结果完成 检测到猫 (Egyptian_cat, 置信度: 0.33) 开始检测 test\human1.png 开始预处理图片... 图片打开成功 图片调整大小完成 转换为numpy数组完成 预处理完成 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step 解码预测结果完成 未检测到猫 开始检测 test\human2.png 开始预处理图片... 图片打开成功 图片调整大小完成 转换为numpy数组完成 预处理完成 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 34ms/step 解码预测结果完成 未检测到猫 开始检测 test\nono.png 开始预处理图片... 图片打开成功 图片调整大小完成 转换为numpy数组完成 预处理完成 1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 33ms/step 解码预测结果完成 未检测到猫
预测效果,其实很差,但可以调整置信度。
微调和优化 概念介绍
模型微调(Fine-tuning):
模型优化:
实施:
数据准备
模型微调
这部分暂时不会,先留着。
网页开发 测试
用 cat2.png
识别效果不好,只能调低置信度,测试 cat5.png
只能先这样了。
最后简单美化一下前端。
主要代码如下
cat_detector.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 """ 猫识别程序 使用预训练的 模型来识别图片中是否包含猫 """ import tensorflow as tf import cv2 import numpy as np from PIL import Image import osdef load_model (): """ 加载预训练的MobileNetV2模型 Returns: model: 加载好的MobileNetV2模型 """ print ("开始加载模型..." ) model = tf.keras.applications.MobileNetV2(weights='imagenet' ) return model def preprocess_image (image_path ): """ 预处理图片,使其符合模型输入要求 Args: image_path: 图片文件路径 Returns: processed_image: 预处理后的图片数组,形状为(1, 224, 224, 3) """ print ("开始预处理图片..." ) img = Image.open (image_path) print ("图片打开成功" ) img = img.resize((224 , 224 )) print ("图片调整大小完成" ) img_array = np.array(img) print ("转换为numpy数组完成" ) img_array = tf.keras.applications.mobilenet_v2.preprocess_input(img_array) print ("预处理完成" ) return np.expand_dims(img_array, axis=0 ) def detect_cat (image, confidence_threshold=0.3 ): model = tf.keras.applications.MobileNetV2(weights='imagenet' ) processed_image = preprocess_image(image) predictions = model.predict(processed_image) decoded_predictions = tf.keras.applications.mobilenet_v2.decode_predictions(predictions, top=5 )[0 ] cat_labels = ['tabby' , 'tiger_cat' , 'Persian_cat' , 'Siamese_cat' , 'Egyptian_cat' ] for _, label, prob in decoded_predictions: if any (cat in label for cat in cat_labels) and prob >= confidence_threshold: return f"检测到猫 ({label} , 置信度: {prob:.2 f} )" return "未检测到猫"
app.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from flask import Flask, request, render_templateimport cat_detectorapp = Flask(__name__) @app.route('/' , methods=['GET' , 'POST' ] ) def upload_file (): if request.method == "POST" : file = request.files['file' ] if file: result = cat_detector.detect_cat(file) return render_template('result.html' , result=result) return render_template('upload.html' ) if __name__ == "__main__" : app.run(debug=True )
前端就不说了。
最后修改一下关键信息,部署在 sealos 上即可。
后记 使用预训练其实比较简单,调库,然后塞测试数据就行了。后续可能需要做进一步的数据收集、模型优化和训练。后面的后面或许可以根据别人上传的图片来进行动态训练。
菜啊,有待提升。