Skip to content

About

AgroSentry AI is a high-performance, offline-capable mobile application developed in Flutter. The platform enables farmers, agronomists, and agricultural researchers to perform instantaneous, on-device diagnostic analysis of crop leaf diseases.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

AgroSentry AI: Enterprise-Grade Offline Crop Disease Diagnostic Suite

CURRENTLY IN DEVELOPMENT

AgroSentry AI is a high-performance, offline-capable mobile application developed in Flutter. The platform enables farmers, agronomists, and agricultural researchers to perform instantaneous, on-device diagnostic analysis of crop leaf diseases. By leveraging localized TensorFlow Lite deep learning inference, the application operates entirely without internet access or cloud dependency, ensuring utility in remote fields and low-connectivity environments.


Technical Architecture Overview

AgroSentry AI employs a decoupled architectural pattern, segregating stateful UI components, data persistency layers, and deep learning execution services.

graph TD
    UI[Flutter UI Layer] --> Provider[Scan Provider State Management]
    Provider --> ModelSvc[Model Service - TFLite Inference]
    Provider --> DBSvc[Database Service - SQLite]
    ModelSvc --> ImageProc[Image Processing Pipeline]
    ModelSvc --> DBSvc
    DBSvc --> SQLite[(Local SQLite Database)]
    ImageProc --> FileSys[(On-Device File System)]
Loading

Core Architecture Components

  1. Inference Engine (TensorFlow Lite): Encapsulated in the ModelService singleton, this module interfaces with the MobileNet-based convolutional neural network (plant_disease.tflite). It executes on-device inference utilizing two execution threads to balance classification latency with system thermals.
  2. Local Data Persistence (SQLite): Controlled by DatabaseService, this module maintains a dual-table database schema (scans and remedies) using the sqflite engine. It facilitates automatic schema migrations across app updates and manages historical scan tracking.
  3. State Management (ChangeNotifier): The ScanProvider state manager acts as the controller, coordinating async camera inputs, image pre-processing, classification execution, and storage of output payloads into the relational database.

High-Level System Execution Flow

The sequence diagram below displays the end-to-end communication lifecycle from physical input capture to diagnostic logging and dashboard render.

sequenceDiagram
    autonumber
    actor User as Field Agronomist
    participant UI as Flutter UI Screen
    participant Provider as ScanProvider (State)
    participant ModelSvc as ModelService (Interpreter)
    participant DBSvc as DatabaseService (SQLite)
    participant Model as TFLite Binary

    User->>UI: Capture leaf photo in Camera Viewfinder
    UI->>Provider: Invoke analyzeImage(imagePath)
    activate Provider
    Provider->>Provider: Set isAnalyzing = true & notify UI
    UI->>UI: Display analytical loading progress bar
    Provider->>ModelSvc: Invoke predictImage(imageFile)
    activate ModelSvc
    ModelSvc->>ModelSvc: Decode image bytes & center-crop to square
    ModelSvc->>ModelSvc: Resize image to 224x224 & extract normalized Float32 values
    ModelSvc->>Model: Run model.run(input, output)
    activate Model
    Model-->>ModelSvc: Return 38 classification logits
    deactivate Model
    ModelSvc->>ModelSvc: Sort logits & extract Top 5 predictions
    ModelSvc->>DBSvc: Query remedies table for top class label
    activate DBSvc
    DBSvc-->>ModelSvc: Return symptoms & remedy JSON structures
    deactivate DBSvc
    ModelSvc-->>Provider: Return hydrated CropDisease payload
    deactivate ModelSvc
    Provider->>DBSvc: Save scan metadata to scans table (insertScan)
    activate DBSvc
    DBSvc-->>Provider: Return autogenerated database ID
    deactivate DBSvc
    Provider->>Provider: Update currentScan, set isAnalyzing = false & notify UI
    deactivate Provider
    UI->>UI: Render DetailScreen with diagnostic data
    UI-->>User: Present diagnostic details, confidence, and treatment plans
Loading

Machine Learning & Inference Pipeline

The deep learning classifier is optimized for mobile deployment. The application uses a custom MobileNet model trained on crop leaf datasets, covering 38 distinct classes (comprising healthy crops and diverse bacterial, fungal, and viral pathological states).

