如何对齐和裁剪位于子目录中的图像以进行人脸识别?

Posted

技术标签:

【中文标题】如何对齐和裁剪位于子目录中的图像以进行人脸识别?【英文标题】:How do I align and crop the images located in subdirectories for face recognition? 【发布时间】:2020-12-20 10:27:30 【问题描述】:

所以,我有一个文件夹,里面有 132 个子文件夹,其中人的名字作为文件夹名称。每个子文件夹有 5 张人脸图像。我想遍历所有子文件夹并对齐和裁剪图像以进行面部识别,并将所有子文件夹存储在名为“aligned_face”的新文件夹中。我找到了面部裁剪和对齐的代码。我的问题是,如何使用此代码循环遍历我的 132 个子文件夹并将所有对齐和裁剪的面存储在前面提到的名为“aligned_face”的文件夹中?

import face_recognition
import cv2
import numpy as np

# load image and find face locations.
image = face_recognition.load_image_file("sample.jpg")
face_locations = face_recognition.face_locations(image, model="hog")

# detect 68-landmarks from image. This includes left eye, right eye, lips, eye brows, nose and chins
face_landmarks = face_recognition.face_landmarks(image)

'''
Let's find and angle of the face. First calculate 
the center of left and right eye by using eye landmarks.
'''
leftEyePts = face_landmarks[0]['left_eye']
rightEyePts = face_landmarks[0]['right_eye']

leftEyeCenter = np.array(leftEyePts).mean(axis=0).astype("int")
rightEyeCenter = np.array(rightEyePts).mean(axis=0).astype("int")

leftEyeCenter = (leftEyeCenter[0],leftEyeCenter[1])
rightEyeCenter = (rightEyeCenter[0],rightEyeCenter[1])

# draw the circle at centers and line connecting to them
cv2.circle(image, leftEyeCenter, 2, (255, 0, 0), 10)
cv2.circle(image, rightEyeCenter, 2, (255, 0, 0), 10)
cv2.line(image, leftEyeCenter, rightEyeCenter, (255,0,0), 10)

# find and angle of line by using slop of the line.
dY = rightEyeCenter[1] - leftEyeCenter[1]
dX = rightEyeCenter[0] - leftEyeCenter[0]
angle = np.degrees(np.arctan2(dY, dX))

# to get the face at the center of the image,
# set desired left eye location. Right eye location 
# will be found out by using left eye location.
# this location is in percentage.
desiredLeftEye=(0.35, 0.35)
#Set the croped image(face) size after rotaion.
desiredFaceWidth = 128
desiredFaceHeight = 128

desiredRightEyeX = 1.0 - desiredLeftEye[0]

# determine the scale of the new resulting image by taking
# the ratio of the distance between eyes in the *current*
# image to the ratio of distance between eyes in the
# *desired* image
dist = np.sqrt((dX ** 2) + (dY ** 2))
desiredDist = (desiredRightEyeX - desiredLeftEye[0])
desiredDist *= desiredFaceWidth
scale = desiredDist / dist

# compute center (x, y)-coordinates (i.e., the median point)
# between the two eyes in the input image
eyesCenter = ((leftEyeCenter[0] + rightEyeCenter[0]) // 2,
    (leftEyeCenter[1] + rightEyeCenter[1]) // 2)

# grab the rotation matrix for rotating and scaling the face
M = cv2.getRotationMatrix2D(eyesCenter, angle, scale)

# update the translation component of the matrix
tX = desiredFaceWidth * 0.5
tY = desiredFaceHeight * desiredLeftEye[1]
M[0, 2] += (tX - eyesCenter[0])
M[1, 2] += (tY - eyesCenter[1])

# apply the affine transformation
(w, h) = (desiredFaceWidth, desiredFaceHeight)
(y2,x2,y1,x1) = face_locations[0] 

output = cv2.warpAffine(image, M, (w, h),
    flags=cv2.INTER_CUBIC)

output = cv2.cvtColor(output, cv2.COLOR_BGR2RGB)

【问题讨论】:

这似乎与 opencv 无关?因为你已经实现了裁剪? 这个问题真的和opencv有关吗?您想遍历包含人脸图像的子文件夹,应用算法将其存储在aligned_face 文件夹中? 是的。差不多。不知道如何循环它。 【参考方案1】:

似乎问题是“我如何遍历文件并写回”?

关于如何遍历文件的几个问题: How do I align and crop the images located in subdirectories for face recognition?, Recursive sub folder search and return files in a list python

要裁剪图像,您可以使用 Pillow:https://pillow.readthedocs.io/en/stable/

保存图片:

f = open('filepath/filename.png','wb') #wb = write byte. Path from the recursive search
f.write(image) #From opencv+numpy->pillow
f.close()

【讨论】:

这不是我想问的,但无论如何谢谢【参考方案2】:

首先,遍历所有目录和子目录。以下代码块将图像的确切路径存储在子目录中。

employees = []
for r, d, f in os.walk(db_path): # r=root, d=directories, f = files
    for file in f:
        if ('.jpg' in file):
            exact_path = r + "/" + file
            employees.append(exact_path)

员工列表存储确切的图像路径。我们需要检测和对齐人脸。在这里,deepface 在一个函数中提供检测和对齐。

#!pip install deepface
from deepface import DeepFace
import cv2

index = 0
for employee in employees:
   aligned_face = DeepFace.detectFace(employee)
   cv2.imwrite('aligned_face/%d.jpg' % (index), aligned_face)
   index = index + 1

这会将检测到并对齐的人脸保存在aligned_face 文件夹中。

Deepface 也提供人脸识别模块,但您询问了如何检测和对齐人脸。

【讨论】:

此外,您可以将 opencv、ssd、dlib 或 mtcnn 等不同方法作为参数传递给 detectFace 函数。 DeepFace.detectFace(employee,detector_backend = 'mtcnn')

以上是关于如何对齐和裁剪位于子目录中的图像以进行人脸识别?的主要内容,如果未能解决你的问题,请参考以下文章

人脸检测实战终极:使用 OpenCV 和 Python 进行人脸对齐

使用 OpenCV 从图像中识别地标和裁剪嘴的脚本看不到人脸

使用MATLAB控制笔记本电脑的摄像头,并进行实时人脸检测和识别

基于python如何建立人脸库

描述人脸识别的过程

人脸识别原理及处理流程