Skip to content

sudipto09/Autonomous-Camera-Trap-for-Insect-Monitoring

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Autonomous Camera Trap for Insect Monitoring

A fully autonomous, low-cost insect monitoring system that runs a complete camera → AI inference → logging → remote-streaming pipeline entirely on-device, on a Raspberry Pi 3 B+ (1 GB RAM, CPU-only). The system detects and classifies insects with a custom-trained YOLOv5n model (33 classes, based on the IP102 benchmark dataset), logs annotated images and a CSV detection record to the local MicroSD card, and serves a live MJPEG video stream over Wi-Fi.

Developed by Sudipto Chakraborty — Master's Programme in Aerospace Informatics, Julius-Maximilians-Universität Würzburg, under the supervision of Prof. Dr. Marco Schmidt (ESSEO Laboratory, JMU Würzburg).


Table of Contents


Project Overview

Primary objective Fully autonomous, low-cost insect monitoring with embedded AI running entirely on-device
Detection model Custom YOLOv5n, 33 insect classes, trained on the IP102 benchmark dataset (500 epochs)
Target hardware Raspberry Pi 3 B+ — 1 GB RAM, CPU-only
Storage Annotated JPEG images + per-class cropped insect images + structured CSV detection log
Remote monitoring Live MJPEG stream via Flask web server (:8080), plus a lightweight /snap fallback
Enclosure Custom 3D-printed PLA enclosure, designed in SolidWorks (hardware/insect_detect.stl)
Effective throughput ~0.3–0.6 fps — sufficient for static-surface monitoring of stationary insects

The full processing pipeline runs locally on the Pi with no cloud or internet dependency once the model weights are deployed.


System Architecture

flowchart LR
    subgraph Capture["Capture / Output"]
        CAM["Camera Module 3\n12 MP, BGR888 640x640"]
    end
    subgraph Pre["Preprocessing"]
        BGR["BGR -> RGB\n(OpenCV)"]
        SHARP["Laplacian Sharpening\n3x3 kernel"]
    end
    subgraph AI["AI Inference"]
        YOLO["YOLOv5n Inference\nPyTorch CPU, conf >= 0.15"]
        FILTER["Two-Stage Filter\nconfidence + bbox area"]
    end
    subgraph Data["Data & Monitoring"]
        STORE["Storage & CSV Log\nMicroSD"]
        DASH["Analytics Dashboard\nmatplotlib"]
        FLASK["Flask Stream\nMJPEG :8080"]
    end

    CAM --> BGR --> SHARP --> YOLO --> FILTER
    FILTER --> STORE --> DASH
    FILTER --> FLASK
Loading

All operations execute locally on the Raspberry Pi 3 B+.

Pipeline stages (per frame)

  1. Image Acquisitioncamera/ captures a 640×640 BGR888 frame via PiCamera2 (primary) or rpicam-jpeg / libcamera-jpeg subprocess (fallback).
  2. BGR → RGB Conversion — OpenCV channel swap; YOLOv5 expects RGB.
  3. Laplacian Sharpening — 3×3 kernel via cv2.filter2D(), enhances edge contrast for close-up macro images.
  4. YOLOv5n Inferencetorch.no_grad() forward pass, 33 classes, conf_thres = 0.15, loaded fully offline via PyTorch Hub local source mode.
  5. Two-Stage Filter — Stage 1: confidence ≥ 0.15. Stage 2: bounding box area ≥ 100 px².
  6. Annotation & Storage — annotated JPEG + per-class cropped images saved to the MicroSD card; CSV log flushed every 20 events.
  7. Flask Live Stream — MJPEG on /, single-frame fallback on /snap.

Output directory layout (created at runtime)

detections/
  <YYYY-MM-DD>/
    <HH-MM-SS>/                 # one directory per session
      annotated/                # full frames with bounding boxes
        frame_7.jpg
        frame_11.jpg
        ...
      cropped/                  # per-class insect crops (no boxes)
        Parasa indetermina/
          7.jpg
        Torpedo bug/
          7.jpg
      detections.csv            # frame, timestamp, class, confidence, x1,y1,x2,y2

