首页 > 解决方案 > 如何使用凸包多边形裁剪面部区域

问题描述

我正在使用 dlib 库中的地标点根据以下问题从我的脸上选择前额、鼻子和眼睛区域:Is there a way to get the area of​​ the fronthead (bounding box) by using opencv/dlib and for a live stream视频。它就像一个魅力,我有我想要的点,我想做的是裁剪使用凸包多边形设置地标的图像。

我想做的是从这个开始:

在此处输入图像描述

对此:

在此处输入图像描述

然后保存

有什么办法吗?即使它看起来不漂亮。这是我当前的面部跟踪代码:

import cv2
import dlib
from imutils import face_utils
import imutils
import numpy as np

cap = cv2.VideoCapture(0)


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

def face_remap(shape):
    remapped_image = cv2.convexHull(shape)
    return remapped_image


while True:
    _, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    out_face = np.zeros_like(frame)
    faces = detector(gray, 1) 

    for face in faces:
        x1 = face.left()
        y1 = face.top()
        x2 = face.right()
        y2 = face.bottom()
        aam = [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, 77, 75, 75, 55, 69, 70, 71, 80, 72, 73, 79, 74, 78]

        landmarks = predictor(gray, face)
        shape = face_utils.shape_to_np(landmarks)
        remapped_shape = np.zeros_like(shape) 
        feature_mask = np.zeros((frame.shape[0], frame.shape[1]))   
        
        x_pts = []
        y_pts = []
        for n in (aam):
            x = landmarks.part(n).x
            y = landmarks.part(n).y

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

            cv2.circle(frame, (x, y), 1, (255, 0, 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)
    k = cv2.waitKey(1)
    if k == 27:
        remapped_shape = face_remap(shape)
        cv2.fillConvexPoly(feature_mask, remapped_shape[0:27], 1)
        feature_mask = feature_mask.astype(np.bool)
        out_face[feature_mask] = frame[feature_mask]
        cv2.imwrite("out_face.png", out_face)
        break
        

    
cap.release()
cv2.destroyAllWindows()

此代码将从背景中裁剪人脸图像并设置地标,如示例中所示。但是我想在地标周围裁剪

标签: pythonpython-3.xopencvcomputer-visiondlib

解决方案


您仅选择了 dlib 识别出的面部 81 个标志的子集,并丢弃了与嘴巴、下巴和面部外轮廓相关的标志。

您应该做一个额外的选择,只留下您感兴趣的区域边界处的点。此外,您应该对选定的点进行排序,以便以正确的顺序连接它们,将形成一个多边形,准确地标记您想要的区域庄稼。

一旦你有了多边形,你可以使用这个方法来裁剪它:


推荐阅读