face_recognition学习(二)——人脸识别样例

上一篇face_recognition学习(一)——face_recognition安装中讲解了如何搭建环境,以及如何简单使用命令来识别未知图片。

我们也可以在Python代码中导入face_recognition模块来使用它,使用方式超级简单,只需操作几个API即可实现人脸检测的效果。

关于项目代码可从github上下载下来:点这里 ,项目文件夹中包括了样例代码以及测试所用的图片。


(一)检测两张图片是否为同一个人

代码:

import face_recognition
known_image = face_recognition.load_image_file("/softs/test/known_people/Obama.jpg")
unknown_image = face_recognition.load_image_file("/softs/test/unknown_pictures/unknown1.jpg")
obama_encoding = face_recognition.face_encodings(known_image)[0]
unknown_encoding = face_recognition.face_encodings(unknown_image)[0]
results = face_recognition.compare_faces([obama_encoding], unknown_encoding)
if results[0] == True:
    print ("It's a picture of Obama!")
else:
    print ("It's not a picture of Obama!")

自行网上随便找两张奥巴马的图片(我们假设有一张不知道他是奥巴马),按照上面的代码:

调用load_image_file函数来加载这两张图片,face_encodings函数用于获取这两张图片中的128维人脸编码(特征向量),一个人脸编码对应一张人脸,如果一张图片包括n张人脸,那么该函数的返回值则是一个由n个人脸编码组成的列表。

获取两张图片的人脸编码后,调用compare_faces函数识别这两张照片的人能否匹配上,即检测未知图片是不是奥巴马,该函数返回值是一个由True或False组成的列表,True表示匹配上,False表示不匹配。

输出结果如下,表明这两张图片都是奥巴马。

It's a picture of Obama!

API说明:

  • 图像载入函数——load_image_file

       load_image_file(file, mode='RGB')

       加载一个图像文件到一个numpy array类型的对象上。

       参数:

       file待加载的图像文件名字

       mode转换图像的格式。只支持“RGB”(8位RGB, 3通道)和“L”(黑白)

       返回值:

       一个包含图像数据的numpy array类型的对象

  • 人脸编码函数——face_encodings

       face_encodings(face_image, known_face_locations=None, num_jitters=1)

       给定一个图像,返回图像中每个人脸的128脸部编码(特征向量)。

       参数:

       face_image输入的人脸图像

       known_face_locations可选参数,如果你知道每个人脸所在的边界框

       num_jitters=1在计算编码时要重新采样的次数。越高越准确,但速度越慢(100就会慢100倍)

       返回值:

       一个128维的脸部编码列表

  • 人脸匹配函数——compare_faces

       compare_faces(known_face_encodings, face_encoding_to_check, tolerance=0.6)

       比较脸部编码列表和候选编码,看看它们是否匹配,设置一个阈值,若两张人脸特征向量的距离,在阈值范围之内,则认为其 是同一个人

       参数:

       known_face_encodings:已知的人脸编码列表

       face_encoding_to_check:待进行对比的单张人脸编码数据

       tolerance=0.6:两张脸之间有多少距离才算匹配。该值越小对比越严格,0.6是典型的最佳值

       返回值:

       一个 True或者False值的列表,该表指示了known_face_encodings列表的每个成员的匹配结果


(二)定位图片中的人脸

代码:

from PIL import Image
import face_recognition
# Load the jpg file into a numpy array
image=face_recognition.load_image_file("/softs/test_images/johnsnow_test1.jpg")

# Find all the faces in the image using the default HOG-based model.
# This method is fairly accurate, but not as accurate as the CNN model and not GPU accelerated.
# See also: find_faces_in_picture_cnn.py

face_locations = face_recognition.face_locations(image)
print("I found {} face(s) in this photograph.".format(len(face_locations)))

for face_location in face_locations:
    # 打印出每张人脸对应四条边在图片中的位置(top、right、bottom、left)
    top, right, bottom, left = face_location
    print ("A face is located at pixel location Top: {}, Left: {}, Bottom: {}, Right: {}")\
        .format(top, right, bottom, right)

    # You can access the actual face itself like this:
    face_image = image[top:bottom, left:right]
    pil_image = Image.fromarray(face_image)
    pil_image.show()

打印信息:

I found 1 face(s) in this photograph.
A face is located at pixel location Top: 180, Left: 448, Bottom: 366, Right: 448

输入的原图片和输出的人脸定位图,分别如下左右图:

                   

