1

I've been working on a project to get the forehead area from a live streaming video and not just use and image and crop the forehead like from this example How can i detect the forehead region using opencv and dlib?.

cap = cv2.VideoCapture(0)

detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(predict_path)


while True:
    _, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    faces = detector(gray) #detects number of faces present

    for face in faces:
        x1 = face.left()
        y1 = face.top()
        x2 = face.right()
        y2 = face.bottom()
        
        cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 3)
        
        landmarks = predictor(gray, face)

        for n in range(68, 81):
            x = landmarks.part(n).x
            y = landmarks.part(n).y

            cv2.circle(frame, (x, y), 4, (0, 255, 0), -1) 
            

I managed to get the forehead region using the landmarks of using https://github.com/codeniko/shape_predictor_81_face_landmarks/blob/master/shape_predictor_81_face_landmarks.dat

But what I need is the rectangle bounding box onto where the landmark is at detecting the forehead region. Is this possible to get? If not, what should I do to get the forehead region. Thanks in advance.

nam
  • 116
  • 1
  • 10

1 Answers1

1

you already find the desired coordinates by:

for face in faces:
    x1 = face.left()
    y1 = face.top()
    x2 = face.right()
    y2 = face.bottom()

    cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 3)

But what I need is the rectangle bounding box onto where the landmark is at detecting the forehead region.

Then change the y-coordinates:

cv2.rectangle(frame, (x1, y1-100), (x2, y2-100), (0, 0, 255), 3)

Update

To stick to the forehead points, we need to get minimum and maximum landmark coordinates, then we need to draw rectangle.

Step1: Getting coordinates:


    1. Initialize x_pts and y_pts
    1. Store landmark(n) points into the arrays.
for n in range(68, 81):
    x = landmarks.part(n).x
    y = landmarks.part(n).y

    x_pts.append(x)
    y_pts.append(y)

    cv2.circle(frame, (x, y), 4, (0, 255, 0), -1)

Step 2: Drawing the rectangle around detected points


    1. Get Minimum and Maximum points
x1 = min(x_pts)
x2 = max(x_pts)
y1 = min(y_pts)
y2 = max(y_pts)

cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 3)

Result:

When I zoom to the webcam:

enter image description here

When I'm far away:

enter image description here

Code:

import cv2
import dlib

cap = cv2.VideoCapture(0)

detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_81_face_landmarks.dat")

while True:
    _, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    faces = detector(gray)  # detects number of faces present

    for face in faces:
        x1 = face.left()
        y1 = face.top()
        x2 = face.right()
        y2 = face.bottom()

        landmarks = predictor(gray, face)

        x_pts = []
        y_pts = []

        for n in range(68, 81):
            x = landmarks.part(n).x
            y = landmarks.part(n).y

            x_pts.append(x)
            y_pts.append(y)

            cv2.circle(frame, (x, y), 4, (0, 255, 0), -1)

        x1 = min(x_pts)
        x2 = max(x_pts)
        y1 = min(y_pts)
        y2 = max(y_pts)

        cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 3)

    cv2.imshow("out", frame)
    key = cv2.waitKey(1) & 0xFF

    # if the `q` key was pressed, break from the loop
    if key == ord("q"):
        break
Ahmet
  • 7,527
  • 3
  • 23
  • 47
  • Yeah, I guess I was stuck there and had no idea how to do it. But thanks for the answer! It did solve what I had asked for. However the box changes its position whenever we go closer/further from the camera. Any idea how to fix that? – nam Sep 07 '20 at 06:30
  • It works if I was closer to the camera and the box does not stay on the forehead when we are far from the camera.. :( – nam Sep 07 '20 at 06:34
  • Ok, then the constant parameter `-100` should be dynamic, let me work on that.. – Ahmet Sep 07 '20 at 06:35
  • I will return back to you once I found the solution, I'm now working on it – Ahmet Sep 07 '20 at 06:36
  • Please replace previous with this one: `cv2.rectangle(frame, (x1 - int(x1 * 0.1), y1 - int(y1*0.5)), (x2 + int(x1 * 0.1), y2), (0, 0, 255), 3)` – Ahmet Sep 07 '20 at 06:57
  • Somehow when use the new line you gave, and I change the parameter values to get only the forehead, it still does not stick to the forehead. I'm also trying different values to get the forehead and only detects the forehead even when object is far – nam Sep 07 '20 at 07:10
  • I have another idea, let me try that one – Ahmet Sep 07 '20 at 07:17
  • I think I solved or close to the solution this time. Please check out my update part of my answer. – Ahmet Sep 07 '20 at 07:43