Repository Structure

insect_detect/
├── main.py                     # Entry point — orchestrates the full pipeline
├── requirements.txt
├── LICENSE
├── .gitignore
├── camera/
│   ├── __init__.py
│   ├── base.py                 # CameraBase abstract interface
│   ├── factory.py              # open_camera() — backend selection
│   ├── picamera2_backend.py    # Primary backend (PiCamera2)
│   └── subprocess_backend.py   # Fallback backend (rpicam-jpeg / libcamera-jpeg)
├── config/
│   ├── __init__.py
│   └── settings.py              # ALL tunable parameters live here
├── detection/
│   ├── __init__.py
│   ├── model.py                 # load_model() — PyTorch Hub local source mode
│   ├── preprocessor.py          # BGR->RGB + Laplacian sharpening
│   └── inference.py             # run_inference() — forward pass + filtering
├── storage/
│   ├── __init__.py
│   ├── session.py                # Session — per-run output directory layout
│   └── writer.py                 # DetectionWriter — JPEG + CSV logging
├── stream/
│   ├── __init__.py
│   └── flask_server.py           # MJPEG stream (/) + snapshot (/snap)
├── utils/
│   ├── __init__.py
│   ├── env.py                    # SSH / headless detection
│   └── paths.py                  # Startup path validation
├── scripts/
│   └── plot_detections.py        # Post-session analytics dashboard generator
├── hardware/
│   └── insect_detect.stl         # 3D-printable enclosure (SolidWorks export)
└── docs/
    └── images/                    # Reference photos used in this README

Not included in this repository (too large / environment-specific — see Deployment):

  • The yolov5/ source tree (clone from ultralytics/yolov5)
  • The trained model weights best.pt
  • Runtime output (detections/)

Hardware

Component Specification Notes
Raspberry Pi 3 B+ ARM Cortex-A53 @ 1.4 GHz, 1 GB LPDDR2 RAM Software is compatible with Pi 4/5 as-is
Camera Module 3 Sony IMX708, 12 MP, motorised autofocus, CSI-2 ~15 cm camera-to-tray distance
MicroSD card ≥ 32 GB, high-endurance / dashcam-rated Standard cards degrade under continuous small-file writes
Power supply 5 V / 3 A, short 26 AWG cable Peak draw 7.5 W; under-spec supplies cause CSI camera corruption
Enclosure Custom SolidWorks design, green PLA, 3-part assembly hardware/insect_detect.stl
Enclosure front view Enclosure side view Enclosure interior
Front view — Camera Module 3 mounted centrally, facing down onto the monitoring tray. Side view — two-part body split (main body + removable base cover). Interior — Raspberry Pi 3 B+ on standoffs, CSI ribbon cable routed to the camera mount.

The enclosure is a 3-part parametric assembly: main body, removable base cover (for tool-free access to the Pi and MicroSD card), and the camera mount / monitoring tray. Ventilation slots are cut into the side walls for passive cooling — see Known Hardware Constraints for why this matters.


Getting Started

This section reproduces a working deployment from a blank Raspberry Pi.

1. Operating System Setup

  1. Flash Raspberry Pi OS Lite (64-bit)not the Desktop image — using Raspberry Pi Imager. The headless Lite image saves ~200–300 MB of RAM that the inference pipeline needs.
  2. In the imager's advanced options, enable SSH and configure Wi-Fi.
  3. Boot the Pi and connect via SSH:
    ssh pi@<hostname>.local

2. System Configuration

# Reduce GPU memory split — gives the CPU pipeline more RAM
sudo nano /boot/firmware/config.txt
# add: gpu_mem=16

# Disable Wi-Fi power management (prevents SSH/MJPEG stalls)
sudo iwconfig wlan0 power off

# (Recommended) increase swap as an OOM safety net
sudo nano /etc/dphys-swapfile
# set: CONF_SWAPSIZE=512
sudo dphys-swapfile setup && sudo dphys-swapfile swapon