API说明:

  • 人脸定位函数——face_locations

       face_locations(face_image,number_of_times_to_upsample=1,model="hog")

       利用CNN深度学习模型或方向梯度直方图(Histogram of Oriented Gradient, HOG)进行人脸提取。返回值是一个数组(top, right, bottom, left)表示人脸所在边框的四条边的位置。

       参数:

       face_image输入的人脸图像

       number_of_times_to_upsample=1从图片的样本中查找多少次人脸,该参数的值越高的话越能发现更小的人脸

       model="hog"使用哪种人脸检测模型。“hog” 准确率不高,但是在CPU上运行更快,“cnn” 更准确更深度(且GPU/CUDA加速,如果有GPU支持的话),默认是“hog”

       返回值:

       一个元组列表,列表中的每个元组包含人脸的四边位置(top, right, bottom, left)

与face_locations相似的,可以批次进行多张图片的人脸定位,使用batch_face_locations,有GPU的可以试一下。

  • 批次人脸定位函数(GPU)——batch_face_locations

       batch_face_locations(face_images,number_of_times_to_upsample=1,batch_size=128)

       使用CNN人脸检测器返回一个包含人脸特征的二维数组,如果使用了GPU,这个函数能够更快速的返回结果;如果不使用GPU的话,该函数就没必要使用

       参数:

       face_images输入多张人脸图像组成的list

       number_of_times_to_upsample=1从图片的样本中查找多少次人脸,该参数的值越高的话越能发现更小的人脸

       batch_size=128每个GPU一次批处理多少个image

       返回值:

       一个元组列表,列表中的每个元组包含人脸的四边位置(top, right, bottom, left)


(三)识别脸部特征

代码:

import face_recognition

# Load the jpg file into a numpy array
from PIL import Image, ImageDraw

image = face_recognition.load_image_file("/softs/test_images/two_people.jpg")

# 找出图片中所有人脸的面部特征
face_landmarks_list = face_recognition.face_landmarks(image)

print ("I found {} face(s) in this photograph.".format(len(face_landmarks_list)))

# 创建一个PIL ImageDraw对象,后面用于图像绘制
pil_image = Image.fromarray(image)
d = ImageDraw.Draw(pil_image)

for face_landmarks in face_landmarks_list:
    # 打印出图片中每个脸部特征的位置
    for facial_feature in face_landmarks.keys():
        print ("The {} in this face has the following points: {}"
               .format(facial_feature, face_landmarks[facial_feature]))

    # 用线段描出图像中的每个脸部特征
    for facial_feature in face_landmarks.keys():
        d.line(face_landmarks[facial_feature], width=5)

# Show the picture
pil_image.show()

代码说明:首先我们还是加载一张人脸图片,调用face_landmarks函数从该图片中,得到一个由脸部特征关键点位置组成的字典记录列表(脸部特征包括:鼻梁nose_bridge、鼻尖nose_tip、下巴chin、左眼left_eye、右眼right_eye、左眉left_eyebrow、右眉right_eyebrow、上唇top_lip、下唇bottom_lip,可参考下面程序打印输出的信息)

接下来为该图片构建一个ImageDraw对象,ImageDraw是Python图像处理库(PIL)中的一个模块,模块提供了图像对象的简单2D绘制,用户可以使用这个模块创建新的图像,注释或润饰已存在图像。我们后面调用ImageDraw.line()方法可以用线段描绘出脸部特征。

打印输出的部分信息如下:

I found 2 face(s) in this photograph.
The nose_bridge in this face has the following points: [(881L, 128L), (880L, 141L), (880L, 154L), (879L, 167L)]
The left_eye in this face has the following points: [(834L, 124L), (843L, 122L), (851L, 124L), (858L, 129L), (850L, 129L), (841L, 127L)]
The nose_tip in this face has the following points: [(857L, 174L), (865L, 178L), (874L, 181L), (881L, 181L), (888L, 180L)]
The chin in this face has the following points: [(789L, 129L), (788L, 150L), (787L, 171L), (788L, 191L), (795L, 211L), (808L, 227L), (824L, 239L), (842L, 249L), (862L, 253L), (881L, 254L), (897L, 247L), (911L, 236L), (921L, 222L), (928L, 206L), (933L, 188L), (937L, 171L), (940L, 153L)]
The right_eye in this face has the following points: [(896L, 138L), (906L, 136L), (914L, 138L), (920L, 143L), (913L, 144L), (904L, 142L)]
The left_eyebrow in this face has the following points: [(821L, 110L), (831L, 102L), (845L, 101L), (860L, 104L), (872L, 111L)]
The bottom_lip in this face has the following points: [(895L, 209L), (884L, 210L), (875L, 208L), (867L, 207L), (859L, 205L), (850L, 202L), (838L, 198L), (842L, 198L), (861L, 199L), (869L, 201L), (877L, 202L), (891L, 207L)]
The right_eyebrow in this face has the following points: [(891L, 117L), (905L, 116L), (918L, 118L), (929L, 124L), (935L, 135L)]
The top_lip in this face has the following points: [(838L, 198L), (852L, 196L), (863L, 196L), (870L, 200L), (878L, 199L), (887L, 203L), (895L, 209L), (891L, 207L), (877L, 203L), (869L, 202L), (862L, 200L), (842L, 198L)]
......

