1. 背景条件
1.1 安装所需库
首先安装 face_recognition
和 Pillow
这两个库。您可以使用以下命令来安装它们:
pip install face_recognition Pillow -i https://pypi.tuna.tsinghua.edu.cn/simple
1.2 拷贝代码
安装完成后,您就可以在本地运行以下提供的代码了。
import face_recognition
from PIL import Image, ImageDraw
from matplotlib import pyplot as plt
import time
def faceRecognition(image_path):
# 尝试加载图片
try:
print(f"Loading image from {image_path}")
image = face_recognition.load_image_file(image_path)
except FileNotFoundError:
return "Error: 文件未找到,请确保文件路径正确!"
except Exception as e:
return f"Error: {e}"
# 人脸定位
print("Detecting faces...")
face_locations = face_recognition.face_locations(image)
face_landmarks = face_recognition.face_landmarks(image)
# 如果没有找到人脸,则返回
if len(face_locations) == 0:
return "没有在图片中找到人脸."
# 打开图片并准备画图
pil_image = Image.open(image_path)
draw = ImageDraw.Draw(pil_image)
for face_location, face_landmark in zip(face_locations, face_landmarks):
top, right, bottom, left = face_location
print(f"Drawing rectangle at location Top: {top}, Left: {left}, Bottom: {bottom}, Right: {right}")
# 画人脸边框
draw.rectangle(((left, top), (right, bottom)), outline=(255, 0, 0), width=3)
# 画出人脸特征点
for facial_feature in face_landmark.keys():
for point in face_landmark[facial_feature]:
draw.circle(point, radius=2, fill=(0, 255, 0)) # 使用绿色填充圆圈
# 使用matplotlib显示图片
plt.imshow(pil_image)
plt.axis('off') # 不显示坐标轴
plt.show()
# 保存图片
output_path = "E:/imgs/recognized_faces_with_landmarks.jpg"
pil_image.save(output_path)
print(f"Image with landmarks saved to {output_path}")
if __name__ == '__main__':
start = time.time()
# 使用示例图片的路径
sample_image_path = "E:/imgs/sample_image.jpg"
output_path = faceRecognition(sample_image_path)
print(output_path)
end = time.time()
print('共耗时' + str(end - start) + '秒')
2. 程序概述
这个程序使用 face_recognition
和 Pillow
库来检测图片中的人脸,并在检测到的人脸周围画边框,同时在人脸的特征点上画绿色的小圆圈。最后,程序将修改后的图片保存到指定的路径。
3. 功能分解
- 导入必要的库:
face_recognition
:用于人脸检测和人脸特征点识别。PIL
(Pillow)库中的Image
和ImageDraw
:用于加载图片和在图片上画图。
- 定义
faceRecognition
函数:- 参数:
image_path
,即输入图片的路径。 - 功能:
- 加载图片:
- 使用
face_recognition.load_image_file
尝试加载图片。 - 如果图片不存在或发生其他错误,则捕获异常并返回错误信息。
- 使用
- 人脸定位:
- 使用
face_recognition.face_locations
方法找到图片中所有人脸的位置。 - 使用
face_recognition.face_landmarks
方法找到每个人脸的特征点。
- 使用
- 检查是否找到人脸:
- 如果没有找到人脸,则返回相应的信息。
- 打开图片并准备画图:
- 使用
Pillow
库打开图片。 - 创建一个
ImageDraw
对象用于在图片上画图。
- 使用
- 画人脸边框和特征点:
- 遍历每个人脸位置和特征点。
- 使用
draw.rectangle
方法在每个人脸周围画一个红色边框。 - 使用
draw.circle
方法在每个人脸的特征点上画一个绿色的小圆圈。
- 保存图片:
- 将修改后的图片保存到指定的路径(
E:/imgs/recognized_faces_with_landmarks.jpg
)。
- 将修改后的图片保存到指定的路径(
- 返回值:
- 返回保存后的图片的路径。
- 加载图片:
- 参数:
- 调用
faceRecognition
函数:- 使用示例图片的路径(
sample_image_path
)作为参数调用faceRecognition
函数。
- 使用示例图片的路径(
- 输出
output_path
:- 打印出保存后的图片的路径,以便知道图片被保存在哪里。
4. 运行效果
4.1 单人检测效果
4.2 多人检测效果
5. 小结
以上程序接受一个图片路径作为输入,检测图片中的人脸和特征点,然后在每个人脸周围画红色边框,在特征点上画绿色小圆圈,最后将修改后的图片保存并返回保存路径。这是一个典型的人脸识别和图像处理任务,可以用于各种需要人脸识别的应用场景。
6. 进阶:人脸识别比对
在以上的基础上,我们应用欧氏距离进行人脸距离计算
6.1 定义
欧氏距离(Euclidean distance)是数学中的一个概念,用于计算两个点在欧几里得空间中的直线距离。在人脸识别和图像处理中,欧氏距离可以用来度量两个面部特征向量之间的差异,从而判断两张人脸的相似度。
6.2 原理:
在二维空间中,两个点A
、B
之间的欧氏距离可以通过以下公式计算:
-
第一个点
A
的坐标:
A = ( x 1 , y 1 ) A = (x_1, y_1) A=(x1,y1) -
第二个点
B
的坐标:
B = ( x 2 , y 2 ) B = (x_2, y_2) B=(x2,y2) -
二维空间的欧氏距离公式:
d = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2} d=(x2−x1)2+(y2−y1)2
在人脸识别中,每张人脸可以表示为一个高维向量,其中每个维度对应于面部特征的一个量化值,比如眼睛的位置、鼻子的宽度、嘴巴的形状等。假设我们有两个面部特征向量A
和B
,它们分别是n
维的:
- 向量
A
的表示:
A = [ a 1 , a 2 , . . . , a n ] \textbf{A} = [a_1, a_2, ..., a_n] A=[a1,a2,...,an] - 向量
B
的表示:
B = [ b 1 , b 2 , . . . , b n ] \textbf{B} = [b_1, b_2, ..., b_n] B=[b1,b2,...,bn]
6.3 公式扩展
欧氏距离的计算公式扩展到 n
维空间为:
- n维空间的欧氏距离公式:
d ( A , B ) = ∑ i = 1 n ( b i − a i ) 2 d(\textbf{A}, \textbf{B}) = \sqrt{\sum_{i=1}^{n} (b_i - a_i)^2} d(A,B)=i=1∑n(bi−ai)2
6.4 判断人脸距离:
- 特征提取:首先,从每张人脸图片中提取特征,这些特征可以是面部关键点的坐标、局部特征描述符(如LBP、HOG)或者深度学习模型提取的特征向量。
- 特征标准化:为了消除不同量纲和数值范围的影响,通常需要对特征向量进行标准化处理。
- 计算距离:使用上述公式计算两个特征向量之间的欧氏距离。
- 相似度判断:设定一个阈值 ( \theta ),如果两个特征向量之间的欧氏距离小于这个阈值,可以认为这两张人脸是相似的或者是同一个人;如果距离大于这个阈值,则认为它们属于不同的人。
6.5 结论
欧氏距离越小,表明两张人脸越相似;欧氏距离越大,表明两张人脸的差异越大。在实际应用中,这个方法可能会受到光照、姿态、表情等因素的影响,因此通常会结合其他方法和算法来提高人脸识别的准确率和鲁棒性。
但在本次的程序中,我们为了条件方便,用了如下方式,所以得出的相似度分数越大则表示两张面孔越相似
similarity_score = 1 - face_distances[0]
6.6 程序代码
import face_recognition
from PIL import Image, ImageDraw
from matplotlib import pyplot as plt
import time
def faceRecognition(image_path, known_image_path, tolerance=0.8):
# 尝试加载图片
try:
print(f"Loading image from {image_path}")
image = face_recognition.load_image_file(image_path)
known_image = face_recognition.load_image_file(known_image_path)
except FileNotFoundError as e:
return f"Error: {e}"
except Exception as e:
return f"Error: {e}"
# 获取已知人脸编码
print("Encoding known face...")
known_face_encoding = face_recognition.face_encodings(known_image)[0]
# 人脸定位和编码
print("Detecting faces...")
face_locations = face_recognition.face_locations(image)
face_encodings = face_recognition.face_encodings(image, face_locations)
# 如果没有找到人脸,则返回
if len(face_locations) == 0:
return "没有在图片中找到人脸."
# 打开图片并准备画图
pil_image = Image.open(image_path)
draw = ImageDraw.Draw(pil_image)
# 遍历每个人脸位置和人脸编码
for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
# 比较人脸
matches = face_recognition.compare_faces([known_face_encoding], face_encoding, tolerance=tolerance)
# 计算相似度分数
face_distances = face_recognition.face_distance([known_face_encoding], face_encoding)
similarity_score = 1 - face_distances[0] if face_distances[0] <= 1 else 0
similarity_score_rounded = round(similarity_score, 2)
name = "Unknown"
if True in matches and similarity_score>tolerance:
name = "Known"
# 画人脸边框
draw.rectangle(((left, top), (right, bottom)), outline=(255, 0, 0), width=3)
# 打印匹配信息
match_text = f"{name} (Match: {'Yes' if True in matches and similarity_score>tolerance else 'No'})"
similarity_text = f"Similarity: {similarity_score_rounded}"
draw.text((right + 10, top), f"{match_text}\n{similarity_text}", fill=(255, 255, 255))
# 使用matplotlib显示图片
plt.imshow(pil_image)
plt.axis('off') # 不显示坐标轴
plt.show()
# 保存图片
output_path = "recognized_faces.png"
pil_image.save(output_path)
print(f"Image with recognized faces saved to {output_path}")
def CompareFace(knownpath, unknowpath):
sample_image_path = unknowpath # 待识别的人脸图片路径
known_image_path = knownpath # 已知人脸图片路径
output_path = faceRecognition(sample_image_path, known_image_path)
end = time.time()
totalTime = end - start
if __name__ == '__main__':
start = time.time()
CompareFace("E:/imgs/img2.png", "E:/imgs/img2.png") # 测试相同人脸图片
CompareFace("E:/imgs/img2.png", "E:/imgs/img.png") # 测试不同人脸图片
end = time.time()
totalTime = end - start
print('共耗时 %.2f 秒'%(totalTime))
以上程序使用 face_recognition
库来来检测、编码人脸和识别图片中的人脸,并使用 matplotlib
库来显示识别结果。并可以保存带有识别结果的图片。通过调整 tolerance
参数,可以设置匹配的相似度阈值。
在以上程序中我们使用 face_distance
函数来计算检测到的人脸与已知人脸之间的距离。然后,我们将距离转换为相似度分数,并四舍五入到两位小数。匹配信息(“Match: Yes” 或 “Match: No”)和相似度分数都打印在检测到的人脸红框的右侧。
相似度分数是通过 1 - face_distances[0]
计算的,以确保分数在 0 到 1 之间。如果距离大于 1,我们将其设置为 0,因为这种情况表明两张脸完全不相似。
7. 识别效果
7.1 相同图片测试
我们传入两张相同的图片,测试结果如下:
结果正如预期一样,识别出已知且相似度为1.0,说明完全相似
7.2 不同图片测试
此时我们传入的是两张完全不同的图片,测试结果如下:
结果也正如预期一样,识别出未知且相似度分数只有0.17。
以上就是本文的全部内容了,感兴趣的小伙伴可以尝试自行扩展程序,实现一个简单的人脸识别系统。
标签:示例,Python,image,face,人脸,path,recognition,图片 From: https://blog.csdn.net/Young_Pro/article/details/140681181