OpenCV 人脸识别和比对工具
这是一个基于OpenCV和dlib的人脸识别工具,可从多张照片中筛选出包含指定人脸的照片。主要功能包括:从目标图片提取人脸特征、在指定目录搜索匹配人脸、保存结果并框出人脸位置。使用前需安装OpenCV、numpy等依赖库,配置目标图片路径和搜索目录。脚本采用dlib进行人脸检测和特征提取,通过欧氏距离计算相似度,可调整阈值控制识别精度。首次运行需下载模型文件,支持jpg、png等常见格式,会递归搜
·
OpenCV 人脸识别和比对工具
应用场景
在很多张包含人脸的照片中,提取出包含指定人脸相关的照片。适合将图片按人物分类。
功能说明
此Python脚本可以:
- 从一张目标人脸图片中提取人脸特征
- 在指定目录中搜索包含该人脸的所有图片
- 将匹配的图片保存到新目录并在图片上框出人脸位置
- 提供阈值参数以调整识别精度
安装依赖
在运行脚本之前,需要安装以下依赖:
pip install opencv-python numpy requests dlib-bin
使用方法
配置路径
在运行脚本之前,需要在脚本中配置以下路径:
target_image:目标人脸图片路径(默认为:C:\Users\zhangqs\Desktop\TEST\1.jpg)search_directory:要搜索的图片目录(默认为:C:\Users\zhangqs\Desktop\TEST\2)tolerance:人脸识别阈值(默认为:0.4,值越小越严格)
运行脚本
python face_recognition_script.py
脚本执行流程
- 检查模型文件:自动检查并下载所需的dlib模型文件(首次运行时)
- 初始化模型:加载人脸识别模型
- 提取特征:从目标人脸图片中提取特征
- 搜索匹配:在指定目录中搜索包含目标人脸的图片
- 保存结果:将匹配的图片保存到
C:\Users\zhangqs\Desktop\TEST\3目录,并在图片上框出人脸位置
提高识别准确性的方法
- 使用清晰的目标图片:确保目标人脸图片清晰、正面,光线充足
- 调整tolerance参数:降低阈值(如0.4)可以提高识别精度,但可能会漏掉一些相似的人脸
- 确保搜索目录中的图片质量:搜索目录中的图片也应该清晰可见人脸
- 使用足够的测试数据:搜索目录中应该包含足够多的图片来测试识别效果
注意事项
- 首次运行时间较长:首次运行时需要下载模型文件,可能需要较长时间
- 处理大量图片时可能耗时:这是正常现象,因为人脸识别是计算密集型任务
- 支持的图片格式:jpg、jpeg、png、bmp
- 脚本会遍历子目录:脚本会递归遍历指定目录及其所有子目录中的图片文件
技术原理
- 使用dlib进行人脸检测和特征提取
- 使用OpenCV进行图像处理
- 使用欧氏距离计算人脸特征相似度
- 通过阈值控制识别的严格程度
- 使用ResNet模型进行人脸识别,提高识别准确性
import os
import cv2
import dlib
import numpy as np
import argparse
# 全局变量
detector = None
sp = None
facerec = None
def extract_face_features(image_path):
"""
从图片中提取人脸特征
"""
try:
# 读取图片
img = cv2.imread(image_path)
if img is None:
print(f"错误: 无法读取 {image_path}")
return None
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 检测人脸
faces = detector(gray)
if len(faces) == 0:
print(f"错误: 在 {image_path} 中未检测到人脸")
return None
# 提取第一个人脸的特征
shape = sp(img, faces[0])
face_descriptor = facerec.compute_face_descriptor(img, shape)
return np.array(face_descriptor)
except Exception as e:
print(f"错误: 处理 {image_path} 时出错: {e}")
return None
def compute_distance(encoding1, encoding2):
"""
计算两个人脸特征之间的欧氏距离
"""
return np.linalg.norm(encoding1 - encoding2)
def find_matching_images(target_encoding, search_directory, target_directory, tolerance=0.6):
"""
在指定目录中查找包含目标人脸的图片
"""
matching_images = []
# 创建保存目录
if not os.path.exists(target_directory):
os.makedirs(target_directory)
print(f"创建保存目录: {target_directory}")
image_count = 1
for root, dirs, files in os.walk(search_directory):
for file in files:
if file.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp')):
image_path = os.path.join(root, file)
print(f"正在处理: {image_path}")
try:
# 读取图片
img = cv2.imread(image_path)
if img is None:
print(f"警告: 无法读取 {image_path}")
continue
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 检测人脸
faces = detector(gray)
# 检查每个人脸
for face in faces:
shape = sp(img, face)
face_descriptor = facerec.compute_face_descriptor(img, shape)
face_encoding = np.array(face_descriptor)
# 计算距离
distance = compute_distance(target_encoding, face_encoding)
print(f" 距离: {distance:.4f}")
# 检查是否匹配
if distance < tolerance:
matching_images.append(image_path)
# 在图片上框出人脸
x, y, w, h = face.left(), face.top(), face.width(), face.height()
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 保存处理后的图片
save_filename = f"{image_count}.jpg"
save_path = os.path.join(target_directory, save_filename)
cv2.imwrite(save_path, img)
print(f" 保存到: {save_path}")
image_count += 1
break
except Exception as e:
print(f"错误: 处理 {image_path} 时出错: {e}")
return matching_images
def download_required_files():
"""
下载所需的模型文件
"""
import requests
import zipfile
files = {
'shape_predictor_68_face_landmarks.dat': 'http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2',
'dlib_face_recognition_resnet_model_v1.dat': 'http://dlib.net/files/dlib_face_recognition_resnet_model_v1.dat.bz2'
}
for filename, url in files.items():
if not os.path.exists(filename):
# 检查压缩包是否存在
if os.path.exists(f"{filename}.bz2"):
print(f"发现压缩包 {filename}.bz2,正在解压...")
try:
# 解压文件
import bz2
with bz2.BZ2File(f"{filename}.bz2", 'rb') as fr, open(filename, 'wb') as fw:
fw.write(fr.read())
# 删除压缩文件
os.remove(f"{filename}.bz2")
print(f"{filename} 解压完成")
except Exception as e:
print(f"错误: 解压 {filename} 时出错: {e}")
return False
else:
print(f"正在下载 {filename}...")
try:
# 下载文件
import bz2
response = requests.get(url, stream=True)
with open(f"{filename}.bz2", 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
# 解压文件
print(f"正在解压 {filename}...")
with bz2.BZ2File(f"{filename}.bz2", 'rb') as fr, open(filename, 'wb') as fw:
fw.write(fr.read())
# 删除压缩文件
os.remove(f"{filename}.bz2")
print(f"{filename} 下载完成")
except Exception as e:
print(f"错误: 下载 {filename} 时出错: {e}")
return False
else:
print(f"{filename} 已存在")
return True
def main():
global detector, sp, facerec
#程序运行目录
root= os.path.dirname(os.path.abspath(__file__))
#目标人脸图片
target_image = os.path.join(root, "target.jpg")
#源图片目录
search_directory = os.path.join(root, "source")
os.makedirs(search_directory, exist_ok=True)
#目标图片目录
target_directory = os.path.join(root, "target")
os.makedirs(target_directory, exist_ok=True)
tolerance = 0.4 # 降低阈值,提高识别精度
print(f"目标人脸图片: {target_image}")
print(f"搜索目录: {search_directory}")
print(f"识别阈值: {tolerance}")
# 检查模型文件是否存在
print("\n检查所需的模型文件...")
model_files = [
'shape_predictor_68_face_landmarks.dat',
'dlib_face_recognition_resnet_model_v1.dat'
]
all_files_exist = True
for model_file in model_files:
if os.path.exists(model_file):
print(f"{model_file} 已存在")
else:
print(f"错误: {model_file} 不存在")
all_files_exist = False
if not all_files_exist:
print("缺少必要的模型文件,程序退出")
return
# 初始化dlib的模型
print("初始化人脸识别模型...")
detector = dlib.get_frontal_face_detector()
sp = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
facerec = dlib.face_recognition_model_v1('dlib_face_recognition_resnet_model_v1.dat')
print(f"\n正在提取目标人脸特征...")
target_encoding = extract_face_features(target_image)
if target_encoding is None:
print("无法提取目标人脸特征,程序退出")
return
print(f"\n正在搜索包含目标人脸的图片...")
matching_images = find_matching_images(target_encoding, search_directory, target_directory, tolerance)
print(f"\n搜索完成!")
print(f"找到 {len(matching_images)} 张包含目标人脸的图片:")
for image_path in matching_images:
print(f"- {image_path}")
if __name__ == "__main__":
main()
资源下载
- 完整人脸检测/识别所需模型及代码,请在文章关联资源下载(文章顶部)。
- 经个人测试,对于人脸较少的情况下比较准确,人脸较多时不够准确,请谨慎使用。
更多推荐
所有评论(0)