Spaces:
Sleeping
Sleeping
import os | |
import cv2 | |
import gradio as gr | |
import numpy as np | |
from PIL import Image, ImageSequence | |
def image_to_sketch_gif(input_image: Image.Image): | |
# Convert PIL image to OpenCV format | |
open_cv_image = np.array(input_image.convert("RGB")) | |
open_cv_image = cv2.cvtColor(open_cv_image, cv2.COLOR_RGB2BGR) | |
# Convert to grayscale | |
grayscale_image = cv2.cvtColor(open_cv_image, cv2.COLOR_BGR2GRAY) | |
# Apply stronger Gaussian blur to smooth fine details | |
blurred_image = cv2.GaussianBlur(grayscale_image, (13, 13), 0) | |
# Use Canny Edge Detection with higher thresholds to detect only strong edges | |
edges = cv2.Canny(blurred_image, threshold1=100, threshold2=200) | |
# Dilate edges to make lines thicker | |
kernel = np.ones((5, 5), np.uint8) | |
edges = cv2.dilate(edges, kernel, iterations=1) | |
# Ensure binary format | |
_, binary_sketch = cv2.threshold(edges, 128, 255, cv2.THRESH_BINARY) | |
# Find connected components | |
num_labels, labels, stats, _ = cv2.connectedComponentsWithStats( | |
binary_sketch, connectivity=8 | |
) | |
# Sort components by size (excluding the background) and ignore very small ones | |
min_area = 250 # Minimum area to keep a component | |
components = sorted( | |
[ | |
(i, stats[i, cv2.CC_STAT_AREA]) | |
for i in range(1, num_labels) | |
if stats[i, cv2.CC_STAT_AREA] > min_area | |
], | |
key=lambda x: x[1], | |
reverse=True, | |
) | |
# Initialize an empty canvas for accumulation | |
accumulated_image = np.zeros_like(binary_sketch, dtype=np.uint8) | |
# Store frames | |
frames = [] | |
for label, _ in components: | |
# Add the current component to the accumulation | |
accumulated_image[labels == label] = 255 | |
# Convert OpenCV image to PIL image and append to frames | |
pil_frame = Image.fromarray(255 - accumulated_image) | |
frames.append(pil_frame.copy()) | |
if not frames: | |
# Handle edge case where no components remain | |
frames.append(Image.fromarray(255 - accumulated_image)) | |
return ( | |
frames[0], | |
frames, | |
gr.Slider( | |
value=len(frames) - 1, | |
maximum=len(frames) - 1, | |
), | |
gr.Button(interactive=False), | |
) | |