Battle of the CNNs: ResNet vs. MobileNet vs. EfficientNet for Fruit Disease Detection

Published: (January 14, 2026 at 02:48 AM EST)
4 min read
Source: Dev.to

Source: Dev.to

Introduction

I’ve always been fascinated by how deep learning can solve real‑world problems, and fruit disease detection seemed like the perfect challenge—​not too simple, not impossibly complex, and genuinely useful for farmers battling crop losses.

I built FruitScan‑AI and tested three different neural‑network architectures to see which one works best. Spoiler: each has its strengths, and the “best” model totally depends on what you’re building.

Why Even Bother With Fruit Disease Detection?

Farmers lose 20 %–40 % of their crops each year to diseases and pests. The traditional way of checking—​walking through fields, manually inspecting every plant, hoping you catch problems early—​is slow, inconsistent, and requires expertise that not everyone has.

What if we could just snap a photo and get an instant diagnosis? That’s where FruitScan‑AI comes in.

What I Built

FruitScan‑AI is a deep‑learning system that looks at fruit images and tells you two things:

  1. What kind of fruit it is
  2. Whether it’s healthy or diseased

I didn’t stop at a single model; I built three versions using EfficientNet, MobileNetV2, and ResNet50 to compare them side‑by‑side.

The Dataset

  • Images of 15+ fruit types (apples, bananas, grapes, mangoes, tomatoes, peppers, …)
  • Each class includes both healthy and diseased specimens (bacterial spots, fungal infections, rot, etc.)
  • High‑resolution images that capture subtle details needed for accurate classification

The Three Architectures (And Why I Picked Them)

EfficientNet – The Balanced One

EfficientNet scales depth, width, and resolution together via compound scaling, delivering great accuracy without becoming a computational monster. I chose it for its efficiency and strong performance on image‑classification tasks.

MobileNetV2 – The Lightweight Champion

Designed for mobile devices, MobileNetV2 uses depthwise separable convolutions to do more with less. Perfect for deployment on a phone or a Raspberry Pi in the middle of a farm. If I were building a field app for farmers, this would be my go‑to.

ResNet50 – The Heavyweight

ResNet50 introduced skip connections, allowing very deep networks to train without vanishing gradients. It’s deeper, more powerful, and provides a solid baseline for comparison.

How It Actually Works

All three models use transfer learning—they’re pretrained on ImageNet, so they already know edges, textures, and shapes.

# 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')
])

Why Transfer Learning?

  1. Training is faster
  2. Less data is required
  3. Better results

The Training Pipeline

  1. Resize images to each model’s expected input (usually 224×224).
  2. Normalize using ImageNet statistics.
  3. Data augmentation (flips, rotations, brightness tweaks) to prevent memorization.
  4. Batch training to keep the GPU happy.

I tracked the usual suspects: accuracy, precision, recall, F1‑score, and confusion matrices to see where each model struggled.

Getting Started (If You Want to Try This)

What You Need

pip install tensorflow keras numpy pandas matplotlib scikit-learn

Grab the Code

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

Repository Layout

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

Running a Notebook

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

Making Predictions

# 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}%")

Simple Flask Wrapper (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)

Closing Thoughts

Each architecture shines in different scenarios:

  • EfficientNet – best overall accuracy‑to‑efficiency ratio.
  • MobileNetV2 – ideal for on‑device inference where resources are limited.
  • ResNet50 – provides a strong baseline and excels when you can afford the compute.

Feel free to explore, tweak, and adapt the code for your own fruit‑disease detection projects!

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))
    })

So… Which Model Won?

Honestly? It depends on what you’re optimizing for.

ModelAccuracySpeed (per image)Size / Use‑case
EfficientNet92 % – 95 %30 ms – 50 msGood all‑rounder
MobileNetV288 % – 91 %10 ms – 20 msFast & tiny – perfect for mobile apps
ResNet5090 % – 93 %50 ms – 80 msSlower & larger – great for research or when accuracy is everything

Try It Out!

If this sounds interesting:

Star the repo

Back to Blog

Related posts

Read more »