3. Install Dependencies

sudo apt update && sudo apt upgrade -y
sudo apt install -y python3-pip python3-opencv libopencv-dev python3-picamera2

pip3 install -r requirements.txt --break-system-packages

PyTorch installation on ARM can take 20–60 minutes on a Pi 3 B+.

4. Deploy YOLOv5 and Model Weights

The detection model is loaded via PyTorch Hub local source mode (detection/model.py), which requires a local clone of the YOLOv5 repository plus the trained weights file. Both must sit next to this repository as configured in config/settings.py:

cd /home/<username>/insect_detect
git clone https://github.com/ultralytics/yolov5.git
cd yolov5 && pip3 install -r requirements.txt --break-system-packages

# Copy the trained weights onto the Pi (from your training machine)
scp best.pt pi@<hostname>.local:/home/<username>/insect_detect/yolov5/best.pt

5. Configure the Project

Edit config/settings.py and set HOME_DIR to match your actual install path (default is /home/sudipto/insect_detect):

HOME_DIR = "/home/<username>/insect_detect"

All other paths (YOLOV5_PATH, MODEL_WEIGHTS, BASE_DIR) derive from HOME_DIR automatically.

6. Run

cd /home/<username>/insect_detect
python3 main.py

Expected startup log:

 Path validation passed.
 SSH mode   : True
 GUI preview: False
Session output : /home/<username>/insect_detect/detections/2026-06-15/10-30-00
Loading YOLOv5 model ...
YOLOv5 model loaded  ✓

Camera backend : picamera2
Live stream  -> http://<pi-ip>:8080/
Snapshot     -> http://<pi-ip>:8080/snap
SSH tunnel   -> ssh -L 8080:localhost:8080 pi@<pi-ip>
Detection running - press Ctrl+C to stop

Open http://<pi-ip>:8080/ in a browser on the same network to view the live MJPEG stream. Stop the system with Ctrl+C — this triggers a clean shutdown (camera release + final CSV flush).

Run as a systemd service (unattended deployment)

# /etc/systemd/system/insect-detect.service
[Unit]
Description=Insect Detection Service
After=network.target

[Service]
Type=simple
User=<username>
WorkingDirectory=/home/<username>/insect_detect
ExecStart=/usr/bin/python3 main.py
Restart=on-failure
RestartSec=10
StandardOutput=append:/home/<username>/insect_detect/service.log
StandardError=append:/home/<username>/insect_detect/service.log

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now insect-detect

Configuration Reference

All tunables live in config/settings.py. Do not hardcode parameters elsewhere in the codebase.

Parameter Default Effect
HOME_DIR /home/sudipto/insect_detect Project root — must be updated per deployment
YOLOV5_PATH HOME_DIR/yolov5 Path to the local YOLOv5 clone (must contain hubconf.py)
MODEL_WEIGHTS YOLOV5_PATH/best.pt Trained model weights
IMG_WIDTH / IMG_HEIGHT 640 / 640 Capture resolution — must match training resolution
CONF_THRESHOLD 0.15 Stage-1 detection filter (confidence)
MIN_BOX_AREA 100 Stage-2 detection filter (bounding box area, px²)
INFER_EVERY 1 Run inference on every Nth captured frame
FRAME_DELAY 0.0 Idle sleep (s) per loop — raise to reduce thermal load
CAPTURE_TIMEOUT 12 Timeout (s) for the subprocess camera fallback
JPEG_QUALITY 60 JPEG compression quality for saved images (0–100)
CSV_FLUSH_EVERY 20 Write detections.csv every N detection events
WEB_PORT 8080 Flask stream server port

Tuning guidance

  • Too many false positives (debris detected as insects) → raise CONF_THRESHOLD to 0.25–0.35 and/or raise MIN_BOX_AREA.
  • Missing genuine insects → lower CONF_THRESHOLD (already biased low by design — see Field Validation Results).
  • Thermal throttling during long sessions → raise FRAME_DELAY to 1.0–2.0 s.
  • MicroSD filling too quickly → lower JPEG_QUALITY to 40–50.

