File size: 2,248 Bytes
9aa82dd
 
 
 
 
 
 
 
 
870afd8
9aa82dd
 
 
 
 
 
 
870afd8
5448cf8
870afd8
 
77f0aab
9aa82dd
870afd8
 
 
9aa82dd
 
 
 
 
 
 
 
 
870afd8
 
9aa82dd
870afd8
 
 
 
 
9aa82dd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
870afd8
 
 
9aa82dd
 
 
 
 
505e263
9aa82dd
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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),
    )