Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, UploadFile, File | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import JSONResponse | |
| import numpy as np | |
| import cv2 | |
| import io | |
| import base64 | |
| from PIL import Image | |
| import image_processing | |
| app = FastAPI( | |
| title="Soil Image Classification API", | |
| description="Classifies soil images based on visual features or segmented regions.", | |
| version="1.0" | |
| ) | |
| # Allow CORS (helpful for frontend dev) | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], # You can restrict this to your frontend domain | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Convert image bytes to OpenCV format | |
| def read_imagefile(image_bytes): | |
| image = Image.open(io.BytesIO(image_bytes)).convert("RGB") | |
| return cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) | |
| # Encode image (OpenCV format) to base64 | |
| def encode_image_to_base64(image): | |
| _, buffer = cv2.imencode('.jpg', image) | |
| return base64.b64encode(buffer).decode('utf-8') | |
| def root(): | |
| return {"message": "Soil Image Classifier API is running."} | |
| # Whole image prediction | |
| async def predict_image(file: UploadFile = File(...)): | |
| try: | |
| image_bytes = await file.read() | |
| image = read_imagefile(image_bytes) | |
| features_df, predicted_class, confidence = image_processing.predict_image_class_with_features( | |
| cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | |
| ) | |
| return { | |
| "predicted_class": predicted_class, | |
| "confidence": float(confidence), | |
| "features": features_df.to_dict(orient="records")[0] | |
| } | |
| except Exception as e: | |
| return JSONResponse(status_code=500, content={"error": str(e)}) | |
| # Region-based prediction | |
| async def predict_regions(file: UploadFile = File(...), k_clusters: int = 2): | |
| try: | |
| image_bytes = await file.read() | |
| image = read_imagefile(image_bytes) | |
| segmented_image, region_predictions = image_processing.segment_and_classify_regions( | |
| cv2.cvtColor(image, cv2.COLOR_BGR2RGB), | |
| k_clusters=k_clusters | |
| ) | |
| base64_segmented = encode_image_to_base64(cv2.cvtColor(segmented_image, cv2.COLOR_BGR2RGB)) | |
| results = [] | |
| for region in region_predictions: | |
| results.append({ | |
| "class": region["class"], | |
| "confidence": float(region["confidence"]), | |
| "bbox": { | |
| "x": region["bbox"][0], | |
| "y": region["bbox"][1], | |
| "width": region["bbox"][2], | |
| "height": region["bbox"][3], | |
| } | |
| }) | |
| return { | |
| "region_count": len(results), | |
| "regions": results, | |
| "segmented_image_base64": base64_segmented | |
| } | |
| except Exception as e: | |
| return JSONResponse(status_code=500, content={"error": str(e)}) | |
| def home(): | |
| return {"message": "FastAPI is running on Hugging Face Spaces!"} | |