Skip to content

Repository files navigation

Apple Counting via a Regression-Based YOLOv8 with an Improved MobileViT-v3 Backbone

This project focuses on single-image apple counting in real orchard environments using a regression-based deep learning approach.
Instead of object detection, the model directly predicts the total apple count from an input image.


Overview

  • Task: Apple counting from RGB orchard images
  • Approach: Regression-based YOLOv8
  • Backbone: Residual-enhanced MobileViT-v3
  • Output: A single scalar value (apple count)

The method is designed to handle:

  • Occlusion by leaves
  • Complex backgrounds
  • Variable lighting conditions
  • Different apple colours and densities

Unlike detection-based approaches, this method does not require bounding-box annotations.
It directly predicts the total apple count from a single image using an end-to-end regression framework.


Method

  • YOLOv8 backbone with detection head removed
  • Standard CSP blocks replaced by an improved MobileViT-v3
  • Added MV2 residual blocks for better local feature preservation
  • Transformer layers capture global context
  • Final fully connected regression head

Architecture Overview

Model Architecture

Only lightweight preprocessing is used:

  • Gaussian blur
  • Image resizing

Traditional handcrafted features (e.g. LBP, colour segmentation) were tested but excluded due to performance degradation.

📁 Dataset

Two public apple-counting datasets are merged and re-split to construct a unified regression dataset:

  • ACFR Apple Dataset
  • MinneApple Dataset

Data Split

  • Training set: 80%
  • Validation set: 10%
  • Testing set: 10%

Total images: 65,715

Annotation Format

The task is formulated as image-level regression.
Annotations are stored in a .txt file, where each line corresponds to one image and its ground-truth apple count:

images_00000.png,0
images_00001.png,3
images_00002.png,15
images_00003.png,7

Each entry follows the format:

<image_filename>,<apple_count>

This annotation scheme does not require bounding-box or instance-level labels, enabling efficient end-to-end regression training.


Hyperparameters and training settings

  • Loss: Mean Squared Error (MSE)
  • Optimizer: Adam
  • Learning rate: 1e-4
  • Epochs: 5 (Google Colab constraint)

Evaluation

RMSE and Within-1 Accuracy

RMSE and Within-1 Accuracy

Performance under Different Preprocessing Strategies

Comparison of Different Image Processing Methods


Project Report


Usage Instructions: YOLOv8 with MobileViT-v3

This document describes how to integrate a custom MobileViT-v3 backbone into the Ultralytics YOLOv8 framework, including model configuration and required code modifications.


1. Model YAML Configuration

Create a custom model configuration file, for example:

yolov8_mobilevitv3.yaml

with the following content:

# Ultralytics YOLO 🚀, GPL-3.0 license

# Parameters
nc: 80  # number of classes
depth_multiple: 0.33
width_multiple: 0.50

# YOLOv8 backbone
backbone:
  # [from, repeats, module, args]
  - [-1, 1, Conv, [64, 3, 2]]          # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]]         # 1-P2/4
  - [-1, 3, C2f, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]]         # 3-P3/8
  - [-1, 6, MobileViTBv3, [256]]
  - [-1, 1, Conv, [512, 3, 2]]         # 5-P4/16
  - [-1, 6, MobileViTBv3, [512]]
  - [-1, 1, Conv, [1024, 3, 2]]        # 7-P5/32
  - [-1, 3, C2f, [1024, True]]
  - [-1, 1, SPPF, [1024, 5]]

# YOLOv8 head
head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 6], 1, Concat, [1]]
  - [-1, 3, C2f, [512]]

  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 4], 1, Concat, [1]]
  - [-1, 3, C2f, [256]]

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 12], 1, Concat, [1]]
  - [-1, 3, C2f, [512]]

  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 9], 1, Concat, [1]]
  - [-1, 3, C2f, [1024]]

  - [[15, 18, 21], 1, Detect, [nc]]

2. Add MobileViT-v3 Module

Place your MobileViT-v3 implementation in the Ultralytics codebase:

ultralytics/
└── nn/
    ├── mobilevitv3.py   # contains class MobileViTBv3
    ├── tasks.py
    └── modules/

Ensure that mobilevitv3.py defines:

class MobileViTBv3(nn.Module):
    ...

3. Modify tasks.py

3.1 Import MobileViT-v3

Open:

ultralytics/nn/tasks.py

Add the following import near the top of the file:

from ultralytics.nn.mobilevitv3 import MobileViTBv3

3.2 Register MobileViT-v3 in the Model Parser

In tasks.py, locate the following code:

elif m is nn.BatchNorm2d:
    args = [ch[f]]

Insert the following block immediately above it:

elif m is MobileViTBv3:
    c1, c2 = ch[f], args[0]
    if c2 != nc:  # not a classification head output
        c2 = make_divisible(min(c2, max_channels) * width, 8)
    args = [c1, c2, *args[1:]]
    args.insert(2, n)  # number of repeats
    n = 1

This step is required for correct channel scaling and repeat handling when parsing the custom backbone.


About

No description or website provided.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages