import numpy as np import gradio as gr import cv2 # OpenCV for face detection from skimage import color from sklearn.decomposition import TruncatedSVD from concurrent.futures import ThreadPoolExecutor from PIL import Image # Detect faces using OpenCV def detect_faces(image_np): """Detect faces in the image and return their bounding boxes.""" gray_image = cv2.cvtColor(image_np, cv2.COLOR_RGB2GRAY) face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') faces = face_cascade.detectMultiScale(gray_image, scaleFactor=1.1, minNeighbors=5) return faces # Compress the image using Truncated SVD for faster performance def truncated_svd_compress(image, k): """Compress the image using Truncated SVD by keeping only the top k singular values.""" svd = TruncatedSVD(n_components=k) U = svd.fit_transform(image) S = svd.singular_values_ Vt = svd.components_ compressed_image = np.dot(U, np.dot(np.diag(S), Vt)) return compressed_image # Process the image asynchronously for smoother user experience async def process_image_async(image, k): """Asynchronous image processing to avoid blocking.""" return await asyncio.to_thread(process_image, image, k) # Main image processing function def process_image(image, k): """Process the uploaded image, detect faces, and compress it using Truncated SVD.""" # Convert PIL Image to NumPy array image_np = np.array(image) # Detect faces in the image faces = detect_faces(image_np) # If faces are detected, highlight the regions (optional) if len(faces) > 0: for (x, y, w, h) in faces: cv2.rectangle(image_np, (x, y), (x+w, y+h), (255, 0, 0), 2) # Convert the image to grayscale gray_image = color.rgb2gray(image_np) # Compress the image compressed_image = truncated_svd_compress(gray_image, k) # Convert compressed image back to PIL Image for Gradio output compressed_image_pil = Image.fromarray((compressed_image * 255).astype(np.uint8)) return compressed_image_pil # Gradio interface gr_interface = gr.Interface( fn=process_image, # Image processing function inputs=[ gr.Image(type="pil", label="Upload Image"), gr.Slider(1, 100, step=1, value=50, label="Compression Rank") # Compression rank slider ], outputs=gr.Image(type="pil", label="Compressed Image"), title="Fast Interactive Image Compression with Face Detection", description="Upload an image and adjust the compression rank. The app detects faces and compresses the image using Truncated SVD for faster processing." ) # Launch the Gradio interface gr_interface.launch()