From 3711928c7de4d80756cd4f637ae75118f1bfb3b9 Mon Sep 17 00:00:00 2001 From: Matthias Guillitte Date: Sun, 23 Aug 2026 12:33:39 +0200 Subject: [PATCH] Enhance image before ai processing --- cloud/app.py | 27 ++++++++++++++++++++++++--- cloud/image_enhancer.py | 23 +++++++++++++++++++++++ cloud/safety_checker.py | 16 ++++++++++++++++ 3 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 cloud/image_enhancer.py diff --git a/cloud/app.py b/cloud/app.py index 3cd90da..ea499e5 100644 --- a/cloud/app.py +++ b/cloud/app.py @@ -17,6 +17,7 @@ from APIs.mqtt import send_command from APIs.webex import WebexManager from APIs.shodan import ShodanAuditor from APIs.twilio import send_alert_sms +from cloud.image_enhancer import enhance_image_for_ai from microwaveCookPlanner import MicrowaveCookPlanner import safety_checker from jobs import job_server_cve_audit, job_client_ip_audit, job_request_telemetry @@ -153,7 +154,7 @@ start_scheduler_once() # --------------------------------------------------------- # Authentication Middleware # --------------------------------------------------------- -EXEMPT_ROUTES = {'hello_world', 'oauth_callback', 'odata_metadata', 'debug_telemetryrequest', 'trigger_job_manually'} +EXEMPT_ROUTES = {'hello_world', 'oauth_callback', 'odata_metadata', 'debug_telemetryrequest', 'trigger_job_manually', 'debug_unsafe_dish', 'debug_safe_dish'} @app.before_request def authenticate_request(): @@ -245,12 +246,14 @@ async def cooking_params(): with open(filepath, "wb") as f: f.write(base64.b64decode(camera_image_b64)) data["camera_image"] = filepath + + enhanced_filepath = enhance_image_for_ai(filepath) # Concurrent AI Execution - safety_task = asyncio.to_thread(safety_checker.check_dish_safety, filepath) + safety_task = asyncio.to_thread(safety_checker.check_dish_safety, enhanced_filepath) planner_task = asyncio.to_thread( microwave_cook_planner.generate_plan, - image_path=filepath, + image_path=enhanced_filepath, height_cm=height_cm, initial_temp_c=initial_temp_c, microwave_wattage=microwave_wattage, @@ -584,6 +587,24 @@ def trigger_job_manually(job_id): "status": "error", "message": f"Job execution failed: {str(e)}" }), 500 + +@app.route("/debug/dishsafety/not_safe", methods=["GET"]) +def debug_unsafe_dish(): + """Debug endpoint to simulate an unsafe dish scenario.""" + # Simulated unsafe dish data + unsafe_dish = "storage/dishPhotos/dish_78827473286c4f67855f3fbd0ccb9bb4.jpg" + + # Call the cooking_params endpoint logic directly + return safety_checker.check_dish_safety(unsafe_dish) + +@app.route("/debug/dishsafety/safe", methods=["GET"]) +def debug_safe_dish(): + """Debug endpoint to simulate a safe dish scenario.""" + # Simulated safe dish data + unsafe_dish = "storage/dishPhotos/dish_972251744d034b32bb5134ff9d0f071c.jpg" + + # Call the cooking_params endpoint logic directly + return safety_checker.check_dish_safety(unsafe_dish) # --------------------------------------------------------- # OData Metadata Definition diff --git a/cloud/image_enhancer.py b/cloud/image_enhancer.py new file mode 100644 index 0000000..d8790bc --- /dev/null +++ b/cloud/image_enhancer.py @@ -0,0 +1,23 @@ +import cv2 + +def enhance_image_for_ai(input_path: str) -> str: + """Enhances dark areas and contrast using CLAHE without blowing out bright areas.""" + img = cv2.imread(input_path) + if img is None: + return input_path + + # Convert to LAB color space to modify luminance channel only + lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB) + l, a, b = cv2.split(lab) + + # Apply CLAHE to Lightness channel + clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8)) + cl = clahe.apply(l) + + # Merge channels and convert back to BGR + limg = cv2.merge((cl, a, b)) + enhanced = cv2.cvtColor(limg, cv2.COLOR_LAB2BGR) + + enhanced_path = input_path.replace(".jpg", "_enhanced.jpg") + cv2.imwrite(enhanced_path, enhanced) + return enhanced_path \ No newline at end of file diff --git a/cloud/safety_checker.py b/cloud/safety_checker.py index 16ec5ec..432f6c1 100644 --- a/cloud/safety_checker.py +++ b/cloud/safety_checker.py @@ -2,6 +2,7 @@ import json from pydantic import BaseModel, Field from APIs.aichat import generate import shared.config as config +from PIL import Image, ImageEnhance class UtensilMaterialCheck(BaseModel): object_name: str = Field( @@ -28,6 +29,21 @@ class DishSafetyResult(BaseModel): description="If is_safe is False, set to 'REMOVE METAL UTENSIL OR FOIL BEFORE MICROWAVING'. Otherwise empty ''." ) +def preprocess_dish_image(image_path: str) -> str: + """Brightens dark areas and sharpens food texture for small vision models.""" + img = Image.open(image_path) + + # 1. Boost brightness slightly + enhancer = ImageEnhance.Brightness(img) + img = enhancer.enhance(1.4) + + # 2. Boost contrast to separate food shapes from dark shadows + enhancer = ImageEnhance.Contrast(img) + img = enhancer.enhance(1.3) + + processed_path = "/tmp/processed_dish.jpg" + img.save(processed_path, quality=85) + return processed_path def check_dish_safety(image_path: str) -> dict: prompt = (