输入的原图片和输出的脸部特征绘制图,分别如下左右图所示:

     

API说明:

  • 人脸特征提取函数——face_landmarks

       face_landmarks(face_image,face_locations=None,model="large")

       给定一个图像,提取图像中每个人脸的脸部特征位置

       参数:

       face_image输入的人脸图片

       face_locations=None可选参数,默认值为None,代表默认解码图片中的每一个人脸。若输入face_locations()[i]可指定人脸进行解码

       model="large"输出的特征模型,默认为“large”,可选“small”。当选择为"small"时,只提取左眼、右眼、鼻尖这三种脸部特征。

       返回值:

       返回值类型为:List[Dict[str,List[Tuple[Any,Any]]]],是由各个脸部特征关键点位置组成的字典记录列表,一个Dict对象对应图片中的一个人脸,其key为某个脸部特征(如输出中的nose_bridge、left_eye等),value是由该脸部特征各个关键点位置组成的List,关键点位置是一个Tuple(如上输出中,nose_bridge对应的关键点位置组成的列表为[(881L, 128L), (880L, 141L), (880L, 154L), (879L, 167L)]  )


(四)给奥黑哥化个妆

代码:

import face_recognition
from PIL import Image, ImageDraw

# Load the jpg file into a numpy array
image = face_recognition.load_image_file("/softs/test_images/obama.jpg")

# Find all facial features in all the faces in the image
face_landmarks_list = face_recognition.face_landmarks(image)

for face_landmarks in face_landmarks_list:
    # Create a PIL imageDraw object so we can draw on the picture
    pil_image = Image.fromarray(image)
    d = ImageDraw.Draw(pil_image,'RGBA')

    # 画个浓眉
    d.polygon(face_landmarks['left_eyebrow'], fill=(68, 54, 39, 128))
    d.polygon(face_landmarks['right_eyebrow'], fill=(68, 54, 39, 128))
    d.line(face_landmarks['left_eyebrow'], fill=(68, 54, 39, 150), width=5)
    d.line(face_landmarks['right_eyebrow'], fill=(68, 54, 39, 150), width=5)

    # 涂个性感的嘴唇
    d.polygon(face_landmarks['top_lip'], fill=(150, 0, 0, 128))
    d.polygon(face_landmarks['bottom_lip'], fill=(150, 0, 0, 128))
    d.line(face_landmarks['top_lip'], fill=(150, 0, 0, 64), width=8)
    d.line(face_landmarks['bottom_lip'], fill=(150, 0, 0, 64), width=8)

    # 闪亮的大眼睛
    d.polygon(face_landmarks['left_eye'], fill=(255, 255, 255, 30))
    d.polygon(face_landmarks['right_eye'], fill=(255, 255, 255, 30))

    # 画眼线
    d.line(face_landmarks['left_eye'] + [face_landmarks['left_eye'][0]], fill=(0, 0, 0, 110), width=6)
    d.line(face_landmarks['right_eye'] + [face_landmarks['right_eye'][0]], fill=(0, 0, 0, 110), width=6)

    pil_image.show()

首先还是先载入图片,构建一个ImageDraw对象。

polygon方法用于绘制多边形:第一个参数是多边形的几个顶点位置组成的list,第二个参数fill是填充该多边形的颜色。

line()方法是用来画多个点之间构成的线段,第一个参数是点位置组成的list,第二个参数fill是线段的颜色,第三个参数width是线段的宽度。

输入的奥巴马原图与化妆后的奥巴马,分别如下左右图:

            

猜你喜欢

转载自blog.csdn.net/qq_42267603/article/details/89240435