CNN之战:ResNet vs. MobileNet vs. EfficientNet 用于水果疾病检测

发布: (2026年1月14日 GMT+8 15:48)
7 min read
原文: Dev.to

Source: Dev.to

介绍

我一直对深度学习如何解决现实世界的问题感到着迷,而水果病害检测似乎是一个完美的挑战——既不过于简单,也不至于复杂到不可实现,并且对与作物损失作斗争的农民真正有用。

我构建了 FruitScan‑AI 并测试了三种不同的神经网络架构,以找出哪一种表现最佳。剧透一下:每种模型都有其优势,而“最佳”模型完全取决于你的具体需求。

为什么要进行水果病害检测?

农民每年因病虫害损失 20 %–40 % 的作物。传统的检查方式——在田间走动,手动检查每株植物,期望及早发现问题——既慢又不稳定,而且需要并非所有人都具备的专业知识。

如果我们只需拍一张照片就能获得即时诊断会怎样?这正是 FruitScan‑AI 的用武之地。

我构建的内容

FruitScan‑AI 是一个深度学习系统,能够查看水果图像并告诉你两件事:

  1. 它是什么水果
  2. 它是健康的还是患病的

我没有只停留在单一模型;我使用 EfficientNetMobileNetV2ResNet50 构建了三个版本,以便并排比较它们。

数据集

  • 包含 15+ 种水果的图像(苹果、香蕉、葡萄、芒果、西红柿、辣椒,…)
  • 每个类别均包括 健康病害 标本(细菌斑点、真菌感染、腐烂等)
  • 高分辨率图像,捕捉用于精确分类的细微细节

三种架构(以及我为何选择它们)

EfficientNet – 平衡之选

EfficientNet 通过 compound scaling 同时缩放深度、宽度和分辨率,能够在不成为计算怪兽的情况下提供出色的准确率。我选择它是因为它的高效性以及在图像分类任务中的强大表现。

MobileNetV2 – 轻量冠军

MobileNetV2 为移动设备设计,使用 depthwise separable convolutions 以更少的资源实现更多功能。非常适合在手机或农场中的 Raspberry Pi 上部署。如果我要为农民构建现场应用,这将是我的首选。

ResNet50 – 重量级选手

ResNet50 引入了 skip connections,使得非常深的网络在没有梯度消失的情况下也能训练。它更深、更强大,并提供了一个可靠的基准用于比较。

实际工作原理

所有三个模型都使用 transfer learning——它们在 ImageNet 上预训练,因此已经掌握了边缘、纹理和形状。

# Freeze the pretrained layers at first
base_model = EfficientNetB0(weights='imagenet', include_top=False)
base_model.trainable = False

# Add custom classification layers on top
model = Sequential([
    base_model,
    GlobalAveragePooling2D(),
    Dense(256, activation='relu'),
    Dropout(0.5),
    Dense(num_classes, activation='softmax')
])

为什么使用迁移学习?

  1. 训练更快
  2. 所需数据更少
  3. 结果更好

训练流程

  1. Resize 将图像调整为每个模型期望的输入尺寸(通常为 224×224)。
  2. Normalize 使用 ImageNet 统计数据。
  3. Data augmentation(翻转、旋转、亮度调整)以防止记忆化。
  4. Batch training 以保持 GPU 高效运行。

我跟踪了常见指标:accuracy, precision, recall, F1‑score,confusion matrices,以查看每个模型的薄弱之处。

入门指南(如果你想尝试)

需求

pip install tensorflow keras numpy pandas matplotlib scikit-learn

获取代码

git clone https://github.com/sisodiajatin/FruitScan-AI.git
cd FruitScan-AI

仓库结构

FruitScan-AI/
├── EfficientNet/   # EfficientNet notebooks
├── MobileNetV2/    # MobileNetV2 experiments
└── ResNet50/      # ResNet50 implementation

运行 Notebook

cd EfficientNet   # or whichever model you want
jupyter notebook
# Open the training notebook and run it cell by cell

进行预测

# Load your model
model = tf.keras.models.load_model('fruit_disease_model.h5')

# Prepare the image
img = tf.keras.utils.load_img('suspicious_apple.jpg', target_size=(224, 224))
img_array = tf.keras.utils.img_to_array(img)
img_array = np.expand_dims(img_array, axis=0)
img_array = tf.keras.applications.efficientnet.preprocess_input(img_array)

# Get prediction
predictions = model.predict(img_array)
class_idx = np.argmax(predictions[0])

print(f"This looks like: {class_labels[class_idx]}")
print(f"Confidence: {predictions[0][class_idx] * 100:.2f}%")

简单的 Flask 包装器(API)

from flask import Flask, request, jsonify
import tensorflow as tf

app = Flask(__name__)
model = tf.keras.models.load_model('best_model.h5')

@app.route('/predict', methods=['POST'])
def predict():
    # Expect an image file under the key 'file'
    file = request.files['file']
    img = tf.keras.utils.load_img(file, target_size=(224, 224))
    img_array = tf.keras.utils.img_to_array(img)
    img_array = np.expand_dims(img_array, axis=0)
    img_array = tf.keras.applications.efficientnet.preprocess_input(img_array)

    preds = model.predict(img_array)
    class_idx = np.argmax(preds[0])
    confidence = preds[0][class_idx] * 100

    return jsonify({
        'class': class_labels[class_idx],
        'confidence': f'{confidence:.2f}%'
    })

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

