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)
|