File size: 4,093 Bytes
4bdc340
999ff86
4bdc340
 
999ff86
4bdc340
999ff86
9d68bbe
4bdc340
9d68bbe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4bdc340
 
9d68bbe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4bdc340
 
9d68bbe
 
 
 
 
4bdc340
9d68bbe
 
 
 
4bdc340
 
 
9d68bbe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import cv2
import gradio as gr
import numpy as np
from mtcnn_cv2 import MTCNN

detector = MTCNN()


def predict(img, selection):
    faces = detector.detect_faces(img)

    if selection == "Low":
        opts = (anonymize_face_pixelate, 20)
    elif selection == "Medium":
        opts = (anonymize_face_pixelate, 10)
    elif selection == "High":
        opts = (anonymize_face_pixelate, 4)
    elif selection == "Emoji":
        opts = (anonymize_face_emoji, "smiley")
    else:
        raise Exception("I don't know how you did it but you chose something else.")

    if len(faces) > 0:
        for features in faces:
            img = opts[0](img, features, opts[1])
    else:
        raise Exception("No faces detected")
    return img


def anonymize_face_pixelate(image, features, blocks=10):
    bb = features["box"]
    face_crop = image[bb[1] : bb[1] + bb[3], bb[0] : bb[0] + bb[2]]
    # Divide the input image into NxN blocks
    (h, w) = face_crop.shape[:2]
    xSteps = np.linspace(0, w, blocks + 1, dtype="int")
    ySteps = np.linspace(0, h, blocks + 1, dtype="int")

    # loop over the blocks in both x and y direction
    for i in range(1, len(ySteps)):
        for j in range(1, len(xSteps)):
            # compute starting and ending (x, y)-coordinates
            # for current block
            startX = xSteps[j - 1]
            startY = ySteps[i - 1]
            endX = xSteps[j]
            endY = ySteps[i]

            # Extract the ROI using NumPy array slicing, compute the
            # mean of the ROI, and then draw a rectangle with the
            # mean RGB values over the ROI in teh original image
            roi = face_crop[startY:endY, startX:endX]
            (B, G, R) = [int(x) for x in cv2.mean(roi)[:3]]
            cv2.rectangle(face_crop, (startX, startY), (endX, endY), (B, G, R), -1)

    image[bb[1] : bb[1] + bb[3], bb[0] : bb[0] + bb[2]] = face_crop
    return image


def anonymize_face_emoji(img, features, name="smiley"):
    bb = features["box"]
    (y, x) = (bb[1] + int(bb[3] / 2), bb[0] + int(bb[2] / 2))
    (h, w) = (bb[3], bb[2])
    # Get emoji with transparency
    mask = cv2.imread("raccoon_emoji.png", -1)

    mshape = max(h, w)
    offset = int(mshape / 2)

    return overlay_transparent(img, mask, x - offset, y - offset, (mshape, mshape))


def overlay_transparent(background_img, img_to_overlay_t, x, y, overlay_size=None):
    """
    @brief      Overlays a transparant PNG onto another image using CV2

    @param      background_img    The background image
    @param      img_to_overlay_t  The transparent image to overlay (has alpha channel)
    @param      x                 x location to place the top-left corner of our overlay
    @param      y                 y location to place the top-left corner of our overlay
    @param      overlay_size      The size to scale our overlay to (tuple), no scaling if None

    @return     Background image with overlay on top
    """

    bg_img = background_img.copy()

    if overlay_size is not None:
        img_to_overlay_t = cv2.resize(img_to_overlay_t.copy(), overlay_size)

    # Extract the alpha mask of the RGBA image, convert to RGB
    b, g, r, a = cv2.split(img_to_overlay_t)
    overlay_color = cv2.merge((b, g, r))

    # Apply some simple filtering to remove edge noise
    mask = cv2.medianBlur(a, 5)

    h, w, _ = overlay_color.shape
    roi = bg_img[y : y + h, x : x + w]

    # Black-out the area behind the logo in our original ROI
    img1_bg = cv2.bitwise_and(roi.copy(), roi.copy(), mask=cv2.bitwise_not(mask))

    # Mask out the logo from the logo image.
    img2_fg = cv2.bitwise_and(overlay_color, overlay_color, mask=mask)

    # Update the original image with our new ROI
    bg_img[y : y + h, x : x + w] = cv2.add(img1_bg, img2_fg)

    return bg_img


gr.Interface(
    fn=predict,
    inputs=[
        gr.components.Image(type="numpy"),
        gr.components.Radio(["Low", "Medium", "High", "Emoji"], value="Medium"),
    ],
    outputs=gr.components.Image(type="pil"),
    allow_flagging="never",
).launch(show_error=True, quiet=False)