人脸去背景

人脸关键点去背景实现

在人脸识别或者活体检测中,可以利用关键点信息对人脸进行去背景,然后再做检测和识别,会提高准确率。

关键点检测可以利用dlib或者自己的关键点检测模型来实现,这里不过多介绍。

 

实现过程分两个步骤:

(1)对图片进行68个关键点检测,找到轮廓的17个关键点,再结合左右眉毛最上端的两个关键点找到最左上、右上这两个点的坐标,一共19个,按顺序连起来,组成了一个新的区域D。代码如下:

# get outline landmarks
def get_outline_landmarks(landmarks, xy, zz):
    # outline include 19 landmarks
    shape_landmarks = np.zeros((19, 2))
    
    for i in range(17):
        shape_landmarks[i][0] = landmarks[i][0] - xy[0]
        shape_landmarks[i][1] = landmarks[i][1] - xy[1]

    shape_landmarks[17] = zz[0] - xy[0], xy[1] - xy[1]
    shape_landmarks[18] = xy[0] - xy[0], xy[1] - xy[1]

    return shape_landmarks

(2)然后遍历每一个像素点,判断该像素点是否在区域 D内,如果不在区域内就把像素点置0。怎么判断像素点是否在区域内呢,其实有一种算法叫射线法,大家可以去看一下。实现代码:

# 获取关键点轮廓坐标
# 参数:landmarks 为68个关键点的坐标  参数:xy 关键点的最小值坐标  参数zz:关键点的最大值坐标
outline = get_outline_landmarks(landmarks, xy, zz)

# 判断单个像素点是否在区域Region内,返回一个True或False
def inside(X, Y, Region):
    j = len(Region) - 1
    flag = False
    for i in range(len(Region)):
        if ((Region[i][1] < Y and Region[j][1] >= Y) or (Region[j][1] < Y and Region[i][1] >= Y)):
            if (Region[i][0] + (Y - Region[i][1]) / (Region[j][1] - Region[i][1]) * (Region[j][0] - Region[i][0]) < X):
                flag = not flag
        j = i
    return flag

# 遍历每个像素点
for i in range(region_y2-region_y1):
    for j in range(region_x2-region_x1):
        if not inside(j, i, outline):
            # outside pixels value set to 0
            landmark_region[i, j] = (0, 0, 0) 

去背景前后的效果对照图:

人脸去背景_第1张图片           人脸去背景_第2张图片

 

改进:这种方法虽然实现了人脸去背景,但是特别耗时,时间复杂度为O(n^3),在pc上运行这个算法也要几百ms。几经研究发现可以使用opencv来实现去背景。前面人脸轮廓关键点的操作都一样,先连成一个区域,然后在使用opencv的cv2.polylines 函数来实现多边形抠图。

效果:原来的几百ms变为了0.2ms,算法速度有了极大的提高。

 


参考:https://blog.csdn.net/kgzhang/article/details/75570843

你可能感兴趣的:(人脸识别)