Module Documentation

camera/

Defines CameraBase (abstract read() / release() interface) and two implementations: PiCamera2Capture (primary, uses the official picamera2 library) and SubprocessCapture (fallback, shells out to rpicam-jpeg/libcamera-jpeg). factory.open_camera() tries backends in priority order and exits only if both fail.

config/settings.py

Single source of truth for every path and tunable constant. See Configuration Reference.

detection/

  • model.load_model() — loads YOLOv5n fully offline via torch.hub.load(..., source="local"), sets model.conf = CONF_THRESHOLD, and puts the model in eval() mode on CPU.
  • preprocessor.preprocess() — BGR→RGB conversion followed by a 3×3 Laplacian sharpening kernel ([[0,-1,0],[-1,5,-1],[0,-1,0]]).
  • inference.run_inference() — runs the forward pass inside torch.no_grad(), returns a detections DataFrame and the rendered annotated frame, and applies the Stage-2 bounding-box-area filter.

storage/

  • session.Session — creates the detections/<date>/<time>/{annotated,cropped}/ directory tree and detections.csv path for one run.
  • writer.DetectionWriter — saves per-class crops (from the raw, not annotated, frame), saves the annotated full frame, and appends to an in-memory log that is flushed to CSV every CSV_FLUSH_EVERY events and on shutdown.

stream/flask_server.py

Runs Flask on a daemon thread so the inference loop is never blocked. Exposes:

  • / — MJPEG multipart stream of the latest annotated frame.
  • /snap — single JPEG snapshot, useful when the MJPEG stream stalls on unstable Wi-Fi.

If Flask is not installed, stream.start() returns False and the pipeline continues without streaming — it never crashes the main loop.

utils/

  • env.is_ssh() / env.show_preview() — detect headless operation so cv2.imshow() is never called without a display.
  • paths.validate() — pre-flight check for YOLOV5_PATH, hubconf.py, and MODEL_WEIGHTS; exits with a clear diagnostic before any expensive initialization if anything is missing.

main.py

Orchestrates startup (validation → session → model → camera → stream), runs the main capture/inference/save loop, and guarantees clean shutdown (cam.release(), writer.flush()) via a finally block and SIGINT/SIGTERM handlers.


Detection Output and Analytics

Each session produces detections.csv with one row per detected insect:

Column Description
frame Frame counter from session start
timestamp Wall-clock time (YYYY-MM-DD HH:MM:SS)
class Detected species name
confidence Detection confidence (0–1)
x1, y1, x2, y2 Bounding box coordinates (pixels)

Run the analytics script on a desktop machine (requires matplotlib + pandas):

python scripts/plot_detections.py path/to/detections.csv
# -> writes detection_plots.png in the same directory

This produces a four-panel "Insect Detection Summary" dashboard: detections per class, confidence score distribution, detections over time (per minute), and bounding-box-area distribution.


Field Validation Results

Field test conducted 27 April 2026, 08:57:26, with live specimens of Parasa indetermina (moth, family Limacodidae) and Torpedo bug (Siphanta acuta, planthopper) placed on the monitoring tray. The session produced 11 annotated frames.

Detection frame 7 Detection frame 11 Detection frame 14
frame_7.jpg — Torpedo bug at 0.20 / 0.26, Parasa indetermina at 0.57 frame_11.jpg — Parasa indetermina at 0.82, Torpedo bug at 0.29 frame_14.jpg — Peak session confidence: Parasa indetermina at 0.79 / 0.85, Torpedo bug at 0.31

Insect Detection Summary dashboard
Detection Summary dashboard generated with scripts/plot_detections.py from the 2026-04-27 session log.