Model Input and Output Specifications

  • Input Tensor:
    • Identifier: input_2
    • Data Type: Float32
    • Shape: [1, 224, 224, 3] (representing batch size, width, height, and RGB channels)
    • Normalization: Raw pixel values (0-255) are normalized to [0.0, 1.0] prior to input injection.
  • Output Tensor:
    • Identifier: Identity
    • Data Type: Float32
    • Shape: [1, 38]
    • Activation Function: Softmax (representing probability distribution across the 38 classes)

Preprocessing and Normalization Code Snippet

The snippet below from ModelService demonstrates the exact normalization and center-square cropping applied to images before executing the TensorFlow Lite interpreter:

// Extracting, cropping, and normalizing pixel channels in ModelService.dart
final int minDimension = decoded.width < decoded.height ? decoded.width : decoded.height;
final int startX = (decoded.width - minDimension) ~/ 2;
final int startY = (decoded.height - minDimension) ~/ 2;

final cropped = img.copyCrop(
  decoded,
  x: startX,
  y: startY,
  width: minDimension,
  height: minDimension,
);

final resized = img.copyResize(cropped, width: 224, height: 224);
final inputBuffer = Float32List(224 * 224 * 3);
int index = 0;

for (int y = 0; y < 224; y++) {
  for (int x = 0; x < 224; x++) {
    final pixel = resized.getPixel(x, y);
    // Normalize color channels to [0.0, 1.0] range
    inputBuffer[index++] = pixel.r / 255.0;
    inputBuffer[index++] = pixel.g / 255.0;
    inputBuffer[index++] = pixel.b / 255.0;
  }
}

Database Architecture & Migration Engine

The local SQLite relational engine is managed by DatabaseService. It maintains structural database tables and seeds remedy lookups automatically on the first initialization.

Data Definition Language (DDL) Schemas

1. scans Table

CREATE TABLE scans (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    scientificName TEXT NOT NULL,
    description TEXT NOT NULL,
    symptoms TEXT NOT NULL,
    treatment TEXT NOT NULL,
    confidence REAL NOT NULL,
    imagePath TEXT NOT NULL,
    scanDate TEXT NOT NULL,
    top5 TEXT,
    isConfident INTEGER,
    cropName TEXT,
    diseaseName TEXT
);

2. remedies Table

CREATE TABLE remedies (
    className TEXT PRIMARY KEY,
    description TEXT NOT NULL,
    symptoms TEXT NOT NULL,
    organicRemedy TEXT NOT NULL,
    chemicalRemedy TEXT NOT NULL,
    prevention TEXT NOT NULL
);

Database Migration Engine

The service implements a structured, incremental migration mechanism utilizing database versioning:

  • Version 1: Initial release, creates scans schema.
  • Version 2: Adds top5 JSON string metadata to scans for model analytical telemetry.
  • Version 3: Adds confidence status (isConfident), cropName, and diseaseName classifications to support advanced filtering.
  • Version 4: Creates and populates the remedies lookup index to store agricultural solution guidelines offline.
