在python中使用OpenCV 模块实现面部识别系统相当简单。

当然我们还可以通过其他模块来实现面部识别。

方法一:face_recognition库

 Python face_recognition库的一些示例用法:

  • 检测图像中的人脸
  • 检测检测到的人脸上的面部特征(如眉毛和鼻子)
  • 检查检测到的人脸是否匹配

以下是一些相关的face_recognition链接,如果您需要/想要它们:

安装“face_recognition”库

先决条件

本示例运行在windows环境下,linux和macos可根据情况自行调整,其实更简单。

要在 Windows 上安装 face_recognition 库,您需要安装以下软件:

如果你没有这些,你会得到这样的错误,

CMake must be installed to build the following extensions: _dlib_pybind11

这告诉你CMake没有安装,或者,

You must use Visual Studio to build a python extension on windows.  If you
are getting this error it means you have not installed Visual C++.  Note
that there are many flavours of Visual Studio, like Visual Studio for C#
development.  You need to install Visual Studio for C++.

这告诉你需要Visual Studio C++生成工具。

CMake的

要安装 CMake,请转到 cmake.org/download/ 并下载适合您计算机的安装程序。我使用的是 64 位 Windows 10,所以我会得到cmake-<version>-win64-x64.msi,下载安装文件。

安装 CMake 时,将 CMake 添加到所有用户或当前用户的系统 PATH 环境变量中,以便轻松找到它。

python中的人脸识别算法实现_面部特征识别

安装完成后,打开终端并执行cmake。此时会显示 CMake 的用法。

如果没有,请确保选择了将其添加到 PATH 环境变量的选项。

您需要关闭并重新打开终端/应用程序,以便更新cmake的 PATH 变量,以便识别二进制文件。

Visual Studio C++ 生成工具

与 Linux 不同,默认情况下,操作系统中不包含适用于 Windows 的 C++ 编译器。如果我们访问 Python wiki 上的 WindowsCompilers 页面,我们可以看到有关获取独立版本的 Visual C++ 14.2 编译器的信息,而无需 Visual Studio。如果我们访问该wiki部分的链接,我们将被带到Microsoft下载页面。在此下载页面上,需要下载“Visual Studio 2019 生成工具”。

下载后,运行vs_buildtools__<some other stuff>.exe并允许它安装一些东西,然后我们才能进入下面的屏幕。当您到达此屏幕时,请选择我所拥有的:

python中的人脸识别算法实现_面部特征识别_02

单击“安装”后,等待安装完成并重新启动。

现在,CMake 和所需的构建工具已经安装完毕,接下来我们可以继续安装 face_recognition 库。

安装face_recognition并验证安装

要安装 face_recognition 库,请在终端中执行以下命令:

python -m pip install face-recognition

这可能需要比平时更长的时间来安装,因为 dlib 需要使用从上面安装的工具构建。若要验证库是否已成功安装,请尝试使用以下命令在 Python 中导入库:

import face_recognition

不应提出任何错误。

安装PIL

使用 Pillow / PIL,这将帮助我们裁剪和绘制图像。这不是使用 face_recognition 库所必需的,但需要证明/显示结果需要安装它,请执行以下命令:

python -m pip install Pillow

要验证库是否已安装,请尝试使用以下命令在 Python 中导入 PIL:

import PIL

检测图像中的人脸

现在我们已经设置了face_recognition库和 PIL,现在可以开始检测人脸了。首先,我们将检测图像中只有一个人的脸。

python中的人脸识别算法实现_CMake_03

该图片仅作为程序测试使用

首先,我们要从 PIL 导入face_recognition和一些助手。

import face_recognition
from PIL import Image, ImageDraw

现在使用 face_recognition.load_image_file 加载您的图像。

image = face_recognition.load_image_file('single-person.jpg')

image现在以face_recognition可以检测人脸的格式包含我们的图像。要识别此图像中人脸的位置,请调用 face_recognition.face_locations 并传递图像。

face_locations = face_recognition.face_locations(image)

face_locations现在将包含人脸位置列表。每个人脸位置都是像素位置的元组 (top, right, bottom, left)- 我们需要记住这一点,以便以后使用它。

由于此图像中只有一张脸,因此我们希望此列表中只有一个项目。要检查检测到多少张面孔,我们可以获取列表的长度。

