diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/README.md b/CV_VR/IoT-Robotics/plant_disease_detection/README.md new file mode 100644 index 0000000..b64994e --- /dev/null +++ b/CV_VR/IoT-Robotics/plant_disease_detection/README.md @@ -0,0 +1,406 @@ +# [Startup_Demo](../../../)/[CV_VR](../../)/[IoT-Robotics](../)/[Plant_Disease_Detection](./) + +# Plant Disease Detection with Arduino UNO Q + +## Table of Contents +- [1. Overview](#1-overview) +- [2. Classification Scenarios](#2-classification-scenarios) +- [3. Requirements](#3-requirements) + - [3.1 Hardware](#31-hardware) + - [3.2 Software](#32-software) +- [4. Plant Disease Detection Workflow](#4-plant-disease-detection-workflow) +- [5. Setup Instructions](#5-setup-instructions) + - [5.1 Setting Up Visual Studio Code (VS Code)](#51-setting-up-visual-studio-code-vs-code) + - [5.2 Setting Up Arduino App Lab](#52-setting-up-arduino-app-lab) + - [5.3 Setting Up Arduino Flasher Cli](#53-setting-up-arduino-flasher-cli) + - [5.4 Setting Up Arduino UNO-Q Device](#54-setting-up-arduino-uno-q-device) +- [6. Get the Model from Edge Impulse](#6-get-the-model-from-edge-impulse) + - [6.1 Setup an Edge Impulse Account](#61-setup-an-edge-impulse-account) + - [6.2 Clone the Edge Impulse Project](#62-clone-the-edge-impulse-project) +- [7. Dataset Collection and Training](#7-dataset-collection-and-training) + - [7.1 Download the Dataset](#71-download-the-dataset) +- [8. Uploading the Dataset and Retraining the Model in Edge Impulse (Optional Step to train the model with new dataset)](#8-uploading-the-dataset-and-retraining-the-model-in-edge-impulse-optional-step-to-train-the-model-with-new-dataset) +- [9. Build and Download Deployable Model](#9-build-and-download-deployable-model) +- [10. Prepare the Application](#10-prepare-the-application) + - [10.1 Copy Existing Video Classification on Camera Application](#101-copy-existing-video-classification-on-camera-application) + - [10.2 Upload Model to the Device](#102-upload-model-to-the-device) + - [10.3 Clone the Plant Disease Detection Application](#103-clone-the-plant-disease-detection-application) + - [10.4 Modify the Sketch File](#104-modify-the-sketch-file) + - [10.5 Modify the Main Python File](#105-modify-the-main-python-file) +- [11. Run the Plant Disease Detection Application](#11-run-the-plant-disease-detection-application) + - [11.1 Demo Output](#111-demo-output) + +## 1. Overview + +The **Plant Disease Detection** demo showcases the edge AI capabilities of the **Arduinoยฎ UNO Q** using a trained model from **Edge Impulse**. This application enables real-time detection and classification of plant diseases from a live video feed captured by a USB webcam, with audible alerts via a buzzer when diseases are detected. + +- ๐Ÿ“ท **Live Disease Detection**: Continuously captures frames from a USB camera and classifies plant diseases using a pre-trained AI model. +- ๐Ÿง  **AI-Powered Processing**: Utilizes the `video_imageclassification` Brick to analyze video frames and identify plant diseases. +- ๐ŸŒ **Web-Based Interface**: Managed through a web interface for seamless control and monitoring. +- ๐Ÿ”Š **Buzzer Alert System**: Activates buzzer for 5 seconds when a disease is detected. +- ๐ŸŽฏ **24 Classification Scenarios**: Detects 16 different diseases and 8 healthy plant states across 8 plant types. + +> **Important:** This demo must be run in **Network Mode or SBC** within the Arduino App Lab. + +This demonstration highlights how the Arduino UNO Q can be paired with a USB webcam to perform edge AI tasks such as plant disease detection. It exemplifies the integration of Edge Impulse models with Arduino hardware for intelligent, real-time computer vision applications in agriculture. + +## 2. Classification Scenarios + +The application supports **24 different classification scenarios** across 8 plant types: + +### ๐ŸŽ Apple (3 scenarios) +1. **Apple_Black_Rot** - Fungal disease causing dark, circular lesions on fruit and leaves +2. **Apple_Scab** - Fungal disease with olive-green to brown lesions on leaves and fruit +3. **Apple_Healthy** - Healthy apple plant with no visible disease symptoms + +### ๐ŸŒถ๏ธ Bell Pepper (2 scenarios) +4. **Bell_Pepper_Bacterial_Spot** - Bacterial disease causing leaf spots and fruit lesions +5. **Bell_Pepper_Healthy** - Healthy bell pepper plant + +### ๐Ÿ’ Cherry (2 scenarios) +6. **Cherry_Powdery_Mildew** - Fungal disease causing white powdery growth on leaves +7. **Cherry_Healthy** - Healthy cherry plant + +### ๐ŸŒฝ Corn (3 scenarios) +8. **Corn_Common_Rust** - Fungal disease causing rust-colored pustules on leaves +9. **Corn_Northern_Leaf_Blight** - Fungal disease with long, elliptical lesions +10. **Corn_Healthy** - Healthy corn plant + +### ๐Ÿ‡ Grape (3 scenarios) +11. **Grape_Black_Rot** - Fungal disease affecting leaves, shoots, and fruit +12. **Grape_Leaf_Blight** - Fungal disease causing leaf spots and blight +13. **Grape_Healthy** - Healthy grape plant + +### ๐Ÿ… Tomato (3 scenarios) +14. **Tomato_Late_Blight** - Devastating fungal-like disease with water-soaked lesions +15. **Tomato_Mosaic_Virus** - Viral disease causing mottled leaves and stunted growth +16. **Tomato_Healthy** - Healthy tomato plant + +### ๐Ÿฅ” Potato (3 scenarios) +17. **Potato_Late_Blight** - Devastating fungal-like disease with water-soaked lesions +18. **Potato_Early_Blight** - Fungal disease causing dark brown spots with concentric rings +19. **Potato_Healthy** - Healthy potato plant + +### ๐Ÿ“ Strawberry (2 scenarios) +20. **Strawberry_Scorch** - Fungal disease causing leaf scorch and browning +21. **Strawberry_Healthy** - Healthy strawberry plant + +### Detection Features +- **Minimum Confidence**: 50% threshold for disease detection +- **Debouncing**: Requires 3 consecutive frames for stable classification +- **Timeout**: Resets to "Unknown" after 1 second of no detection +- **Buzzer Alert**: 5-second alert when disease is detected (not triggered for healthy states) + +## 3. Requirements + +### 3.1 Hardware + +- **[Arduinoยฎ UNO Q](../../../Hardware/Arduino_UNO-Q.md#arduino-uno-q)** +- **Modulino Buzzer** (for audio alerts) +- USB camera (x1) +- USB-Cยฎ hub adapter with external power (x1) +- A power supply (5 V, 3 A) for the USB hub (e.g., a phone charger) +- Personal computer (x86/AMD64) with internet access + +### 3.2 Software + +- Arduino App Lab +- Edge Impulse +- Bricks +- VS Code + +## 4. Plant Disease Detection Workflow + +```mermaid +flowchart LR + A[Start] --> B[Setting Up Arduino UNO-Q Device] + B --> C[Create/Train Edge Impulse Model] + C --> D[Download Deployable Model] + D --> E[Upload Model to Device] + E --> F[Deploy Application] + F --> G[โœ… Disease Detection Active] +``` + +## 5. Setup Instructions + +Before proceeding further, please ensure that **all the setup steps outlined below are completed in the specified order**. These instructions are essential for configuring the various tools required to successfully run the application. + +### 5.1 Setting Up Visual Studio Code (VS Code) + +Visual Studio Code is the recommended IDE for editing, debugging, and managing the project's source code. + +For detailed steps, refer to the internal documentation: +[Set up VS Code](../../../Tools/Software/VScode_Setup/README.md#34-configure-ssh) + +### 5.2 Setting Up Arduino App Lab + +Arduino App Lab enables you to create and deploy Apps directly on the Arduinoยฎ UNO Q board. + +For detailed steps, refer to the documentation: +[Set up Arduino App Lab](../../../Tools/Software/Arduino_App_Lab/README.md#4-installation) + +### 5.3 Setting Up Arduino Flasher Cli + +Arduino Flasher CLI provides a streamlined way to flash Linux images onto your Arduino UNO Q board. + +For detailed steps, refer to the documentation: +[Arduino Flasher CLI](../../../Hardware/Arduino_UNO-Q.md#flashing-a-new-image-to-the-uno-q) + +### 5.4 Setting Up Arduino UNO-Q Device + +Arduino UNO-Q must be properly configured to ensure reliable communication with the host system. + +For detailed steps, refer to the documentation: +[Set up Arduino UNO-Q](../../../Hardware/Arduino_UNO-Q.md#uno-q-as-a-single-board-computer) + +## 6. Get the Model from Edge Impulse + +Edge Impulse empowers you to build datasets, train machine learning models, and optimize libraries for deployment directly on-device. + +Click here to know more about [Edge Impulse](../../../Tools/Software/Edge_Impluse/README.md) + +### 6.1 Setup an Edge Impulse Account + +An Edge Impulse account is required to access the platform's full suite of tools for building, training, and deploying machine learning models. + +Follow the instructions to sign up: +[Signup Instructions](../../../Tools/Software/Edge_Impluse/README.md#22-login-or-signup) + +### 6.2 Clone the Edge Impulse Project + +Cloning an Edge Impulse project allows you to replicate existing machine learning workflows, datasets, and configurations for customization or deployment on the Arduino UNO Q. Please follow the setup instructions carefully to ensure proper synchronization and compatibility with your device. + +Clone the Industrial plant disease detection project [Plant disease detection](https://studio.edgeimpulse.com/public/940384/live) + +For detailed steps, refer to the documentation: +[Clone Project](../../../Tools/Software/Edge_Impluse/README.md#29-clone-project-repository) + +## 7. Dataset Collection and Training + +This section explains how to prepare, convert, and upload a dataset into Edge Impulse Studio for model training. + +### 7.1 Download the Dataset + +You'll need to collect or download datasets for all 24 classification scenarios. Here are some recommended sources: + +#### Plant Disease Datasets: +- **PlantVillage Dataset**: Comprehensive dataset with multiple plant diseases + - [PlantVillage on Kaggle](https://www.kaggle.com/datasets/emmarex/plantdisease) +- **Plant Pathology Dataset**: High-quality images of plant diseases + - [Plant Pathology 2020](https://www.kaggle.com/c/plant-pathology-2020-fgvc7) + +#### Specific Disease Datasets: +- **Apple Diseases**: Search for apple scab and black rot datasets +- **Tomato Diseases**: Late blight and mosaic virus datasets +- **Corn Diseases**: Common rust and northern leaf blight datasets +- **Grape Diseases**: Black rot and leaf blight datasets +- **Bell Pepper Diseases**: Bacterial spot datasets + +โš ๏ธ **Disclaimer:** Please review and comply with each dataset's license terms and conditions before accessing, using, or redistributing the data. + +#### Dataset Organization: +Organize your dataset into folders matching the classification labels: +``` +Dataset/ +โ”œโ”€โ”€ Apple_Black_Rot/ +โ”œโ”€โ”€ Apple_Scab/ +โ”œโ”€โ”€ Apple_Healthy/ +โ”œโ”€โ”€ Bell_Pepper_Bacterial_Spot/ +โ”œโ”€โ”€ Bell_Pepper_Healthy/ +โ”œโ”€โ”€ Cherry_Powdery_Mildew/ +โ”œโ”€โ”€ Cherry_Healthy/ +โ”œโ”€โ”€ Corn_Common_Rust/ +โ”œโ”€โ”€ Corn_Northern_Leaf_Blight/ +โ”œโ”€โ”€ Corn_Healthy/ +โ”œโ”€โ”€ Grape_Black_Rot/ +โ”œโ”€โ”€ Grape_Leaf_Blight/ +โ”œโ”€โ”€ Grape_Healthy/ +โ”œโ”€โ”€ Tomato_Late_Blight/ +โ”œโ”€โ”€ Tomato_Mosaic_Virus/ +โ”œโ”€โ”€ Tomato_Healthy/ +โ”œโ”€โ”€ Potato_Late_Blight/ +โ”œโ”€โ”€ Potato_Early_Blight/ +โ”œโ”€โ”€ Potato_Healthy/ +โ”œโ”€โ”€ Strawberry_Scorch/ +โ””โ”€โ”€ Strawberry_Healthy/ +``` + +## 8. Uploading the Dataset and Retraining the Model in Edge Impulse (Optional Step to train the model with new dataset) +This section provides instructions for uploading a new dataset and retraining the model in Edge Impulse Studio. This step is optional but useful when you want to enhance the model's performance with additional data or customize it for specific use cases. + +> **Note:** If you are using the pre-trained model provided in the project, you can skip this section. However, if you wish to customize or improve the model with your own dataset, proceed with the following steps. + +### Step 1: Upload Dataset to Edge Impulse + +1. Go to your Edge Impulse project +2. Navigate to **Data acquisition** tab +3. Click **Upload data** +4. Select your organized dataset folders +5. Ensure each image is labeled correctly according to the folder name + +![N|Solid](assets/images/uno_q_plantdisease_data.png) + +### Step 2: Retrain the Model + +1. Go to **Transfer Learning** under Impulse design +2. Click **Start training** +3. Wait for training to complete +4. Review accuracy metrics + +![N|Solid](assets/images/uno_q_plantdisease_train.png) + +### Step 3: Test the Model + +1. Go to **Model testing** tab +2. Click **Classify all** +3. Review classification accuracy for each scenario +4. If accuracy is low, consider: + - Adding more training data + - Adjusting training parameters + - Using data augmentation + +![N|Solid](assets/images/uno_q_plantdisease_test.png) + +## 9. Build and Download Deployable Model + +Edge Impulse allows you to build optimized machine learning models tailored for deployment on the Arduino UNO Q. + +### Build Steps: + +1. Navigate to **Deployment** tab in Edge Impulse Studio +2. Select **Ardduino UNO Q** as the deployment target +3. Click **Build** to create the deployable model +4. The model will automatically download as a `.eim` file + +![N|Solid](assets/images/uno_q_app_edge_impulse_deployment.png) + +For detailed steps, refer to the documentation: +[Build and Deploy Model](../../../Tools/Software/Edge_Impluse/README.md#28-download-deployable-model) + +## 10. Prepare the Application + +### 10.1 Copy Existing Video Classification on Camera Application + +Arduino App Lab provides a ready-to-use Video Image Classification on Camera application that can be copied and customized for your specific use case. This section will guide you through duplicating the existing application, modifying its components, integrating Edge Impulse models, and tailoring the classification logic to suit your deployment on the Arduino UNO Q. + +In this example, we are using the Person classifer on Camera application for Plant Disease Detection. + +![N|Solid](assets/images/uno_q_plantdisease_dashboard.png) + +Click on the Copy and Edit button to modify the application and name it Plant Disease Detection. + + ![N|Solid](assets/images/uno_q_plantdisease_app.png) + + For detailed steps, refer to the documentation: +[Copy and Edit Existing Sample]( ../../../Tools/Software/Arduino_App_Lab/README.md#duplicate-an-existing-example) + +### 10.2 Upload Model to the Device + +After obtaining the deployable model from [Section 9](#9-build-and-download-deployable-model), upload it to the Arduino UNO Q using one of the following options: + +**Option 1: Manual Upload via SSH or File Transfer** +1. Connect to your Arduino UNO Q via SSH or file transfer +2. Upload the `.eim` file to: `/home/arduino/.arduino-bricks/ei-models/plant-disease-detection-linux-aarch64-v1.eim` + +**Option 2: Upload via Arduino App Lab UI** +- Use the Arduino App Lab UI to upload the model directly to the device + +For detailed steps, refer to the documentation: +[Upload Model](../../../Tools/Software/Arduino_App_Lab/README.md#upload-model-to-device) + +### 10.3 Clone the Plant Disease Detection Application + +This section will guide you through cloning the Plant Disease Detection application from the repository, modifying its components, and deploying it to your Arduino UNO Q device. + +#### Steps + +1. **Create your working directory**: + +```bash +mkdir my_working_directory +cd my_working_directory +``` + +2. **Download the Application**: + +Clone the Plant Disease Detection application from the repository to get started with the project. This will provide you with all the necessary files including the application code, buzzer control logic, and configuration files needed for plant disease detection. + +```bash +cd ~ +git clone -n --depth=1 --filter=tree:0 https://github.com/qualcomm/Startup-Demos.git +cd Startup-Demos +git sparse-checkout set --no-cone /CV_VR/IoT-Robotics/plant_disesase_detection/ +git checkout +``` + +3. **Navigate to Application Directory**: + +```bash +cd ./CV_VR/IoT-Robotics/plant_disesase_detection/ +``` + +4. **Modify the Configuration Files and Main Functions**: + +The `app.yaml` file defines the structure, behavior, and dependencies of your Arduino App Lab application. Modifying this configuration allows you to customize how your app interacts with hardware, integrates Edge Impulse models, and launches on the Arduino UNO Q. This section will guide you through editing key parameters such as bricks, model paths, and runtime settings. + +```bash +cp app.yaml /home/arduino/ArduinoApps/Plant_Disease_Detection/ +``` + +### 10.4 Modify the Sketch File + +The `sketch.ino` file contains the main program logic for your Arduino App Lab project. It initializes hardware, communicates with bricks defined in `app.yaml`, and runs the primary control loop. This file implements the buzzer control system that alerts users when plant diseases are detected on the Arduino UNO Q. + +```bash +cp sketch.ino /home/arduino/ArduinoApps/Plant_Disease_Detection/sketch/ +``` + +### 10.5 Modify the Main Python File + +The `main.py` file contains the core Python logic for your Arduino App Lab application. It handles communication with connected bricks, runs Edge Impulse model inference, and processes events coming from the App Lab runtime. Use this file to define custom behaviors, manage data flow, and implement high-level control logic for your application. + +```bash +cp main.py /home/arduino/ArduinoApps/Plant_Disease_Detection/python/ +``` + +## 11. Run the Plant Disease Detection Application + +Once your application is configured and deployed in Arduino App Lab, you can run it directly on the Arduino UNO Q. + +### Running the Application: + +1. Open Arduino App Lab +2. Navigate to your Plant Disease Detection application +3. Click **Run** to start the application +4. The web interface will open showing the live camera feed +5. Point the camera at plants to detect diseases + +![N|Solid](assets/images/uno_q_app_run.png) + +For detailed steps, refer to the documentation: +[Run Application](../../../Tools/Software/Arduino_App_Lab/README.md#run-example-apps-in-arduino-app-lab) + +### 11.1 Demo Output + +When running the application: + +#### Web Interface: +- **Live video feed** from the USB camera +- **Classification results** displayed in real-time +- **Confidence scores** for each detection +- **Timestamp** for each classification + +#### Buzzer Behavior: +- **Disease Detected**: Buzzer sounds for 5 seconds +- **Healthy Plant**: No buzzer sound +- **Unknown**: No buzzer sound +- **Debouncing**: Same disease won't re-trigger buzzer within 5 seconds + +#### Console Output: +``` +[INFO] Detection status changed: Unknown -> Tomato_Late_Blight +[INFO] New plant disease detected: Tomato_Late_Blight (confidence: 0.87) +[DEBUG] should_trigger_buzzer -> true (disease: Tomato_Late_Blight, time_since: 0.12s) +Buzzer activated - Disease detected! +``` +![N|Solid](assets/images/uno_q_plantdisease_output.gif) diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/app.yaml b/CV_VR/IoT-Robotics/plant_disease_detection/app.yaml new file mode 100644 index 0000000..d24a213 --- /dev/null +++ b/CV_VR/IoT-Robotics/plant_disease_detection/app.yaml @@ -0,0 +1,17 @@ +#===--app.yaml----------------------------------------------===// +# Part of the Startup-Demos Project, under the MIT License +# See https://github.com/qualcomm/Startup-Demos/blob/main/LICENSE.txt +# for license information. +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# SPDX-License-Identifier: MIT License +#===--------------------------------------------------------===// + +name: Plant Disease Detection +description: This example showcases plant disease classification within a live feed from a USB camera using Edge Impulse model. +ports: [] +bricks: +- arduino:video_image_classification: {variables: { + EI_IMAGE_CLASSIFICATION_MODEL: /home/arduino/.arduino-bricks/ei-models/plant-disease-detection-linux-aarch64-v1.eim + }} +- arduino:web_ui: {} +icon: ๐ŸŒฑ diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_app_edge_impulse_deployment.png b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_app_edge_impulse_deployment.png new file mode 100644 index 0000000..e94da54 Binary files /dev/null and b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_app_edge_impulse_deployment.png differ diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_app_run.png b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_app_run.png new file mode 100644 index 0000000..0aea78a Binary files /dev/null and b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_app_run.png differ diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_app.png b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_app.png new file mode 100644 index 0000000..795fe97 Binary files /dev/null and b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_app.png differ diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_dashboard.png b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_dashboard.png new file mode 100644 index 0000000..39e58e5 Binary files /dev/null and b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_dashboard.png differ diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_data.png b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_data.png new file mode 100644 index 0000000..45b4bd1 Binary files /dev/null and b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_data.png differ diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_output.gif b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_output.gif new file mode 100644 index 0000000..5426b04 Binary files /dev/null and b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_output.gif differ diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_test.png b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_test.png new file mode 100644 index 0000000..ec249d5 Binary files /dev/null and b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_test.png differ diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_train.png b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_train.png new file mode 100644 index 0000000..31ccea7 Binary files /dev/null and b/CV_VR/IoT-Robotics/plant_disease_detection/assets/images/uno_q_plantdisease_train.png differ diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/project.yaml b/CV_VR/IoT-Robotics/plant_disease_detection/project.yaml new file mode 100644 index 0000000..224ce8a --- /dev/null +++ b/CV_VR/IoT-Robotics/plant_disease_detection/project.yaml @@ -0,0 +1,14 @@ +name: "Plant_Disease_Detection" +description: "This application enables real-time plant disease classification from a live video feed captured by a USB webcam. It detects 16 different plant disease scenarios including Apple Black Rot, Apple Scab, Bell Pepper Bacterial Spot, Cherry Powdery Mildew, Corn Common Rust, Corn Northern Leaf Blight, Grape Black Rot, Grape Leaf Blight, Tomato Late Blight, Tomato Mosaic Virus, and healthy states for Tomato, Grape, Cherry, Corn, Bell Pepper, and Apple." +category: + - "CV_VR" + - "IoT-Robotics" +platforms: + - "Arduino UNO-Q" + - "Edge Impulse" +tags: + - "Computer Vision" + - "IoT" + - "Image Classification" + - "Real-time" + - "MCU" diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/python/main.py b/CV_VR/IoT-Robotics/plant_disease_detection/python/main.py new file mode 100644 index 0000000..baccc64 --- /dev/null +++ b/CV_VR/IoT-Robotics/plant_disease_detection/python/main.py @@ -0,0 +1,235 @@ +#===--main.py-------------------------------------------------------------===// +# Part of the Startup-Demos Project, under the MIT License +# See https://github.com/qualcomm/Startup-Demos/blob/main/LICENSE.txt +# for license information. +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +#===----------------------------------------------------------------------===// + +from arduino.app_utils import * +from arduino.app_bricks.web_ui import WebUI +from arduino.app_bricks.video_imageclassification import VideoImageClassification +from datetime import datetime, UTC +import threading +import time +import json + +## Disease Scenarios Configuration + +# Valid plant disease scenarios +DISEASE_SCENARIOS = { + # Apple diseases + "Apple_Black_Rot": {"plant": "Apple", "condition": "diseased", "severity": "high"}, + "Apple_Scab": {"plant": "Apple", "condition": "diseased", "severity": "high"}, + "Apple_Healthy": {"plant": "Apple", "condition": "healthy", "severity": "none"}, + + # Bell Pepper diseases + "Bell_Pepper_Bacterial_Spot": {"plant": "Bell Pepper", "condition": "diseased", "severity": "medium"}, + "Bell_Pepper_Healthy": {"plant": "Bell Pepper", "condition": "healthy", "severity": "none"}, + + # Cherry diseases + "Cherry_Powdery_Mildew": {"plant": "Cherry", "condition": "diseased", "severity": "medium"}, + "Cherry_Healthy": {"plant": "Cherry", "condition": "healthy", "severity": "none"}, + + # Corn diseases + "Corn_Common_Rust": {"plant": "Corn", "condition": "diseased", "severity": "medium"}, + "Corn_Northern_Leaf_Blight": {"plant": "Corn", "condition": "diseased", "severity": "high"}, + "Corn_Healthy": {"plant": "Corn", "condition": "healthy", "severity": "none"}, + + # Grape diseases + "Grape_Black_Rot": {"plant": "Grape", "condition": "diseased", "severity": "high"}, + "Grape_Leaf_Blight": {"plant": "Grape", "condition": "diseased", "severity": "high"}, + "Grape_Healthy": {"plant": "Grape", "condition": "healthy", "severity": "none"}, + + # Tomato diseases + "Tomato_Late_Blight": {"plant": "Tomato", "condition": "diseased", "severity": "high"}, + "Tomato_Mosaic_Virus": {"plant": "Tomato", "condition": "diseased", "severity": "high"}, + "Tomato_Healthy": {"plant": "Tomato", "condition": "healthy", "severity": "none"}, + + # Potato diseases + "Potato_Late_Blight": {"plant": "Potato", "condition": "diseased", "severity": "high"}, + "Potato_Early_Blight": {"plant": "Potato", "condition": "diseased", "severity": "high"}, + "Potato_Healthy": {"plant": "Potato", "condition": "healthy", "severity": "none"}, + + # Strawberry diseases + "Strawberry_Scorch": {"plant": "Strawberry", "condition": "diseased", "severity": "medium"}, + "Strawberry_Healthy": {"plant": "Strawberry", "condition": "healthy", "severity": "none"}, +} + +# Helper function to check if a detection is a disease (not healthy) +def is_disease(classification: str) -> bool: + """Check if the classification represents a disease (not healthy state)""" + if classification not in DISEASE_SCENARIOS: + return False + return DISEASE_SCENARIOS[classification]["condition"] == "diseased" + +# Helper function to get disease info +def get_disease_info(classification: str) -> dict: + """Get detailed information about a disease classification""" + return DISEASE_SCENARIOS.get(classification, { + "plant": "Unknown", + "condition": "unknown", + "severity": "unknown" + }) + +## global state + +current_status = "Unknown" # Plant disease status or Unknown +status_lock = threading.Lock() + +MIN_CONFIDENCE = 0.5 + +last_decision = "Unknown" +same_decision_count = 0 +DEBOUNCE_COUNT = 3 + +# Timeout: if no detection occurs beyond this number of seconds, force the status to Unknown +TIMEOUT_SECONDS = 1.0 +last_detection_time = time.time() + +# Track last detection for buzzer control (with lock protection) +last_detected_disease = None +detection_timestamp = 0 +detection_lock = threading.Lock() # Add lock for buzzer state + + +# Web UI & Video Image Classification + +ui = WebUI() +detection_stream = VideoImageClassification(confidence=MIN_CONFIDENCE, debounce_sec=0.0) + +ui.on_message("override_th", + lambda sid, threshold: detection_stream.override_threshold(threshold)) + + +def update_status_with_debounce(new_status: str): + global last_decision, same_decision_count, current_status + + if new_status == last_decision: + same_decision_count += 1 + else: + last_decision = new_status + same_decision_count = 1 + + if same_decision_count >= DEBOUNCE_COUNT: + with status_lock: + if current_status != new_status: + print(f"[INFO] Detection status changed: {current_status} -> {new_status}") + current_status = new_status + + +# VideoImageClassification callback + +def send_classifications_to_ui(classifications: dict): + global last_detection_time, last_detected_disease, detection_timestamp + + if len(classifications) == 0: + print("[DEBUG] classifications is empty (no detections this frame)") + return + + # Update last detection time + last_detection_time = time.time() + + entries = [] + best_classification = None + best_confidence = 0.0 + + for key, value in classifications.items(): + confidence = value if isinstance(value, float) else value.get("confidence", 0.0) + + entry = { + "content": key, + "confidence": confidence, + "timestamp": datetime.now(UTC).isoformat() + } + entries.append(entry) + + # Validate against known disease scenarios + if key in DISEASE_SCENARIOS: + disease_info = get_disease_info(key) + print(f"[DEBUG] classification label='{key}' confidence={confidence} | " + f"Plant: {disease_info['plant']}, Condition: {disease_info['condition']}, " + f"Severity: {disease_info['severity']}") + else: + print(f"[DEBUG] classification label='{key}' confidence={confidence} (unknown scenario)") + + # Track the best classification + if confidence > best_confidence: + best_confidence = confidence + best_classification = key + + # Send all classifications to UI + if len(entries) > 0: + msg = json.dumps(entries) + ui.send_message("classifications", message=msg) + + # Update status based on best classification + if best_classification and best_confidence >= MIN_CONFIDENCE: + current_time = time.time() + with detection_lock: # Protect shared state + if (last_detected_disease != best_classification or + (current_time - detection_timestamp) > 5.0): + last_detected_disease = best_classification + detection_timestamp = current_time + print(f"[INFO] New plant disease detected: {best_classification} (confidence: {best_confidence:.2f})") + + update_status_with_debounce(best_classification) + else: + update_status_with_debounce("Unknown") + + +detection_stream.on_detect_all(send_classifications_to_ui) + + +# Timeout background thread: set status to Unknown if no detection for over 1 second + +def timeout_watcher(): + global current_status + while True: + now = time.time() + dt = now - last_detection_time + if dt > TIMEOUT_SECONDS: + with status_lock: + if current_status != "Unknown": + print(f"[INFO] No detections for {dt:.2f}s -> force Unknown") + current_status = "Unknown" + time.sleep(0.1) + + +# Start the timeout thread +threading.Thread(target=timeout_watcher, daemon=True).start() + + +# Bridge: For MCU + +def get_detection_status(): + with status_lock: + status = current_status + print(f"[DEBUG] get_detection_status -> {status}") + return status + +def should_trigger_buzzer(): + """Check if buzzer should be triggered based on new detection""" + with detection_lock: # Protect shared state + current_time = time.time() + + # Trigger buzzer only for diseased plants (not healthy ones) + if last_detected_disease and last_detected_disease != "Unknown": + time_since_detection = current_time - detection_timestamp + is_recent = time_since_detection < 5.0 + is_diseased = is_disease(last_detected_disease) + should_trigger = is_recent and is_diseased + + if is_recent: + disease_info = get_disease_info(last_detected_disease) + print(f"[DEBUG] should_trigger_buzzer -> {should_trigger} | " + f"Disease: {last_detected_disease}, Condition: {disease_info['condition']}, " + f"Severity: {disease_info['severity']}, Time since: {time_since_detection:.2f}s") + + return should_trigger + + return False + +Bridge.provide("get_detection_status", get_detection_status) +Bridge.provide("should_trigger_buzzer", should_trigger_buzzer) + +App.run() diff --git a/CV_VR/IoT-Robotics/plant_disease_detection/sketch/sketch.ino b/CV_VR/IoT-Robotics/plant_disease_detection/sketch/sketch.ino new file mode 100644 index 0000000..7c80d25 --- /dev/null +++ b/CV_VR/IoT-Robotics/plant_disease_detection/sketch/sketch.ino @@ -0,0 +1,68 @@ +//===--sketch.ino----------------------------------------------------------===// +// Part of the Startup-Demos Project, under the MIT License +// See https://github.com/qualcomm/Startup-Demos/blob/main/LICENSE.txt +// for license information. +// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +//===----------------------------------------------------------------------===// + +#include +#include + +ModulinoBuzzer buzzer; + +// Buzzer control variables +unsigned long buzzerStartTime = 0; +bool buzzerActive = false; +const unsigned long BUZZER_DURATION = 5000; // 5 seconds in milliseconds +bool lastBuzzerTrigger = false; + +void setup() { + Serial.begin(115200); + + // Initialize Modulino + Modulino.begin(); + buzzer.begin(); + + // Initialize Bridge + Bridge.begin(); + + Serial.println("Plant Disease Detection System Initialized"); +} + +void loop() { + String detectionStatus; + bool statusOk = Bridge.call("get_detection_status").result(detectionStatus); + + // Check if buzzer should be triggered + bool shouldTrigger = false; + bool triggerOk = Bridge.call("should_trigger_buzzer").result(shouldTrigger); + + // Handle buzzer triggering + if (triggerOk && shouldTrigger && !lastBuzzerTrigger) { + // New detection - start buzzer + buzzerStartTime = millis(); + buzzerActive = true; + buzzer.tone(1000, BUZZER_DURATION); // 1000 Hz tone for 5 seconds + Serial.println("Buzzer activated - Disease detected!"); + } + + lastBuzzerTrigger = shouldTrigger; + + // Check if buzzer duration has elapsed + if (buzzerActive && (millis() - buzzerStartTime >= BUZZER_DURATION)) { + buzzerActive = false; + Serial.println("Buzzer deactivated"); + } + + // Print status for debugging + if (statusOk) { + static String lastStatus = ""; + if (detectionStatus != lastStatus) { + Serial.print("Detection Status: "); + Serial.println(detectionStatus); + lastStatus = detectionStatus; + } + } + + delay(100); // Small delay to prevent excessive polling +} diff --git a/README.md b/README.md index be06d68..816974f 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,9 @@ This repository is a collection of demo applications that highlight the capabili
Segmentation (ONNX) +
+ + Super Resolution (ONNX) โ€” @@ -97,6 +100,9 @@ This repository is a collection of demo applications that highlight the capabili
People Detection on IoT +
+ + Plant_Disease_Detection โ€” @@ -186,6 +192,9 @@ This repository is a collection of demo applications that highlight the capabili Object_detection_via_Tflite_model
+ + Plant_Disease_Detection +
Voice Enabled Gate Control System