结束语

每种架构在不同场景下各有优势:

  • EfficientNet – 最佳的整体准确率与效率比。
  • MobileNetV2 – 在资源受限的设备上进行推理的理想选择。
  • ResNet50 – 提供强大的基线,并在计算资源充足时表现出色。

欢迎随意探索、微调并将代码应用于您自己的水果病害检测项目!

def predict():
    file = request.files['image']
    img = preprocess_image(file)
    prediction = model.predict(img)

    return jsonify({
        'fruit': get_fruit_name(prediction),
        'status': 'healthy' if is_healthy(prediction) else 'diseased',
        'confidence': float(np.max(prediction))
    })

那么…哪个模型赢了?

老实说? 这取决于你的优化目标。

ModelAccuracySpeed (per image)Size / Use‑case
EfficientNet92 % – 95 %30 ms – 50 ms表现均衡
MobileNetV288 % – 91 %10 ms – 20 ms快速且体积小——非常适合移动应用
ResNet5090 % – 93 %50 ms – 80 ms速度较慢且体积更大——适合研究或对精度要求极高的场景

试一试!

如果这听起来很有趣:

给仓库加星

Back to Blog

相关文章

阅读更多 »

构建生产就绪的交通违规检测系统(计算机视觉)

交通监控与违规检测是一个经典的计算机视觉问题,看似简单,却在真实场景中迅速变得复杂。该任务涉及从摄像头获取的连续视频流中检测、跟踪和分析车辆及行人的行为,以识别诸如闯红灯、超速、违章变道、占用应急车道以及非法停车等违规行为。实现高精度的违规检测需要克服多种挑战,包括光照变化、天气影响、遮挡、摄像头视角差异、车辆外观多样性以及实时处理的计算约束。 本文综述了交通监控与违规检测的最新研究进展,重点关注以下几个方面: 1. **目标检测与分割** - 基于深度学习的两阶段(如 Faster R-CNN、Mask R-CNN)和单阶段(如 YOLOv5、SSD、EfficientDet)检测框架在道路场景中的适配与改进。 - 语义分割与实例分割模型(如 DeepLabv3+、Panoptic FPN)用于提取车道线、交通标志和路面区域,以辅助行为理解。 2. **多目标跟踪(MOT)** - 传统基于卡尔曼滤波和匈牙利算法的跟踪方法与基于深度特征关联的端到端跟踪网络(如 DeepSORT、ByteTrack、TrackFormer)的比较。 - 在拥堵或遮挡严重的交叉口场景中,引入图神经网络(GNN)或注意力机制提升跨帧身份保持的鲁棒性。 3. **行为识别与违规判定** - 基于时空特征的行为分类模型,包括 3D CNN(如 I3D、SlowFast)和时序卷积网络(TCN),用于捕捉车辆加速、减速和转向等动态模式。 - 轨迹分析方法:利用贝塞尔曲线拟合、多项式回归或基于 Kalman/Particle Filter 的轨迹预测,对比实际轨迹与交通规则(如红灯时段、限速区间)进行违规判定。 - 事件驱动的规则引擎:将检测到的视觉事件映射到预定义的违规规则库,支持灵活的规则更新和本地化法规适配。 4. **多摄像头协同与跨视角融合** - 基于同质或异质摄像头网络的跨视角目标重识别(ReID)技术,利用全局特征和局部关键点对车辆进行跨摄像头身份匹配。 - 空间几何校准(如基于标定板或道路标线的单应性矩阵)与时间同步机制,构建统一的全局坐标系,实现跨摄像头的连续轨迹跟踪。 5. **实时推理与系统部署** - 模型压缩与加速:剪枝、量化、知识蒸馏以及 TensorRT、ONNX Runtime 等推理引擎在嵌入式 GPU/TPU 上的部署实践。 - 边缘计算与云端协同:在摄像头端完成初步检测与跟踪,复杂违规判定和历史数据存储迁移至云端,以平衡延迟和算力需求。 6. **数据集与评估指标** - 公共基准数据集:UA‑Detrac、MOT17、KITTI‑Tracking、CityFlow、D2‑CityScapes、BDD100K‑Traffic 等,涵盖不同城市、天气和摄像头布局。 - 评价指标:mAP、Recall、IDF1、MOTA、MOTP 用于检测与跟踪性能评估;违规检测则采用 Precision、Recall、F1‑Score 以及延迟(Latency)等业务相关指标。 7. **挑战与未来方向** - **鲁棒性**:提升模型在极端天气(雨、雪、雾)和夜间低光环境下的检测与跟踪能力。 - **可解释性**:构建可视化的违规判定路径,帮助监管人员理解模型决策过程。 - **跨域适应**:利用无监督域适应或自监督学习降低不同城市、摄像头配置之间的性能落差。 - **法规融合**:将本地交通法规与模型输出进行动态映射,实现“一键”规则更新和多地区部署。 - **隐私保护**:在满足 GDPR 等数据保护法规的前提下,探索加密推理和匿名化特征提取技术。 综上所述,交通监控与违规检测正从单纯的目标检测向融合多模态感知、跨摄像头协同、实时推理和法规智能化的综合系统演进。随着更高效的深度模型、强大的边缘计算平台以及更丰富的标注数据的出现,未来的智能交通系统有望实现更高的安全性、效率和可持续性,为智慧城市建设提供坚实的技术支撑。