
- 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
69 lines
2.7 KiB
Python
69 lines
2.7 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
from sqlalchemy import Column, String, DateTime, Float, Text, ForeignKey, Integer
|
|
from sqlalchemy.orm import relationship
|
|
from app.db.session import Base
|
|
|
|
|
|
class TomatoImage(Base):
|
|
__tablename__ = "tomato_images"
|
|
|
|
id = Column(String(36), primary_key=True, index=True, default=lambda: str(uuid.uuid4()))
|
|
filename = Column(String(255), nullable=False)
|
|
file_path = Column(String(512), nullable=False, unique=True)
|
|
file_size = Column(Integer, nullable=False)
|
|
mime_type = Column(String(50), nullable=False)
|
|
width = Column(Integer, nullable=True)
|
|
height = Column(Integer, nullable=True)
|
|
|
|
uploaded_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
|
|
# Relationships
|
|
analysis_results = relationship("AnalysisResult", back_populates="image", cascade="all, delete-orphan")
|
|
|
|
def __repr__(self):
|
|
return f"<TomatoImage {self.filename}>"
|
|
|
|
|
|
class AnalysisResult(Base):
|
|
__tablename__ = "analysis_results"
|
|
|
|
id = Column(String(36), primary_key=True, index=True, default=lambda: str(uuid.uuid4()))
|
|
image_id = Column(String(36), ForeignKey("tomato_images.id", ondelete="CASCADE"), nullable=False)
|
|
model_name = Column(String(255), nullable=False)
|
|
model_version = Column(String(50), nullable=False)
|
|
|
|
# Overall severity data
|
|
primary_severity = Column(String(50), nullable=True)
|
|
severity_confidence = Column(Float, nullable=True)
|
|
|
|
# Segmentation data (stored as JSON string)
|
|
segmentation_data = Column(Text, nullable=True)
|
|
|
|
# Additional metadata
|
|
processed_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
|
processing_time_ms = Column(Integer, nullable=True)
|
|
|
|
# Relationships
|
|
image = relationship("TomatoImage", back_populates="analysis_results")
|
|
severity_details = relationship("SeverityDetail", back_populates="analysis_result", cascade="all, delete-orphan")
|
|
|
|
def __repr__(self):
|
|
return f"<AnalysisResult {self.id} for image {self.image_id}>"
|
|
|
|
|
|
class SeverityDetail(Base):
|
|
__tablename__ = "severity_details"
|
|
|
|
id = Column(String(36), primary_key=True, index=True, default=lambda: str(uuid.uuid4()))
|
|
analysis_id = Column(String(36), ForeignKey("analysis_results.id", ondelete="CASCADE"), nullable=False)
|
|
|
|
severity_class = Column(String(50), nullable=False)
|
|
confidence = Column(Float, nullable=False)
|
|
affected_area_percentage = Column(Float, nullable=True)
|
|
|
|
# Relationships
|
|
analysis_result = relationship("AnalysisResult", back_populates="severity_details")
|
|
|
|
def __repr__(self):
|
|
return f"<SeverityDetail {self.severity_class} ({self.confidence:.2f})>" |