File size: 3,034 Bytes
735d318
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a1086da
735d318
 
 
 
 
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
import gradio as gr
import cv2
import numpy as np


class ImageToSketchEffect:
    """Transform an image to mimic the effect of a sketch drawn with a pencil."""

    def __init__(
            self,
            blur_strength: int = 5,
            blur_kernel_size: tuple = (0, 0),
            edge_enhance_level: int = None,
            custom_sharpen_kernel: np.ndarray = None,
    ):
        self.blur_strength = blur_strength
        self.blur_kernel_size = blur_kernel_size
        self.edge_enhance_level = edge_enhance_level
        self.sharpen_kernel = np.array([[0, -1, 0], [-1, edge_enhance_level, -1],
                                        [0, -1, 0]]) if custom_sharpen_kernel is None else custom_sharpen_kernel

    def blend_mode_dodge(self, top_layer: np.ndarray, bottom_layer: np.ndarray) -> np.ndarray:
        output = bottom_layer * 255.0 / (255.0 - top_layer)
        output[output > 255] = 255
        output[bottom_layer == 255] = 255
        return output.astype('uint8')

    def enhance_edges(self, img: np.ndarray) -> np.ndarray:
        if self.edge_enhance_level is not None and isinstance(self.edge_enhance_level, int):
            inverse_image = 255 - img
            return 255 - cv2.filter2D(src=inverse_image, ddepth=-1, kernel=self.sharpen_kernel)
        return img

    def apply_sketch_effect(self, image: np.ndarray) -> (np.ndarray, np.ndarray):
        grayscale_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        inverted_image = 255 - grayscale_image
        blurred_image = cv2.GaussianBlur(inverted_image, ksize=self.blur_kernel_size, sigmaX=self.blur_strength)
        sketch_image = self.blend_mode_dodge(blurred_image, grayscale_image)
        sketch_image = self.enhance_edges(sketch_image)
        blurred_for_alpha = cv2.GaussianBlur(sketch_image, (5, 5), 0)
        if len(blurred_for_alpha.shape) == 3 and blurred_for_alpha.shape[2] == 3:
            blurred_for_alpha = cv2.cvtColor(blurred_for_alpha, cv2.COLOR_BGR2GRAY)
        _, alpha_mask = cv2.threshold(blurred_for_alpha, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

        final_sketch_transparent = cv2.merge((blurred_for_alpha, blurred_for_alpha, blurred_for_alpha, alpha_mask))

        return sketch_image, final_sketch_transparent


def process_image(image, blur_strength, blur_kernel_size, edge_enhance_level):
    sketch_effect = ImageToSketchEffect(blur_strength, (blur_kernel_size, blur_kernel_size), edge_enhance_level)
    return sketch_effect.apply_sketch_effect(image)


iface = gr.Interface(fn=process_image,
                     inputs=[gr.Image(), gr.Slider(1, 10, value=7), gr.Slider(3, 25, step=2, value=15),
                             gr.Slider(1, 10, value=7)],
                     outputs=[gr.Image(type="numpy", label="Pencil Sketch"),gr.Image(type="numpy", label="Transparent Pencil Sketch")],
                     title="Image to Sketch Converter",
                     description="Upload an image to convert it into a pencil sketch.")

if __name__ == "__main__":
    iface.launch()