Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

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.

Please let me know if you have any ideas.

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.

Please let me know if you have any ideas.

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. image description

Please let me know if you have any ideas.

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. image description

The result would be something like this. image description

Please let me know if you have any ideas.