diff --git a/tools/face_recognition_service/.gitignore b/tools/face_recognition_service/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4ecf239680254297a58c484b548645123c373f5a --- /dev/null +++ b/tools/face_recognition_service/.gitignore @@ -0,0 +1,4 @@ +.idea/ +.vscode/ +__pycache__/ +*/__pycache__/ diff --git a/tools/face_recognition_service/Database/database.npz b/tools/face_recognition_service/Database/database.npz new file mode 100644 index 0000000000000000000000000000000000000000..8550215d9946f829dc344a3b7ea9a802c9977fdf Binary files /dev/null and b/tools/face_recognition_service/Database/database.npz differ diff --git a/tools/face_recognition_service/Database/train/Aaron_Sorkin.jpg b/tools/face_recognition_service/Database/train/Aaron_Sorkin.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e6b1dfa6dd2b9046631cc2342bc043f05b871c7f Binary files /dev/null and b/tools/face_recognition_service/Database/train/Aaron_Sorkin.jpg differ diff --git a/tools/face_recognition_service/Database/train/Anwar_Ibrahim.jpg b/tools/face_recognition_service/Database/train/Anwar_Ibrahim.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4f1236fe8713e34ca3f0b695d48b82864d9b6f8d Binary files /dev/null and b/tools/face_recognition_service/Database/train/Anwar_Ibrahim.jpg differ diff --git a/tools/face_recognition_service/Database/train/Bob_Graham.jpg b/tools/face_recognition_service/Database/train/Bob_Graham.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2f03900854fedbf79e3229dcd940b2f0c7f53677 Binary files /dev/null and b/tools/face_recognition_service/Database/train/Bob_Graham.jpg differ diff --git a/tools/face_recognition_service/Database/train/Carlos_Ortega.jpg b/tools/face_recognition_service/Database/train/Carlos_Ortega.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bfb1f9e3d318e80ee0578b791fed944b41be4936 Binary files /dev/null and b/tools/face_recognition_service/Database/train/Carlos_Ortega.jpg differ diff --git a/tools/face_recognition_service/Database/train/Cindy_Crawford.jpg b/tools/face_recognition_service/Database/train/Cindy_Crawford.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e788f7ff6879f809f3e3a93ebc2f2aafc7dca7e8 Binary files /dev/null and b/tools/face_recognition_service/Database/train/Cindy_Crawford.jpg differ diff --git a/tools/face_recognition_service/Database/train/Monica_Seles.jpg b/tools/face_recognition_service/Database/train/Monica_Seles.jpg new file mode 100644 index 0000000000000000000000000000000000000000..713019007834351024cfd33d572dd13fbc84be0a Binary files /dev/null and b/tools/face_recognition_service/Database/train/Monica_Seles.jpg differ diff --git a/tools/face_recognition_service/Database/train/Sally_Kirkland.jpg b/tools/face_recognition_service/Database/train/Sally_Kirkland.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b3cbfe16a4ddf6b944953a5194ba0274a3da8d82 Binary files /dev/null and b/tools/face_recognition_service/Database/train/Sally_Kirkland.jpg differ diff --git a/tools/face_recognition_service/Database/train/Vanessa_Redgrave.jpg b/tools/face_recognition_service/Database/train/Vanessa_Redgrave.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e2ea52babd45f30a59d7d7b5a8bc88725989b6e1 Binary files /dev/null and b/tools/face_recognition_service/Database/train/Vanessa_Redgrave.jpg differ diff --git a/tools/face_recognition_service/Database/val/Aaron_Sorkin.jpg b/tools/face_recognition_service/Database/val/Aaron_Sorkin.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a7959c51ba1d9ff8b5e93b1106e91c72568c59a9 Binary files /dev/null and b/tools/face_recognition_service/Database/val/Aaron_Sorkin.jpg differ diff --git a/tools/face_recognition_service/Database/val/Anwar_Ibrahim.jpg b/tools/face_recognition_service/Database/val/Anwar_Ibrahim.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1f9369001d2b54808d9582b79a3a1314e8194690 Binary files /dev/null and b/tools/face_recognition_service/Database/val/Anwar_Ibrahim.jpg differ diff --git a/tools/face_recognition_service/Database/val/Bob_Graham.jpg b/tools/face_recognition_service/Database/val/Bob_Graham.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dbb1be1dbccc189e07c0475bfe3b5930063eca6e Binary files /dev/null and b/tools/face_recognition_service/Database/val/Bob_Graham.jpg differ diff --git a/tools/face_recognition_service/Database/val/Carlos_Ortega.jpg b/tools/face_recognition_service/Database/val/Carlos_Ortega.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4255a3a08f435e9f84b844b498210cd3c528b5a7 Binary files /dev/null and b/tools/face_recognition_service/Database/val/Carlos_Ortega.jpg differ diff --git a/tools/face_recognition_service/Database/val/Cindy_Crawford.jpg b/tools/face_recognition_service/Database/val/Cindy_Crawford.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2502f6baaacc4a75085b635696ae2aec19202a21 Binary files /dev/null and b/tools/face_recognition_service/Database/val/Cindy_Crawford.jpg differ diff --git a/tools/face_recognition_service/Database/val/Monica_Seles.jpg b/tools/face_recognition_service/Database/val/Monica_Seles.jpg new file mode 100644 index 0000000000000000000000000000000000000000..38b2e685b1079467b8a01a6e0bff73b2bd9a92ba Binary files /dev/null and b/tools/face_recognition_service/Database/val/Monica_Seles.jpg differ diff --git a/tools/face_recognition_service/Database/val/Sally_Kirkland.jpg b/tools/face_recognition_service/Database/val/Sally_Kirkland.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5201ead274f86dbcac944bfa65a1c286b21496b9 Binary files /dev/null and b/tools/face_recognition_service/Database/val/Sally_Kirkland.jpg differ diff --git a/tools/face_recognition_service/Database/val/Vanessa_Redgrave.jpg b/tools/face_recognition_service/Database/val/Vanessa_Redgrave.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1087aade492ea0b009206a1506dba4246b1fdbc0 Binary files /dev/null and b/tools/face_recognition_service/Database/val/Vanessa_Redgrave.jpg differ diff --git a/tools/face_recognition_service/README.md b/tools/face_recognition_service/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c22cf0ad3772cc4f0c06529a76e2afac51f30bb7 --- /dev/null +++ b/tools/face_recognition_service/README.md @@ -0,0 +1,69 @@ +# 人脸识别项目 + +这个项目是一个用于人脸识别的Python应用程序。它利用计算机视觉技术和深度学习模型来识别人脸并与预先构建的数据库进行比较。您可以通过本地图像文件或相机捕获的实时图像来执行人脸识别。本项目可以在openEuler系统下正常使用。 + +## 依赖项 + +在运行该应用程序之前,请确保已安装以下依赖项: + +- OpenCV +- NumPy +- Faiss +- InsightFace + +您可以使用以下命令来安装这些依赖项: + +``` +pip install opencv-python numpy faiss-cpu insightface +``` + +## 使用方法 + +您可以使用以下命令行参数来运行该应用程序: + +- `--image_path`: 本地照片文件路径。使用此选项可以对单个本地图像进行人脸识别。 +- `--camera`: 使用相机识别。使用此选项可以打开摄像头并进行实时人脸识别。 +- `--build`: 建立数据库。使用此选项可以构建人脸数据库,需要提供包含用于建立数据库的图像的文件夹地址。 +- `--img_fold`: 构建数据库所使用的图像文件夹地址。在使用 `--build` 选项时,指定包含用于建立数据库的图像的文件夹。 +- `--save_dir`: 数据库保存地址。指定数据库文件的保存路径。 +- `--add`: 添加人脸数据。使用此选项可以将新的人脸数据添加到现有的数据库中,需要提供要添加的图像文件的路径。 + +### 示例用法 + +- 使用本地照片进行人脸识别: + +``` +python main.py --image_path /path/to/your/image.jpg +``` + +- 使用相机进行实时人脸识别: + +``` +python main.py --camera +``` + +- 建立人脸数据库: + +``` +python main.py --build --img_fold /path/to/database/images --save_dir /path/to/database/database.npz +``` + +- 添加人脸数据到数据库: + +``` +python main.py --add /path/to/new/face/image.jpg --save_dir /path/to/database/database.npz +``` + +## 注意事项 + +- 请确保图像文件的路径正确,并且文件存在。 +- 当使用 `--build` 选项构建数据库时,您需要提供包含足够多人脸图像的文件夹,以便构建一个具有良好识别性能的数据库。 +- 使用 `--add` 选项时,请确保提供的图像包含有效的人脸,并且已经在数据库中有相应的标签。 + +## 作者 + +- 朱一杰 + +## 许可证 + +此项目根据 MulanPSL-2.0 许可。 \ No newline at end of file diff --git a/tools/face_recognition_service/SimHei.ttf b/tools/face_recognition_service/SimHei.ttf new file mode 100644 index 0000000000000000000000000000000000000000..60a4819db82ba2670bed0dec143b370346b7fb30 Binary files /dev/null and b/tools/face_recognition_service/SimHei.ttf differ diff --git a/tools/face_recognition_service/src/add_data.py b/tools/face_recognition_service/src/add_data.py new file mode 100644 index 0000000000000000000000000000000000000000..e0a327375c8fa9d44e6d66e548108aae21c350f7 --- /dev/null +++ b/tools/face_recognition_service/src/add_data.py @@ -0,0 +1,51 @@ +import os +from face_detect import * +from utils import crop_and_expand +from cfg import cfg + +# 先剪裁出人脸位置,再提特征,最后保存到数据库中 + +def add_database(image_path, save_dir): + # 获取access_token + token_info = get_access_toke_from_client_infos(cfg.CLIENT_ID, cfg.CLIENT_SECRET) + + # 准备FaceAnalysis模型 + model = insightface.app.FaceAnalysis() + model.prepare(ctx_id=0, det_thresh=0.3) + + # 声明一个数据库实例 + database = FaceRecognitionDatabase() + database.load_database("../Database/database.npz") + + # 读取图像 + image = cv2.imread(image_path) + + f = open(image_path, 'rb') + image_data = f.read() + image_base64 = base64.b64encode(image_data) + + # 利用获取的access_token调用推理接口 + if token_info: + inference_ret = face_detection(INFERENCE_TYPE, token_info["access_token"], image_base64) + image = crop_and_expand(image, inference_ret) + + # 利用FaceAnalysis模型提取特征 + face_result = model.get(image) + + # 仅考虑检测到单张人脸的情况 + if len(face_result) == 1: + # 获取特征向量 + feature_vector = face_result[0].embedding + # 去除图像名称的后缀 + file_name = os.path.basename(image_path) + name = os.path.splitext(file_name)[0] + + # 将特征向量和名称添加到数据库中 + database.add_to_database(feature_vector, name) + else: + print(f'{name}未检测到人脸') + + # 保存数据库 + database.save_database(save_dir) + + print("数据库建立完成") diff --git a/tools/face_recognition_service/src/build_Database.py b/tools/face_recognition_service/src/build_Database.py new file mode 100644 index 0000000000000000000000000000000000000000..805b8bc1bb65e4b452c1d77bb79b0ea07a5b226e --- /dev/null +++ b/tools/face_recognition_service/src/build_Database.py @@ -0,0 +1,56 @@ +import os +import numpy as np +import cv2 +import faiss +import insightface +from face_detect import * +from utils import crop_and_expand +from cfg import cfg + +# 先剪裁出人脸位置,再提特征,最后保存到数据库中 + +def build_database(image_folder_path, save_dir): + # 获取access_token + token_info = get_access_toke_from_client_infos(cfg.CLIENT_ID, cfg.CLIENT_SECRET) + + # 准备FaceAnalysis模型 + model = insightface.app.FaceAnalysis() + model.prepare(ctx_id=0, det_thresh=0.5) + + # 声明一个数据库实例 + database = FaceRecognitionDatabase() + + # 读取图片文件夹中的图片,并提取特征保存到数据库中 + for filename in os.listdir(image_folder_path): + # 读取图像 + image_path = os.path.join(image_folder_path, filename) + image = cv2.imread(image_path) + + f = open(image_path, 'rb') + image_data = f.read() + image_base64 = base64.b64encode(image_data) + + # 利用获取的access_token调用推理接口 + if token_info: + inference_ret = face_detection(INFERENCE_TYPE, token_info["access_token"], image_base64) + image = crop_and_expand(image, inference_ret) + + # 利用FaceAnalysis模型提取特征 + face_result = model.get(image) + + # 去除图像名称的后缀 + name = os.path.splitext(filename)[0] + + # 仅考虑检测到单张人脸的情况 + if len(face_result) == 1: + # 获取特征向量 + feature_vector = face_result[0].embedding + # 将特征向量和名称添加到数据库中 + database.add_to_database(feature_vector, name) + else: + print(f'{name}未检测到人脸或有多张人脸,请重新拍照') + + # 保存数据库 + database.save_database(save_dir) + + print("数据库建立完成") diff --git a/tools/face_recognition_service/src/camera.py b/tools/face_recognition_service/src/camera.py new file mode 100644 index 0000000000000000000000000000000000000000..ec7abdaad1cd411ae17b291489c3164aae4610a3 --- /dev/null +++ b/tools/face_recognition_service/src/camera.py @@ -0,0 +1,128 @@ +import base64 +import json +from urllib import parse +import requests +from PIL import Image, ImageDraw +import cv2 +import numpy as np +from face_detect import * +from utils import crop_and_expand, draw_detection_boxes +from cfg import cfg +import warnings + +# 关闭控制台所有的警告输出 +warnings.filterwarnings("ignore") + +def use_camera(): + """ + 调用摄像头,并使用接口进行人脸检测 + :return: + """ + INFERENCE_TYPE = "face_detection" + + # 准备模型 + model = insightface.app.FaceAnalysis() + model.prepare(ctx_id=0, det_thresh=0.3) + + # 创建FaceRecognitionDatabase实例并加载数据库 + database = FaceRecognitionDatabase() + database.load_database("../Database/database.npz") + + cap = cv2.VideoCapture(0) + frame_count = 0 # 计数器,用于控制每10帧进行一次推理 + while True: + ret, frame = cap.read() + + if ret: + frame_count += 1 + if frame_count == 10: # 每10帧进行推理 + frame_count = 0 # 重置计数器 + + # 获取摄像头的一帧图像并编码 + img_data = cv2.imencode('.jpg', frame)[1] + image_base64 = base64.b64encode(img_data) + + # 获取access_token + token_info = get_access_toke_from_client_infos(cfg.CLIENT_ID, cfg.CLIENT_SECRET) + # 利用获取的access_token调用推理接口 + if token_info: + inference_ret = face_detection(INFERENCE_TYPE, token_info["access_token"], image_base64) + image = crop_and_expand(frame, inference_ret) + try: + print(f"Inference result is: {inference_ret}") + # 提取特征 + res = model.get(image) + try: + emb1 = res[0].embedding + except: + continue + + result = None + if emb1 is not None: + # 使用数据库中的相似度查找函数 + result = database.search_similar_faces(emb1, cfg.cosine_similarity_threshold) + if result is not None: + name, _, _ = result + else: + name = 'None' + # 如果检测到人脸以及相应的位置,就在结果图上画框并显示出来 + draw_detection_boxes(inference_ret, frame, name) + + except Exception as err: + print(err) + break + else: + break + + cap.release() + cv2.destroyAllWindows() + +def no_camera(image_path): + INFERENCE_TYPE = "face_detection" + + # 准备模型 + model = insightface.app.FaceAnalysis() + model.prepare(ctx_id=0, det_thresh=0.3) + + # 创建FaceRecognitionDatabase实例并加载数据库 + database = FaceRecognitionDatabase() + database.load_database("../Database/database.npz") + + # 读取验证图像 + image = cv2.imread(image_path) + + f = open(image_path, 'rb') + image_data = f.read() + image_base64 = base64.b64encode(image_data) + + # 获取access_token + token_info = get_access_toke_from_client_infos(cfg.CLIENT_ID, cfg.CLIENT_SECRET) + # 利用获取的access_token调用推理接口 + if token_info: + inference_ret = face_detection(INFERENCE_TYPE, token_info["access_token"], image_base64) + image = crop_and_expand(image, inference_ret) + try: + print(f"Inference result is: {inference_ret}") + # 提取特征 + res = model.get(image) + try: + emb1 = res[0].embedding + except Exception as err: + print(err) + + result = None + if emb1 is not None: + # 使用数据库中的相似度查找函数 + result = database.search_similar_faces(emb1, cfg.cosine_similarity_threshold) + if result is not None: + name, _, _ = result + else: + name = 'None' + + print(name) + except Exception as err: + print(err) + + +if __name__ == "__main__": + use_camera() diff --git a/tools/face_recognition_service/src/cfg.py b/tools/face_recognition_service/src/cfg.py new file mode 100644 index 0000000000000000000000000000000000000000..aa55ce2881ba7f4ade554d6323f80e5b43ccecef --- /dev/null +++ b/tools/face_recognition_service/src/cfg.py @@ -0,0 +1,8 @@ +from easydict import EasyDict + +# 创建一个包含 CLIENT_ID 和 CLIENT_SECRET 的字典 +cfg = EasyDict({ + 'CLIENT_ID': '2b96bc92a1e5406cacfc26846245b717', + 'CLIENT_SECRET': 'cbec5898006947a73c8b4ef8e0067673729c280313581b56', + "cosine_similarity_threshold": 0.5 +}) diff --git a/tools/face_recognition_service/src/face_detect.py b/tools/face_recognition_service/src/face_detect.py new file mode 100644 index 0000000000000000000000000000000000000000..b8ccb96b34d594575fce277c6d1ad536f5aadfdb --- /dev/null +++ b/tools/face_recognition_service/src/face_detect.py @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +import base64 +import json +from urllib import parse +import insightface +import cv2 +import requests +import numpy as np +import faiss + +INFERENCE_TYPE = "face_detection" + +def get_access_toke_from_client_infos(client_id, client_secret): + try: + headers = { + "Content-Type": "application/x-www-form-urlencoded" + } + send_data = {"grant_type": 'client_credentials', + "client_id": client_id, + "client_secret": client_secret} + resp = requests.post(url="https://studio.e.huawei.com/baas/auth/v1.0/oauth2/token", + headers=headers, + data=parse.urlencode(send_data), + verify=False) + return resp.json() + except requests.exceptions.RequestException as err: + print(err) + return {} + + +def face_detection(inference_type, access_token, image_base64): + # 请求body体 + send_data = { + "name": inference_type, + "dataInputs": {"images": [{"image": image_base64.decode(), "type": "base64"}]} + } + + # 请求header + headers = { + "access-Token": access_token, + "Content-Type": "application/json" + } + try: + resp = requests.post(url="https://studio.e.huawei.com/ai-enable/v1.0/services/invoke", + headers=headers, + data=json.dumps(send_data), + verify=False) + return resp.json() + except Exception as err: + print(err) + return {} + +class FaceRecognitionDatabase: + def __init__(self): + self.feature_matrix = np.empty((0, 512), dtype=np.float32) + self.face_names = [] + self.faiss_index = None + + def build_faiss_database(self): + if self.feature_matrix.shape[0] > 0: + d = self.feature_matrix.shape[1] + self.faiss_index = faiss.IndexFlatIP(d) + self.faiss_index.add(self.feature_matrix) + + + def search_similar_faces(self, query_vector, cosine_similarity_threshold): + if self.faiss_index is None: + raise ValueError("Faiss index is not built. Please add vectors to the database and build the index.") + + k = 1 + _, indices = self.faiss_index.search(np.expand_dims(query_vector, axis=0), k) + + query_vector_norm = np.linalg.norm(query_vector) + feature_vector_norm = np.linalg.norm(self.feature_matrix[indices[0][0]]) + + cosine_similarity = np.dot(query_vector, self.feature_matrix[indices[0][0]]) / (query_vector_norm * feature_vector_norm) + + if cosine_similarity < cosine_similarity_threshold: + return None + else: + similar_name = self.face_names[indices[0][0]] + similar_vector = self.feature_matrix[indices[0][0]] + return similar_name, similar_vector, cosine_similarity + + def add_to_database(self, new_feature_vector, face_name): + assert new_feature_vector.shape[0] == self.feature_matrix.shape[1], "维度不匹配" + self.feature_matrix = np.vstack([self.feature_matrix, new_feature_vector]) + self.face_names.append(face_name) + if self.faiss_index is None: + self.build_faiss_database() + else: + self.faiss_index.add(np.expand_dims(new_feature_vector, axis=0)) + + def save_database(self, save_dir): + np.savez(save_dir, feature_matrix=self.feature_matrix, face_names=self.face_names) + + def load_database(self, load_dir): + data = np.load(load_dir) + self.feature_matrix = data['feature_matrix'] + self.face_names = data['face_names'] + self.build_faiss_database() + + +if __name__ == '__main__': + # 先剪裁出人脸位置,提特征,最后比较 + + # 根据用户的aksk获取access_token + token_info = get_access_toke_from_client_infos(CLIENT_ID, CLIENT_SECRET) + # 利用获取的access_token调用推理接口 + if token_info: + inference_ret = face_detection(INFERENCE_TYPE, token_info["access_token"], "C:\\Users\\qinxialo\\Desktop\\2.jpg") + # print(f"Inference result is: {inference_ret}") + img1 = crop_and_expand("C:\\Users\\qinxialo\\Desktop\\2.jpg", inference_ret) + + model = insightface.app.FaceAnalysis() + model.prepare(ctx_id=0, det_thresh=0.45) + + # img1 = cv2.imread("C:\\Users\\qinxialo\\Desktop\\2.jpg") + res = model.get(img1) + emb1 = res[0].embedding + + inference_ret = face_detection(INFERENCE_TYPE, token_info["access_token"], "C:\\Users\\qinxialo\\Desktop\\5.jpg") + # print(f"Inference result is: {inference_ret}") + img2 = crop_and_expand("C:\\Users\\qinxialo\\Desktop\\5.jpg", inference_ret) + + # img2 = cv2.imread("C:\\Users\\qinxialo\\Desktop\\5.jpg") + res = model.get(img2) + emb2 = res[0].embedding + + similarity_score = cosine_similarity(emb1, emb2) + print("余弦相似度:", similarity_score) +# +# if __name__ == '__main__': +# # 不剪裁出人脸位置,提特征,最后比较 +# +# Database = FaceRecognitionDatabase() +# model = insightface.app.FaceAnalysis() +# model.prepare(ctx_id=0, det_thresh=0.45) +# +# img1 = cv2.imread("C:\\Users\\qinxialo\\Desktop\\2.jpg") +# res = model.get(img1) +# emb1 = res[0].embedding +# +# img2 = cv2.imread("C:\\Users\\qinxialo\\Desktop\\5.jpg") +# res = model.get(img2) +# emb2 = res[0].embedding +# +# img3 = cv2.imread("C:\\Users\\qinxialo\\Desktop\\4.jpg") +# res = model.get(img3) +# emb3 = res[0].embedding +# +# # 添加到数据库中 +# Database.add_to_database(emb1, "张三") +# Database.add_to_database(emb2, "张三") +# data = Database.search_similar_faces(emb3, 0.5) +# print(data) \ No newline at end of file diff --git a/tools/face_recognition_service/src/main.py b/tools/face_recognition_service/src/main.py new file mode 100644 index 0000000000000000000000000000000000000000..408b743716638a37bcc225ea7de8fe9eded27b4f --- /dev/null +++ b/tools/face_recognition_service/src/main.py @@ -0,0 +1,34 @@ +import os +import cv2 +import numpy as np +from face_detect import FaceRecognitionDatabase +import faiss +import insightface +from add_data import add_database +from build_Database import build_database +import warnings +import argparse +from camera import * + +# 关闭控制台所有的警告输出 +warnings.filterwarnings("ignore") + +parser = argparse.ArgumentParser(description="人脸识别程序") +parser.add_argument("--image_path", help="本地照片文件路径") +parser.add_argument("--camera", action="store_true", help="使用相机识别") +parser.add_argument("--build", action="store_true", help="建立database") +parser.add_argument("--img_fold", default="../Database/train", help="build所使用的图像文件夹地址") +parser.add_argument("--save_dir", default="../Database/database.npz", help="数据库保存地址") +parser.add_argument("--add", help="添加人脸数据,输入图像路径") + + +args = parser.parse_args() + +if args.camera: + use_camera() +elif args.image_path: + result = no_camera(args.image_path) +elif args.build: + build_database(args.img_fold, args.save_dir) +elif args.add: + add_database(args.add, args.save_dir) \ No newline at end of file diff --git a/tools/face_recognition_service/src/move_files.py b/tools/face_recognition_service/src/move_files.py new file mode 100644 index 0000000000000000000000000000000000000000..9c39d44382317771066df6b1605a62d6fc40d0d1 --- /dev/null +++ b/tools/face_recognition_service/src/move_files.py @@ -0,0 +1,34 @@ +import os +import shutil + +# 指定LFW数据集文件夹路径 +lfw_folder = 'D:\\pycharm_file\\openeuler\\Database\\lfw' + +# 指定训练数据和验证数据文件夹路径 +train_folder = 'D:\\pycharm_file\\openeuler\\Database\\train' +validate_folder = 'D:\\pycharm_file\\openeuler\\Database\\val' + +# 创建训练数据和验证数据文件夹 +os.makedirs(train_folder, exist_ok=True) +os.makedirs(validate_folder, exist_ok=True) + +# 遍历LFW数据集中的每个人的文件夹 +for person_name in os.listdir(lfw_folder): + person_folder = os.path.join(lfw_folder, person_name) + + # 确保是文件夹 + if os.path.isdir(person_folder): + # 获取该人的所有图像文件 + image_files = os.listdir(person_folder) + + # 确保至少有一张图像 + if len(image_files) > 0: + # 复制第一张图像到训练文件夹,并更改文件名为人名 + first_image = image_files[0] + shutil.copy2(os.path.join(person_folder, first_image), os.path.join(train_folder, f"{person_name}.jpg")) + + # 复制其余的图像到验证文件夹,保持原始文件名 + for image_file in image_files[1:]: + shutil.copy2(os.path.join(person_folder, image_file), os.path.join(validate_folder, image_file)) + +print("数据处理完成。") diff --git a/tools/face_recognition_service/src/utils.py b/tools/face_recognition_service/src/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..f03ddc43ac07329eef0213bcbcd94827d4889481 --- /dev/null +++ b/tools/face_recognition_service/src/utils.py @@ -0,0 +1,67 @@ +import numpy as np +import cv2 +from PIL import Image, ImageDraw + +def cosine_similarity(vector_a, vector_b): + # 计算向量的余弦相似度 + dot_product = np.dot(vector_a, vector_b) # 计算点积 + norm_a = np.linalg.norm(vector_a) # 计算向量A的模长 + norm_b = np.linalg.norm(vector_b) # 计算向量B的模长 + similarity = dot_product / (norm_a * norm_b) # 计算余弦相似度 + return similarity + +def draw_detection_boxes(inference_ret, frame, name): + + # 如果检测到人脸以及相应的位置,就在结果图上画框并显示出来 + if len(inference_ret["result"]) > 0: + for i in range(len(inference_ret["result"])): + for j in range(len(inference_ret["result"][i]["infos"])): + # 把一次检测出的多张人脸都画在一张图上,并显示出来 + location = inference_ret["result"][i]["infos"][j]["location"] + height, top_left_x, top_left_y, width = location["height"], location["top_left_x"], \ + location["top_left_y"], location["width"] + + # 绘制人脸框 + img = frame.copy() # 创建图像的副本以免影响原图像 + cv2.rectangle(img, (top_left_x, top_left_y), (top_left_x + width, top_left_y + height), (0, 0, 255), 2) + + # chinese_font_path = "../SimHei.ttf" + chinese_font = cv2.FONT_HERSHEY_SIMPLEX + text_position = (top_left_x, top_left_y - 10) # 文本位置稍微上移一些 + cv2.putText(img, name, text_position, chinese_font, 0.6, (0, 0, 255), 2) + + # 显示图像 + cv2.imshow('FaceDetect', img) + + if cv2.waitKey(1) & 0xFF == ord('q'): + break + +def crop_and_expand(image, detection_result): + # 检查检测是否成功以及是否检测到任何人脸 + if "resCode" in detection_result and detection_result["resCode"] == "0" and "result" in detection_result: + faces = detection_result["result"] + if len(faces) > 0 and "infos" in faces[0] and len(faces[0]["infos"]) > 0: + face_info = faces[0]["infos"][0] + location = face_info["location"] + top_left_x = int(location["top_left_x"]) + top_left_y = int(location["top_left_y"]) + width = int(location["width"]) + height = int(location["height"]) + + # 计算扩展区域 + expand_width = width // 2 + expand_height = height // 2 + + # 确保扩展区域在图像边界内 + expanded_top_left_x = max(top_left_x - expand_width, 0) + expanded_top_left_y = max(top_left_y - expand_height, 0) + expanded_bottom_right_x = min(top_left_x + width + expand_width, image.shape[1]) + expanded_bottom_right_y = min(top_left_y + height + expand_height, image.shape[0]) + + # 裁剪扩展区域 + cropped_image = image[expanded_top_left_y:expanded_bottom_right_y, expanded_top_left_x:expanded_bottom_right_x] + + return cropped_image + + # 如果未检测到人脸或检测失败,则返回None + return image diff --git a/tools/face_recognition_service/test/test.py b/tools/face_recognition_service/test/test.py new file mode 100644 index 0000000000000000000000000000000000000000..90a5281a0c50c3665d651b36216f4678ad29d572 --- /dev/null +++ b/tools/face_recognition_service/test/test.py @@ -0,0 +1,68 @@ +import os +import cv2 +import numpy as np +from src.face_detect import FaceRecognitionDatabase +import faiss +import insightface +from src.build_Database import build_database +import warnings + +# 关闭控制台所有的警告输出 +warnings.filterwarnings("ignore") + +#建立数据库database +build_database("../Database/train", "../Database/database.npz") + +# 指定验证数据集的文件夹路径 +val_folder = '../Database/val' # 请替换为您的验证数据集文件夹路径 + +# 创建FaceRecognitionDatabase实例并加载数据库 +database = FaceRecognitionDatabase() +database.load_database("../Database/database.npz") + +# 准备FaceAnalysis模型 +model = insightface.app.FaceAnalysis() +model.prepare(ctx_id=0, det_thresh=0.3) + +# 设置相似度阈值 +cosine_similarity_threshold = 0.5 # 根据需要调整阈值 + +# 计数器,用于统计正确识别的人脸数 +correct_count = 0 +total_count = 0 + +# 遍历验证数据集中的图像 +for filename in os.listdir(val_folder): + image_path = os.path.join(val_folder, filename) + + # 读取验证图像 + image = cv2.imread(image_path) + + # 提取特征 + res = model.get(image) + try: + emb1 = res[0].embedding + except: + print(res) + continue + + if emb1 is not None: + # 使用数据库中的相似度查找函数 + result = database.search_similar_faces(emb1, cosine_similarity_threshold) + + if result is not None: + similar_name, _, _ = result + # 获取验证图像的文件名(去除后缀) + val_name = os.path.splitext(filename)[0] + + # 检查是否正确识别 + if similar_name == val_name: + correct_count += 1 + + total_count += 1 + +# 计算正确率 +accuracy = correct_count / total_count if total_count > 0 else 0 +print(f"正确识别人脸数: {correct_count}") +print(f"总人脸数: {total_count}") +print(f"识别准确率: {accuracy * 100:.2f}%")