Automated Action ab0e9b973a Implement tomato severity segmentation model API
- Set up FastAPI project structure with SQLite database
- Create database models for tomato images and severity classifications
- Implement image upload and processing endpoints
- Develop a segmentation model for tomato disease severity detection
- Add API endpoints for analysis and results retrieval
- Implement health check endpoint
- Set up Alembic for database migrations
- Update project documentation
2025-05-27 06:22:15 +00:00

148 lines
5.6 KiB
Python

import numpy as np
import cv2
import time
from typing import Dict, Optional, Any
from app.core.config import settings
from app.utils.image import load_image, resize_image, normalize_image
class TomatoSegmentationModel:
"""
Model for tomato disease severity segmentation.
This class implements a simple image segmentation model using
conventional computer vision techniques as a placeholder.
In a production scenario, this would be replaced with a proper
deep learning model like U-Net, DeepLabV3, etc.
"""
def __init__(self):
self.model_name = settings.DEFAULT_MODEL_NAME
self.model_version = "0.1.0"
self.severity_classes = settings.SEVERITY_CLASSES
self.input_size = (224, 224) # Standard input size
def preprocess_image(self, image_path: str) -> Optional[np.ndarray]:
"""Preprocess an image for analysis."""
# Load image
image = load_image(image_path)
if image is None:
return None
# Resize
image = resize_image(image, self.input_size)
# Normalize
image = normalize_image(image)
return image
def analyze_image(self, image_path: str) -> Dict[str, Any]:
"""
Analyze a tomato image to determine disease severity.
Args:
image_path: Path to the image file
Returns:
Dictionary with analysis results including segmentation masks and severity scores
"""
start_time = time.time()
# Preprocess image
image = self.preprocess_image(image_path)
if image is None:
return {
"error": "Failed to load or process image",
"success": False
}
# Simple color-based segmentation to identify potential disease areas
# This is a simplified placeholder implementation
# Convert back to BGR for OpenCV
image_bgr = (image * 255).astype(np.uint8)
image_bgr = cv2.cvtColor(image_bgr, cv2.COLOR_RGB2BGR)
# Convert to HSV for better color segmentation
image_hsv = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2HSV)
# Define color ranges for different severity classes
# These are placeholder values and would need to be calibrated for real use
color_ranges = {
"healthy": [(35, 50, 50), (85, 255, 255)], # Green healthy leaves
"early_blight": [(15, 50, 50), (35, 255, 255)], # Yellowish
"late_blight": [(0, 50, 50), (15, 255, 255)], # Reddish-brown
"bacterial_spot": [(0, 0, 0), (180, 50, 100)], # Dark spots
"septoria_leaf_spot": [(0, 0, 100), (180, 50, 255)] # Light spots
}
# Create segmentation masks and calculate affected areas
masks = {}
severity_details = []
total_pixels = image.shape[0] * image.shape[1]
for severity_class, (lower, upper) in color_ranges.items():
# Create mask for this color range
lower = np.array(lower, dtype=np.uint8)
upper = np.array(upper, dtype=np.uint8)
mask = cv2.inRange(image_hsv, lower, upper)
# Apply morphological operations to clean up the mask
kernel = np.ones((5, 5), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
# Calculate affected area percentage
affected_pixels = np.count_nonzero(mask)
affected_percentage = (affected_pixels / total_pixels) * 100
# Generate a random confidence score for demo purposes
# In a real model, this would be the model's actual confidence
confidence = min(affected_percentage / 50, 1.0)
if severity_class == "healthy" and affected_percentage < 10:
confidence = 0.9 # Boost confidence for low healthy area (likely diseased)
# Store results
masks[severity_class] = mask.tolist() # Convert to list for JSON serialization
severity_details.append({
"severity_class": severity_class,
"confidence": float(confidence),
"affected_area_percentage": float(affected_percentage)
})
# Determine primary severity class
severity_details.sort(key=lambda x: x["confidence"], reverse=True)
primary_severity = severity_details[0]["severity_class"]
severity_confidence = severity_details[0]["confidence"]
# If healthy has high confidence, it takes precedence
for detail in severity_details:
if detail["severity_class"] == "healthy" and detail["confidence"] > 0.7:
primary_severity = "healthy"
severity_confidence = detail["confidence"]
break
# Prepare results
processing_time = int((time.time() - start_time) * 1000) # ms
result = {
"success": True,
"model_name": self.model_name,
"model_version": self.model_version,
"primary_severity": primary_severity,
"severity_confidence": severity_confidence,
"severity_details": severity_details,
"segmentation_data": {
"image_size": self.input_size,
"masks": masks
},
"processing_time_ms": processing_time
}
return result
# Singleton instance
segmentation_model = TomatoSegmentationModel()