Metric Value
Inference time (normal) 1.5 – 3.5 s/frame
Inference time (thermally throttled) 4 – 6 s/frame
Effective frame rate ~0.3 – 0.6 fps
Peak RAM during inference ~700 MB / 1024 MB
Peak detection confidence 0.85 (Parasa indetermina, frame 14)
Annotated frames produced 11

The ~0.3–0.6 fps throughput is sufficient for static-surface monitoring: insects on the tray remain stationary for seconds to minutes. It is not sufficient for fast-flying insects — see Roadmap.


Known Hardware Constraints

Empirically observed constraints and their mitigations. See the full project report for detailed root-cause analysis.

# Constraint Severity Mitigation
1 Voltage instability — CSI camera corrupts below ~4.65 V HIGH Dedicated 5 V/3 A supply, short 26 AWG cable
2 CPU thermal throttling — clock drops 1.4 GHz → 600 MHz above 80°C HIGH Heatsinks, ventilation slots, FRAME_DELAY
3 RAM exhaustion — OOM kills / swap thrashing near 700–750 MB HIGH OS Lite, gpu_mem=16, YOLOv5n, explicit gc.collect()
4 Wi-Fi / SSH instability — periodic 3–10 s freezes MEDIUM iwconfig wlan0 power off, ServerAliveInterval=30, /snap fallback
5 MicroSD I/O degradation under continuous small-file writes MEDIUM High-endurance (dashcam-rated) card, batched CSV writes
6 Inference latency — precludes fast-flying insect detection LOW (accepted) Acceptable for static tray monitoring; Coral USB Accelerator planned

Troubleshooting

Symptom Likely cause Fix
PATH ERRORS on startup, "YOLOv5 directory not found" HOME_DIR in config/settings.py doesn't match the actual install path Update HOME_DIR to /home/<username>/insect_detect
Model weights not found best.pt not copied to the Pi scp best.pt into <HOME_DIR>/yolov5/
All camera backends failed CSI cable not seated / camera not enabled Check ribbon cable orientation at both ends; vcgencmd get_camera; enable camera in raspi-config
Frames are black Camera lens cap on, or AEC warm-up too short in low light Increase the 1 s time.sleep() in picamera2_backend.py to 2 s
Corrupted / scrambled frames Under-voltage Use a 5 V/3 A supply with a short 26 AWG cable
All frames show "no detections" CONF_THRESHOLD too high, or model not trained on the target species Lower CONF_THRESHOLD; verify the species is in the 33-class set
MJPEG stream loads once then freezes Wi-Fi power management sudo iwconfig wlan0 power off; use /snap as a fallback
detections.csv missing/incomplete after shutdown Process killed with kill -9 instead of Ctrl+C, bypassing the final flush Always stop with Ctrl+C (SIGINT) or systemctl stop (SIGTERM)

Roadmap

Phase Focus Planned work
1 Power Autonomy Solar panel + LiPo battery, multi-week deployment, DC-DC power budget
2 AI Acceleration Pi 4/5 upgrade, Google Coral USB Accelerator, sub-200 ms inference
3 Wide-Area Connectivity LoRaWAN / GSM-LTE uplink, central biodiversity server
4 Physical Robustness IP65-rated weatherproof housing, condensation management, active cooling
5 Dataset Expansion European species (bees, hoverflies, butterflies), sticky-trap validation

References

  1. Sánchez-Bayo, F. & Wyckhuys, K.A.G. (2019). Worldwide decline of the entomofauna: A review of its drivers. Biological Conservation, 232, 8–27.
  2. Geissmann, Q. et al. (2023). Insect Detect: An open-source DIY camera trap for automated insect monitoring. bioRxiv.
  3. Wu, X. et al. (2019). IP102: A Large-Scale Benchmark Dataset for Insect Pest Recognition. IEEE/CVF CVPR.
  4. Jocher, G. et al. (2020). ultralytics/yolov5. Zenodo.

License

This project is licensed under the MIT License.

About

Autonomous edge-AI insect monitoring system. YOLOv5n detection on Raspberry Pi 3 B+ with live MJPEG stream, local storage, zero cloud dependency.

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages