import cv2 import numpy as np from PIL import Image import gradio as gr def sharpen_image(img: Image.Image, strength: float = 1.0) -> Image.Image: """ Apply sharpening to an image using OpenCV's unsharp masking technique. Args: img: Input PIL Image strength: Sharpening intensity (0.0 to 3.0) Returns: Sharpened PIL Image """ # Handle different image modes if img.mode not in ['L', 'RGB']: img = img.convert('RGB') original_mode = 'RGB' else: original_mode = img.mode # Convert PIL Image to numpy array img_array = np.array(img) try: # Convert to BGR format for OpenCV processing if original_mode == 'L': img_bgr = cv2.cvtColor(img_array, cv2.COLOR_GRAY2BGR) else: img_bgr = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR) # Apply Gaussian Blur blurred = cv2.GaussianBlur(img_bgr, (0, 0), 3) # Unsharp masking sharpened = cv2.addWeighted(img_bgr, 1.0 + strength, blurred, -strength, 0) sharpened = np.clip(sharpened, 0, 255).astype(np.uint8) # Convert back to original color space if original_mode == 'L': processed = cv2.cvtColor(sharpened, cv2.COLOR_BGR2GRAY) else: processed = cv2.cvtColor(sharpened, cv2.COLOR_BGR2RGB) except Exception as e: raise gr.Error(f"Image processing failed: {str(e)}") return Image.fromarray(processed, mode=original_mode) # Gradio interface with gr.Blocks(theme=gr.themes.Soft()) as app: gr.Markdown("# 🔍 Image Sharpening Tool") with gr.Row(): with gr.Column(): input_image = gr.Image(type="pil", label="Original Image", sources=["upload"]) strength_slider = gr.Slider( minimum=0.0, maximum=3.0, value=1.0, step=0.1, label="Sharpening Strength", info="Adjust between 0.0 (no effect) to 3.0 (strongest)" ) process_btn = gr.Button("Process Image", variant="primary") output_image = gr.Image(type="pil", label="Sharpened Image", interactive=False) # Example section gr.Examples( examples=[ ["https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", 1.2], ["https://upload.wikimedia.org/wikipedia/commons/thumb/4/41/Sunflower_from_Silesia2.jpg/1280px-Sunflower_from_Silesia2.jpg", 1.5] ], inputs=[input_image, strength_slider], outputs=output_image, fn=sharpen_image, cache_examples=True ) # Event handling process_btn.click( fn=sharpen_image, inputs=[input_image, strength_slider], outputs=output_image ) if __name__ == "__main__": app.launch(show_error=True)