Mask out face from image with OpenCV
Hi, I am trying to use OpenCV to extract only the face on a image but I don't want any of the background in my image (I only want the actual face contour). I tried to detect a face and extract the ROI and pass that to a skin detector algorithm but the latter step fails for the most part.
import cv2
import numpy as np
import sys
cascPath = sys.argv[1]
faceCascade = cv2.CascadeClassifier(cascPath)
lower = np.array([0, 48, 80], dtype = "uint8")
upper = np.array([20, 255, 255], dtype = "uint8")
video_capture = cv2.VideoCapture(0)
def face_detect():
while True:
# Capture frame-by-frame
ret, frame = video_capture.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30),
flags=cv2.CASCADE_SCALE_IMAGE
)
# Draw a rectangle around the faces
for (x, y, w, h) in faces:
#face_region = cv2.GetSubRect(image,(x, y, x+w, y+h))
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
face_region = frame[y:y+h, x:x+w]
converted = cv2.cvtColor(face_region, cv2.COLOR_BGR2HSV)
skinMask = cv2.inRange(converted, lower, upper)
# apply a series of erosions and dilations to the mask
# using an elliptical kernel
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11, 11))
skinMask = cv2.erode(skinMask, kernel, iterations = 2)
skinMask = cv2.dilate(skinMask, kernel, iterations = 2)
# blur the mask to help remove noise, then apply the
# mask to the frame
skinMask = cv2.GaussianBlur(skinMask, (3, 3), 0)
skin = cv2.bitwise_and(face_region, face_region, mask = skinMask)
cv2.imshow("Face", np.hstack([face_region, skin]))
# Further processing on only the face without the background.
#cv2.ellipse(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
# Display the resulting frame
cv2.imshow('Video', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
return
face_detect()
video_capture.release()
cv2.destroyAllWindows()
Is there a better approach to extract the face? Maybe there is a way to select the most common colours and threshold that and apply the mask on to my image.
So I would like to like to segment the face provided by guidelines such as the ones below using OpenCV instead.
The result would be something like this.
Please let me know if you have any ideas.
http://www.morethantechnical.com/2010...
@sturkmen Thank you that seems like it could work, although if possible I'd like to extract only the facial part like demonstrated in this picture but with OpenCV.
see also http://life-in-a-monospace-typeface.t... i just googled "face swap opencv"
@sturkmen Thanks, but it uses the obsolete API and I use opencv 3.0, however I will have a look at it.