Future _upgradeDB(Database db, int oldVersion, int newVersion) async {
  if (oldVersion < 2) {
    await db.execute('ALTER TABLE scans ADD COLUMN top5 TEXT');
  }
  if (oldVersion < 3) {
    await db.execute('ALTER TABLE scans ADD COLUMN isConfident INTEGER');
    await db.execute('ALTER TABLE scans ADD COLUMN cropName TEXT');
    await db.execute('ALTER TABLE scans ADD COLUMN diseaseName TEXT');
  }
  if (oldVersion < 4) {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS remedies (
        className TEXT PRIMARY KEY,
        description TEXT NOT NULL,
        symptoms TEXT NOT NULL,
        organicRemedy TEXT NOT NULL,
        chemicalRemedy TEXT NOT NULL,
        prevention TEXT NOT NULL
      )
    ''');
  }
}

State Management Architecture

State mutations are coordinated by the ScanProvider class, implementing the ChangeNotifier pattern. The state updates are structured around an internal state model:

stateDiagram-v2
    [*] --> Idle
    Idle --> Analyzing : User triggers analyzeImage()
    Analyzing --> Success : Inference complete, saved to DB
    Analyzing --> Failure : Inference failed or out-of-memory
    Success --> Idle : clear() called
    Failure --> Idle : clear() called
Loading

State Properties

  • _currentScan: Stores the active hydrated CropDisease instance.
  • _isAnalyzing: Boolean flag indicating if image preprocessing or TFLite inference is running.
  • _error: Captures error states for UI rendering (e.g. file access errors, model issues).
// Core state transition logic in scan_provider.dart
Future<CropDisease> analyzeImage(String imagePath) async {
  _isAnalyzing = true;
  _error = '';
  notifyListeners();

  try {
    final imageFile = File(imagePath);
    final result = await ModelService.instance.predictImage(imageFile);
    await DatabaseService.instance.insertScan(result);

    _currentScan = result;
    _isAnalyzing = false;
    notifyListeners();
    return result;
  } catch (e) {
    _isAnalyzing = false;
    _error = e.toString();
    notifyListeners();
    rethrow;
  }
}

Directory Structure & Codebase Map

agro_sentry_ai/
├── assets/
│   ├── data/
│   │   ├── labels.txt          # Mapping of index to the 38 classification classes
│   │   └── remedies.json       # Seed data containing detailed disease descriptions and remedies
│   ├── images/
│   │   ├── app_icon.png        # Launcher icon assets
│   │   └── splash_brand.png    # Branding asset for native splash screens
│   ├── models/
│   │   └── plant_disease.tflite # Compact compiled deep learning model binary
│   └── test_images/
│       └── leaf_test.png       # Test image for validation
├── lib/
│   ├── main.dart               # Bootstrapper initializing SQLite and TFLite
│   ├── models/
│   │   └── crop_disease.dart   # Data modeling schemas for CropDisease and Prediction objects
│   ├── screens/
│   │   ├── camera_screen.dart  # Native camera controller with viewfinder guide overlay
│   │   ├── detail_screen.dart  # Detailed display for treatments, symptoms, and analytics
│   │   ├── history_screen.dart # Paginated list of historical crop diagnoses
│   │   ├── home_screen.dart    # Dashboard displaying recent scans and quick-action triggers
│   │   ├── image_preview_screen.dart # Image verification step before processing
│   │   └── scan_screen.dart    # Entry screen coordinating photo upload and scan execution
│   ├── services/
│   │   ├── database_service.dart # SQLite management, tables creation, upgrade and seed handlers
│   │   ├── model_service.dart  # TFLite loading, pre-processing, and inference execution
│   │   └── scan_provider.dart  # Global state manager for active scan sessions
│   └── widgets/
│       └── disease_card.dart   # Reusable UI card for history and dashboard listings
└── pubspec.yaml                # Flutter project dependency configuration

User Interface & Views Walkthrough

1. Home Dashboard (home_screen.dart)

  • Renders current diagnostics metrics (total plants scanned, healthy rates, and pathogen detection logs).
  • Displays a horizontal sliding carousel showing recent scans.
  • Offers floating shortcut triggers to start a new leaf diagnostic session immediately.

2. Camera Viewfinder (camera_screen.dart)

  • Integrates a live camera feed.
  • Displays a physical guide box overlay on the camera preview, directing the user to place the leaf in the center to optimize cropping precision.
  • Provides real-time controls for camera flash settings and camera switching (rear/front).
  • Restricts access to standard system photo galleries if the user prefers to select an existing image.

3. Image Verification (image_preview_screen.dart)

  • Freezes the captured frame before model analysis.
  • Allows users to review photo quality and alignment.
  • Provides quick controls to discard and re-capture the image.

4. Diagnosis and Analytics Detail Page (detail_screen.dart)

  • Renders diagnosis results alongside a visual confidence bar.
  • Displays botanical classifications and Latin scientific names.
  • Displays expandable tabs containing specific symptoms, organic solutions, chemical controls, and preventive steps.
  • Features a dropdown section showing alternative classifications (top 5 predictions) to assist agronomists with complex diagnoses.

5. Historical Database Repository (history_screen.dart)

  • Displays a scrollable timeline of all historical scans.
  • Features a local search bar to filter records by crop or disease name.
  • Includes swipe-to-delete options to remove old scan files and database records.

Target Pathological Classification Classes

The TFLite model classifier supports 38 classes, mapping crop types to specific health states:

Supported Botanical Species

  1. Apple: Scab, Black Rot, Cedar Rust, Healthy
  2. Blueberry: Healthy
  3. Cherry: Powdery Mildew, Healthy
  4. Corn (Maize): Gray Leaf Spot, Common Rust, Northern Leaf Blight, Healthy
  5. Grape: Black Rot, Esca (Black Measles), Leaf Blight, Healthy
  6. Orange: Citrus Greening (Huanglongbing)
  7. Peach: Bacterial Spot, Healthy
  8. Pepper (Bell): Bacterial Spot, Healthy
  9. Potato: Early Blight, Late Blight, Healthy
  10. Raspberry: Healthy
  11. Soybean: Healthy
  12. Squash: Powdery Mildew
  13. Strawberry: Leaf Scorch, Healthy
  14. Tomato: Bacterial Spot, Early Blight, Late Blight, Leaf Mold, Septoria Leaf Spot, Spider Mites (Two-spotted spider mite), Target Spot, Yellow Leaf Curl Virus, Mosaic Virus, Healthy

Installation and Configuration

Prerequisites

  • Flutter SDK (version 3.0.0 or higher) installed and configured on the path.
  • Target SDK version: Android API level 21 minimum, iOS 12.0 minimum.
  • Physical device or emulator with camera permissions enabled.

1. Generate Platform Project Files

Generate platform-specific wrappers for Android and iOS in the current directory:

flutter create --org com.agrosentry --project-name agro_sentry .

2. Fetch Dependencies

Install package requirements:

flutter pub get

3. Setup Custom Assets

Verify that your assets are properly located and mapped:

  • TFLite Model File: assets/models/plant_disease.tflite
  • Labels Text File: assets/data/labels.txt
  • Remedies JSON File: assets/data/remedies.json

Verify the asset configuration in pubspec.yaml:

flutter:
  assets:
    - assets/models/plant_disease.tflite
    - assets/data/labels.txt
    - assets/data/remedies.json

4. Build and Run

Launch the application on your target emulator or physical device:

flutter run

Troubleshooting & Build Optimization

1. Android Release Crash (Native Library Errors)

If the application crashes on launch when built in --release mode, the issue is typically due to Proguard shrinking the native C++ library binaries utilized by TensorFlow Lite. To resolve this, add the following lines to your android/app/proguard-rules.pro file:

# Prevent ProGuard from renaming or stripping TFLite C++ symbols
-keep class org.tensorflow.lite.** { *; }
-dontwarn org.tensorflow.lite.**

2. OOM (Out Of Memory) & Garbage Collection Lag

Processing high-resolution images can exhaust heap memory on older mobile devices. To prevent memory issues:

  • Garbage Collection: Reassign local image bytes variables to null immediately after extracting the Float32 flat buffer.
  • TFLite Disposal: When navigating away from scanning workflows, call dispose() on the model service to release GPU and CPU delegate instances.
// Properly disposing of model interpreter instances
void dispose() {
  _interpreter?.close();
  _interpreter = null;
  _isLoaded = false;
}

3. Camera Controller Unsynchronized States

To prevent camera controller lag or hardware access crashes:

  • Always initialize the camera controller using a FutureBuilder or in an async initState block.
  • Call dispose() on the controller inside the screen's dispose() lifecycle method to free camera hardware locks.
@override
void dispose() {
  _cameraController?.dispose();
  super.dispose();
}

Testing & Verification Suite

AgroSentry AI includes tests to verify preprocessing, model loading, and database services.

1. Running Flutter Unit and Integration Tests

To run all local tests, execute:

flutter test

2. Mocking Model Inference for Unit Tests

The test file test/model_service_test.dart checks the fallback detection flows when TFLite interpreter hardware features are unavailable during unit testing.

void main() {
  test('Verification of offline fallback values on low confidence detection', () {
    // Verifies that predictions below the 60% confidence threshold
    // return an uncertain diagnostic classification.
    final confidence = 0.45;
    final isConfident = confidence >= 0.60;
    
    expect(isConfident, isFalse);
  });
}

Developer Information

About

AgroSentry AI is a high-performance, offline-capable mobile application developed in Flutter. The platform enables farmers, agronomists, and agricultural researchers to perform instantaneous, on-device diagnostic analysis of crop leaf diseases.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages