import gradio as gr import cv2 import numpy as np from PIL import Image import io import os import tempfile def image_to_line_art_svg(image, line_thickness=2, blur_value=7, threshold_value=7): """ Convert an image to line art and return as SVG """ try: # Ensure blur_value and threshold_value are odd blur_value = blur_value if blur_value % 2 == 1 else blur_value + 1 threshold_value = threshold_value if threshold_value % 2 == 1 else threshold_value + 1 # Convert PIL image to numpy array if isinstance(image, Image.Image): image_array = np.array(image.convert('RGB')) else: image_array = image # Resize image if too large (to prevent memory issues) height, width = image_array.shape[:2] max_dimension = 1024 if max(height, width) > max_dimension: scale = max_dimension / max(height, width) new_width = int(width * scale) new_height = int(height * scale) image_array = cv2.resize(image_array, (new_width, new_height)) height, width = new_height, new_width # Convert to grayscale gray = cv2.cvtColor(image_array, cv2.COLOR_RGB2GRAY) # Apply median filter to reduce noise gray_blur = cv2.medianBlur(gray, blur_value) # Create an edge mask using adaptive threshold edges = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, threshold_value, blur_value) # Convert edges back to 3-channel for display edges_colored = cv2.cvtColor(edges, cv2.COLOR_GRAY2RGB) # Invert edges so lines are black on white background edges = cv2.bitwise_not(edges) # Find contours contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # Create SVG content svg_content = f''' ' return svg_content, edges_colored except Exception as e: # Return error SVG error_svg = f''' ''' error_image = np.ones((200, 400, 3), dtype=np.uint8) * 255 return error_svg, error_image def process_image(image, line_thickness, blur_value, threshold_value): """ Process the uploaded image and return both SVG content and preview image """ if image is None: return None, None, "❌ Please upload an image first." try: svg_content, preview_image = image_to_line_art_svg( image, line_thickness, blur_value, threshold_value ) # Create temporary file for SVG download temp_dir = tempfile.gettempdir() svg_path = os.path.join(temp_dir, "line_art.svg") with open(svg_path, "w", encoding="utf-8") as f: f.write(svg_content) return preview_image, svg_path, "✅ Conversion completed successfully!" except Exception as e: error_image = np.ones((200, 400, 3), dtype=np.uint8) * 255 return error_image, None, f"❌ Error processing image: {str(e)}" # Create Gradio interface with gr.Blocks( title="Image to Line Art SVG Converter", theme=gr.themes.Soft(), css=""" .gradio-container { max-width: 1200px !important; } """ ) as demo: gr.HTML("""
Convert your images into beautiful line art and download as scalable SVG files!