amount = len(face_locations)
print(f'There are {amount} face locations')

对于我上面提供并用于本教程的示例图像,这告诉我检测到一张脸。

为了获得这张脸的位置供以后使用,我们可以从列表中获取第一个元素。

first_face_location = face_locations[0]

要查看其中的内容,您可以调用:

print(first_face_location)

这将打印出类似以下内容:

(400, 1221, 862, 759)

这些是我们将用于创建框并很快裁剪的像素位置。(top, right, bottom, left)

识别检测到的人脸

为了确定在图像中检测到的人脸的位置,我们将在face_recognition.face_locations返回的边界上绘制一个红色框。

首先,我们需要从使用face_recognition.load_image_file加载的映像创建一个 PIL 映像。这样做将使我们能够使用PIL提供的功能。

img = Image.fromarray(image, 'RGB')

现在我们有了 PIL 图像,我们需要创建一个对象来帮助我们在图像上绘图。在执行此操作之前,我们还将图像复制到一个新对象中,以便稍后裁剪脸部时,它周围不会仍然有一个红色框。

img_with_red_box = img.copy()
img_with_red_box_draw = ImageDraw.Draw(img_with_red_box)

现在我们有一个对象来帮助我们在图像上绘制,我们将使用之前返回的尺寸绘制一个矩形。

要绘制一个盒子,我们需要两个点,左上角和右下角作为 x 和 y 坐标。

img_with_red_box_draw.rectangle(
    [
        (first_face_location[3], first_face_location[0]),
        (first_face_location[1], first_face_location[2])
    ],
    outline="red",
    width=3
)

我们需要得到 (x, y) (x, y) 点。(left, top), (right, bottom)

在该步骤中,我们还设置了将框设置为红色并使框宽 3 像素。outline="red"width=3

要查看最终结果,我们调用:

img_with_red_box.show()

这将在默认图像查看器中打开图像。图像应如下所示:

python中的人脸识别算法实现_人脸识别_04

该图像仅作此处程序测试用。

裁剪检测到的人脸

除了画一个盒子,我们还可以将脸裁剪成另一个图像。

使用我们没有绘制的原始图像(因为我们在复制的图像上绘制),我们可以调用提供之前的尺寸。

img_cropped = img.crop((
    first_face_location[3],  # Left x
    first_face_location[0],  # Top y
    first_face_location[1],  # Right x
    first_face_location[2]   # Bottom y
))

img.crop返回正在复制的原始图像的副本,因此如果要对原始图像执行其他操作,则无需事先复制。

img_cropped现在包含一个新的裁剪图像,要显示它,我们可以再次调用。.show()

img_cropped.show()

python中的人脸识别算法实现_CMake_05

完整代码

import face_recognition
from PIL import Image, ImageDraw

# Detecting the faces
image = face_recognition.load_image_file('single-person.jpg')  # Load the image
face_locations = face_recognition.face_locations(image)  # Detect the face locations
first_face_location = face_locations[0]  # Get the first face

# Convert the face_recognition image to a PIL image
img = Image.fromarray(image, 'RGB')

# Creating the image with red box
img_with_red_box = img.copy()  # Create a copy of the original image so there is not red box in the cropped image later
img_with_red_box_draw = ImageDraw.Draw(img_with_red_box)  # Create an image to draw with
img_with_red_box_draw.rectangle(  # Draw the rectangle on the image
    [
        (first_face_location[3], first_face_location[0]),  # (left, top)
        (first_face_location[1], first_face_location[2])  # (right, bottom)
    ],
    outline="red",  # Make the box red
    width=3  # Make the box 3px in thickness
)
img_with_red_box.show()  # Open the image in the default image viewer

# Creating the cropped image
img_cropped = img.crop((  # Crop the original image
    first_face_location[3],
    first_face_location[0],
    first_face_location[1],
    first_face_location[2]
))
img_cropped.show()  # Open the image in the default image viewer

检测图像中的多张面孔

我们之前看到,face_recognition.face_locations返回了一个与人脸位置相对应的元组数组。这意味着我们可以使用与上述相同的方法,但在绘制和裁剪时循环显示结果。

我将使用以下内容作为测试图像。它有 5 张可见的脸,其中 2 张略微模糊。

python中的人脸识别算法实现_CMake_06

细节不在赘述,重点说下不同之处

如果我们打印出 face_locations (),我们可以看到已经检测到 5 张面孔。

[
    (511, 1096, 666, 941),
    (526, 368, 655, 239)
    (283, 1262, 390, 1154),
    (168, 1744, 297, 1615),
    (271, 390, 378, 282)
]

由于我们现在有不止一张脸,因此采用第一张面孔是没有意义的 - 我们应该遍历它们并在循环中执行我们的操作。

在我们继续之前,我们还应该创建我们将要使用的 PIL 映像。

img = Image.fromarray(image, 'RGB')

识别检测到的多个人脸

现在我们可以循环所有面并创建矩形。

for face_location in face_locations:
    img_with_red_box_draw.rectangle(
        [
            (face_location[3], face_location[0]),
            (face_location[1], face_location[2])
        ],
        outline="red",
        width=3
    )

再一次,看一下图片:

img_with_red_box.show()

python中的人脸识别算法实现_人脸识别剪裁_07

同样也可以分开裁剪。

完整代码

import face_recognition
from PIL import Image, ImageDraw

# Load image and detect faces
image = face_recognition.load_image_file("group-of-people.jpg")
face_locations = face_recognition.face_locations(image)

# Create the PIL image to copy and crop
img = Image.fromarray(image, 'RGB')

img_with_red_box = img.copy()  # Make a single copy for all the red boxes
img_with_red_box_draw = ImageDraw.Draw(img_with_red_box)  # Get our drawing object again
for face_location in face_locations:  # Loop over all the faces detected this time
    img_with_red_box_draw.rectangle(  # Draw a rectangle for the current face
        [
            (face_location[3], face_location[0]),
            (face_location[1], face_location[2])
        ],
        outline="red",
        width=3
    )
img_with_red_box.show()  # Open the image in the default image viewer

for face_location in face_locations:  # Loop over all the faces detected
    img_cropped = img.crop((  # Crop the current image like we did last time
        face_location[3],
        face_location[0],
        face_location[1],
        face_location[2]
    ))
    img_cropped.show()  # Show the image for the current iteration

可以识别面部特征吗?

face_recognition还有一个函数 face_recognition.face_landmarks,它的工作原理类似于但会返回包含人脸特征位置的字典列表,而不是检测到的人脸本身的位置。

回到一个人的映像,我们可以再次导入所有内容,加载映像并调用face_recognition.face_landmarks 

import face_recognition
from PIL import Image, ImageDraw

image = face_recognition.load_image_file('single-person.jpg')
face_landmarks_list = face_recognition.face_landmarks(image)  # The new call

现在,如果我们打印,对象face_landmarks_list看起来会有点不同。

[
    {
        'chin': [(315, 223), (318, 248), (321, 273), (326, 296), (335, 319), (350, 339), (370, 354), (392, 365), (415, 367), (436, 363), (455, 351), (469, 336), (479, 318), (486, 296), (488, 273), (490, 251), (489, 229)],
        'left_eyebrow': [(329, 194), (341, 183), (358, 180), (375, 182), (391, 189)],
        'right_eyebrow': [(434, 189), (448, 184), (461, 182), (474, 184), (483, 194)],
        'nose_bridge': [(411, 209), (411, 223), (412, 238), (412, 253)],
        'nose_tip': [(394, 269), (403, 272), (412, 275), (421, 272), (428, 269)],
        'left_eye': [(349, 215), (360, 208), (373, 207), (384, 216), (372, 218), (359, 219)],
        'right_eye': [(436, 216), (446, 208), (458, 208), (467, 216), (459, 219), (447, 219)],
        'top_lip': [(374, 309), (388, 300), (402, 296), (411, 298), (420, 296), (434, 301), (448, 308), (442, 308), (420, 307), (411, 308), (402, 307), (380, 309)],
        'bottom_lip': [(448, 308), (434, 317), (421, 321), (411, 322), (401, 321), (388, 317), (374, 309), (380, 309), (402, 309), (411, 310), (421, 309), (442, 308)]
    }
]

这里有很多东西。对于每个面部特征(即下巴、左眉、右眉等),相应的列表包含 x 和 y 元组 - 这些 x 和 y 点是图像上的 x 和 y 坐标。

PIL在我们一直在使用的绘图对象上提供了一种方法,.line()方法采用x和y点的列表,非常适合这种情况。首先,我们需要一个绘图对象。

img = Image.fromarray(image, 'RGB')  # Make a PIL image from the loaded image
img_draw = ImageDraw.Draw(img)  # Create the draw object

在此示例中,我们不会复制图像,因为这是我们唯一使用它的时间

现在我们有了帮助我们绘制的对象,请使用上面返回的列表中的第一个字典绘制所有这些线条。

face_landmarks = face_landmarks_list[0]  # Get the first dictionary of features
img_draw.line(face_landmarks['chin'])
img_draw.line(face_landmarks['left_eyebrow'])
img_draw.line(face_landmarks['right_eyebrow'])
img_draw.line(face_landmarks['nose_bridge'])
img_draw.line(face_landmarks['nose_tip'])
img_draw.line(face_landmarks['left_eye'])
img_draw.line(face_landmarks['right_eye'])
img_draw.line(face_landmarks['top_lip'])
img_draw.line(face_landmarks['bottom_lip'])

现在我们可以调用我们的图像来查看它:

img_draw.show()

python中的人脸识别算法实现_opencv_08

完整代码

import face_recognition
from PIL import Image, ImageDraw

# Load the image and detect face landmarks for each face within
image = face_recognition.load_image_file('single-person.jpg')
face_landmarks_list = face_recognition.face_landmarks(image)

# Make a PIL image from the loaded image and then get a drawing object
img = Image.fromarray(image, 'RGB')
img_draw = ImageDraw.Draw(img)

# Draw all the features for the first face
face_landmarks = face_landmarks_list[0]  # Get the first object corresponding to the first face
img_draw.line(face_landmarks['chin'])
img_draw.line(face_landmarks['left_eyebrow'])
img_draw.line(face_landmarks['right_eyebrow'])
img_draw.line(face_landmarks['nose_bridge'])
img_draw.line(face_landmarks['nose_tip'])
img_draw.line(face_landmarks['left_eye'])
img_draw.line(face_landmarks['right_eye'])
img_draw.line(face_landmarks['top_lip'])
img_draw.line(face_landmarks['bottom_lip'])

img_with_face_landmarks.show()  # Show the image for the current iteration

方法二:OpenCV识别人脸

先决条件:

  1. 下载 Python 2.7.x 版本、numpy 和 Opencv 2.7.x 版本。检查您的 Windows 32 位或 64 位是否兼容并相应地安装。
  2. 确保 numpy 在 python 中运行,然后尝试安装 opencv。
  3. 将 haarcascade_eye.xml & haarcascade_frontalface_default.xml 文件放在同一个文件夹中。

test.py

import cv2 

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') 

eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml') 

# capture frames from a camera 
cap = cv2.VideoCapture(0) 

# loop runs if capturing has been initialized. 
while 1: 

	# reads frames from a camera 
	ret, img = cap.read() 

	# convert to gray scale of each frames 
	gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 

	# Detects faces of different sizes in the input image 
	faces = face_cascade.detectMultiScale(gray, 1.3, 5) 

	for (x,y,w,h) in faces: 
		# To draw a rectangle in a face 
		cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,0),2) 
		roi_gray = gray[y:y+h, x:x+w] 
		roi_color = img[y:y+h, x:x+w] 

		# Detects eyes of different sizes in the input image 
		eyes = eye_cascade.detectMultiScale(roi_gray) 

		#To draw a rectangle in eyes 
		for (ex,ey,ew,eh) in eyes: 
			cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,127,255),2) 

	# Display an image in a window 
	cv2.imshow('img',img) 

	# Wait for Esc key to stop 
	k = cv2.waitKey(30) & 0xff
	if k == 27: 
		break

# Close the window 
cap.release() 

# De-allocate any associated memory usage 
cv2.destroyAllWindows()

haarcascade_frontalface_default.xml(去github上开源的opencv中找)

下载路径:https:///Itseez/opencv/blob/master/   上的 data/haarcascades/haarcascade_frontalface_default.xml

haarcascade_eye.xml(去github上开源的opencv中找)

下载路径:https:///Itseez/opencv/blob/master/  上的 data/haarcascades/haarcascade_eye.xml