在python中使用OpenCV 模块实现面部识别系统相当简单。
当然我们还可以通过其他模块来实现面部识别。
方法一:face_recognition库
Python face_recognition库的一些示例用法:
- 检测图像中的人脸
- 检测检测到的人脸上的面部特征(如眉毛和鼻子)
- 检查检测到的人脸是否匹配
以下是一些相关的face_recognition链接,如果您需要/想要它们:
- 文档:face-recognition.readthedocs.io
- 源代码: /ageitgey/face_recognition
- PyPI:pypi.org/project/face-recognition
安装“face_recognition”库
先决条件
本示例运行在windows环境下,linux和macos可根据情况自行调整,其实更简单。
要在 Windows 上安装 face_recognition 库,您需要安装以下软件:
- CMake的
- Visual Studio C++ 生成工具
如果你没有这些,你会得到这样的错误,
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 环境变量中,以便轻松找到它。

安装完成后,打开终端并执行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并允许它安装一些东西,然后我们才能进入下面的屏幕。当您到达此屏幕时,请选择我所拥有的:

单击“安装”后,等待安装完成并重新启动。
现在,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,现在可以开始检测人脸了。首先,我们将检测图像中只有一个人的脸。

该图片仅作为程序测试使用
首先,我们要从 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()这将在默认图像查看器中打开图像。图像应如下所示:

该图像仅作此处程序测试用。
裁剪检测到的人脸
除了画一个盒子,我们还可以将脸裁剪成另一个图像。
使用我们没有绘制的原始图像(因为我们在复制的图像上绘制),我们可以调用提供之前的尺寸。
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()
完整代码
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 张略微模糊。

细节不在赘述,重点说下不同之处
如果我们打印出 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()
同样也可以分开裁剪。
完整代码
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()
完整代码
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识别人脸
先决条件:
- 下载 Python 2.7.x 版本、numpy 和 Opencv 2.7.x 版本。检查您的 Windows 32 位或 64 位是否兼容并相应地安装。
- 确保 numpy 在 python 中运行,然后尝试安装 opencv。
- 将 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
















