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

112 lines
3.3 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, status
from sqlalchemy.orm import Session
from typing import List
from pathlib import Path
from app.db.session import get_db
from app.db.crud_tomato import tomato_image
from app.schemas.tomato import TomatoImage, TomatoImageCreate, UploadResponse
from app.utils.image import save_uploaded_image
from app.core.config import settings
router = APIRouter()
@router.post("/upload", response_model=UploadResponse, status_code=status.HTTP_201_CREATED)
async def upload_tomato_image(
file: UploadFile = File(...),
db: Session = Depends(get_db)
):
"""
Upload a tomato image for analysis.
The image will be saved and registered in the database.
It can then be analyzed using the analysis endpoint.
"""
# Validate file type
if file.content_type not in settings.ALLOWED_IMAGE_TYPES:
raise HTTPException(
status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,
detail=f"Unsupported file type: {file.content_type}. Allowed types: {', '.join(settings.ALLOWED_IMAGE_TYPES)}"
)
# Read file content
contents = await file.read()
# Validate file size
if len(contents) > settings.MAX_IMAGE_SIZE:
raise HTTPException(
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
detail=f"File too large. Maximum size allowed: {settings.MAX_IMAGE_SIZE / (1024 * 1024)}MB"
)
# Save file and get metadata
image_data = save_uploaded_image(contents, file.filename)
# Create database record
image_in = TomatoImageCreate(**image_data)
db_image = tomato_image.create(db=db, obj_in=image_in)
return UploadResponse(
image=db_image,
message="Image uploaded successfully"
)
@router.get("/", response_model=List[TomatoImage])
def list_tomato_images(
skip: int = 0,
limit: int = 100,
db: Session = Depends(get_db)
):
"""
List all uploaded tomato images.
"""
images = tomato_image.get_multi(db=db, skip=skip, limit=limit)
return images
@router.get("/{image_id}", response_model=TomatoImage)
def get_tomato_image(
image_id: str,
db: Session = Depends(get_db)
):
"""
Get a specific tomato image by ID.
"""
db_image = tomato_image.get(db=db, id=image_id)
if db_image is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Image not found"
)
return db_image
@router.delete("/{image_id}", status_code=status.HTTP_204_NO_CONTENT, response_model=None)
def delete_tomato_image(
image_id: str,
db: Session = Depends(get_db)
):
"""
Delete a tomato image and its associated data.
"""
db_image = tomato_image.get(db=db, id=image_id)
if db_image is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Image not found"
)
# Delete the image file
try:
if db_image.file_path and Path(db_image.file_path).exists():
Path(db_image.file_path).unlink()
except Exception:
# Log error but continue with database deletion
pass
# Delete database record (cascade will handle related records)
tomato_image.remove(db=db, id=image_id)
return None