Skip to content

Instantly share code, notes, and snippets.

@mhiramat
Last active May 4, 2020 23:14
Show Gist options
  • Save mhiramat/7fe0aaeb22f55e4772f4e963b5f26d88 to your computer and use it in GitHub Desktop.
Save mhiramat/7fe0aaeb22f55e4772f4e963b5f26d88 to your computer and use it in GitHub Desktop.
Face Detection and masking filter program with fake webcam
import cv2
import numpy
import pyfakewebcam as fakecam
import threading, queue
from time import sleep
imq = queue.Queue()
rectq = queue.Queue()
def faceDetector():
CASCADE_DIR = "/usr/share/opencv/haarcascades/" # Data path (maybe depends on your distro)
CASCADE_FILE = "haarcascade_frontalface_default.xml" # Face model data
cascade = cv2.CascadeClassifier(CASCADE_DIR + CASCADE_FILE)
# Noise reduction
px = 0
py = 0
while True:
sleep(0.1) # Reduce %CPU, keep cool, stay home.
img = imq.get()
if img is None:
break
gscale = cv2.cvtColor(sframe, cv2.COLOR_RGB2GRAY)
facerect = cascade.detectMultiScale(gscale)
if len(facerect) > 0:
max_rect = facerect[0]
for rect in facerect:
if rect[3] > max_rect[3]:
max_rect = rect
px = px*2/3 + max_rect[2]/3
py = py*2/3 + max_rect[3]/3
max_rect[2] = px
max_rect[3] = py
else:
max_rect = None
rectq.put(max_rect)
# Open capture source
videodev = "/dev/video1" # Change to your own video device
cap = cv2.VideoCapture(videodev)
height, width = 720, 1280 # 720p
cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
cap.set(cv2.CAP_PROP_FPS, 30)
# Open loopback device
v4l2loopback = "/dev/video20"
fake = fakecam.FakeWebcam(v4l2loopback, width, height)
# Read background image
bgfile = "./EVFe-qiUUAA1EuH.jpeg" # Change to your own image file
bgimg = cv2.imread(bgfile)
bgimg = cv2.resize(bgimg, (width, height))
# Sound only image (https://twitter.com/evangelion_co/status/1247883138849624069)
sofile = "./EVFe99XUMAoR28L.jpeg"
soimg = cv2.imread(sofile)
soimg = cv2.resize(soimg, (width, height))
# Start face detection thread
frect = None
t1 = threading.Thread(target = faceDetector)
t1.start()
while True:
success, frame = cap.read()
if imq.empty(): # Feed new image when worker is waiting
sframe = cv2.resize(frame, None, fx=0.25, fy=0.25)
imq.put(sframe)
if not rectq.empty(): # Update face rectangle
frect = rectq.get()
if frect is not None:
# Make a mask (simple ellipse mask)
center = int((frect[0] + frect[2]/2))*4, int(frect[1] + frect[3]/2.5)*4
size = int(frect[2])*2, int(frect[3])*3
mask = numpy.zeros((height, width, 3), numpy.uint8)
cv2.ellipse(mask, center, size, 0,0,360, (255,255,255), -1)
# Blend 2 images
frame = cv2.addWeighted(cv2.bitwise_and(frame, mask), 1.0,
cv2.bitwise_and(bgimg, cv2.bitwise_not(mask)), 1.0, 0)
else:
frame = soimg
# Zoom expects RGB and mirrored image
fake.schedule_frame(cv2.flip(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB), 1))
# showing result in window (and get key input)
cv2.imshow('camera capture', frame)
k = cv2.waitKey(10)
if k == 27:
break
imq.put(None)
t1.join()
cap.release()
cv2.destroyAllWindows()
@mhiramat
Copy link
Author

mhiramat commented May 4, 2020

This requires opencv and pyfakewebcam modules.

@mhiramat
Copy link
Author

mhiramat commented May 4, 2020

Note that we need to setup v4l2loopback before run.

sudo modprobe v4l2loopback devices=1 video_nr=20 card_label="v4l2loopback" exclusive_caps=1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment