commit 0190d1230f22bf33f64a4722c24c6ccb7773169f Author: haotian <2421912570@qq.com> Date: Mon Jul 21 11:10:04 2025 +0800 现在能运行. 主体文件为faceApp.py和config.yaml diff --git a/compreface_utils/DataUtils.py b/compreface_utils/DataUtils.py new file mode 100644 index 0000000..65b5fc7 --- /dev/null +++ b/compreface_utils/DataUtils.py @@ -0,0 +1,100 @@ +import requests +import json +import datetime + +def group_get_subjects(faces_data): + grouped_faces = {} + for face in faces_data['faces']: + subject = face['subject'] + image_id = face['image_id'] + if subject in grouped_faces: + grouped_faces[subject].append(image_id) + else: + grouped_faces[subject] = [image_id] + return grouped_faces + + +def filter_images_by_subject(data, subject): + # 初始化一个空列表来存储匹配的image_id + image_ids = [] + + # 遍历data中的faces列表 + for face in data['faces']: + # 检查face字典中的'subject'键是否与传入的subject相匹配 + if face['subject'] == subject: + # 如果匹配,将'image_id'添加到列表中 + image_ids.append(face['image_id']) + # 返回包含所有匹配image_id的列表 + return image_ids + + +# 该方法最后的返回结果是 打卡的人或者是陌生人 +def getMaxSimilaritySubject(recognition_face_data): + first_result = recognition_face_data['result'][0] + # 从first_result中获取Box的probability + box_probability = first_result['box']['probability'] + # 先判断是否存在人脸 + if box_probability > 0.9: + recognition_subject_list = first_result['subjects'] + # TODO 此处判断最为相似的subject,如果recognition_subject 低于阈值 直接返回陌生人 + recognition_subject = recognition_subject_list[0] + + +# TODO postMsg 发送请求 +# 1. 判断当前姓名,是否已经打卡过,若打卡过则不处理 +# 2. minio保存,发送请求 +def postMsg(recognition_name,temp_path,clock_in_dict) : + # 判断当前 recognition_name 之前是否已经在打卡了 + # 若打卡则直接返回 + if recognition_name in clock_in_dict : + return + + # TODO + # 1. 保存minio + # 2. 发送请求 + send_post_request() + return + +def send_post_request(url, token, msg, picUrl, videoUrl): + payload = { + "channelNo": 'ip', + "alarmContent": msg, + "alarmTime": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + "picInfo": [ + {"url": picUrl} + ], + "videoInfo": [ + {"url": videoUrl} + ] + } + headers = { + 'X-Access-Token': token, + 'Content-Type': 'application/json' + } + response = requests.post(url, headers=headers, data=json.dumps(payload)) + print(response) + + +def getFacelist(data): + # 解析JSON数据 + parsed_data = json.loads(json.dumps(data)) + + # 提取faces中的数据 + faces = parsed_data['faces'] + + # 用于存储唯一的subject + unique_subjects = set() + + # 用于存储过滤后的face + filtered_faces = [] + + # 遍历faces + for face in faces: + subject = face['subject'] + + # 如果subject是唯一的,则将其添加到unique_subjects集合和filtered_faces列表中 + if subject not in unique_subjects: + unique_subjects.add(subject) + filtered_faces.append(face) + return filtered_faces + diff --git a/compreface_utils/FaceUtils.py b/compreface_utils/FaceUtils.py new file mode 100644 index 0000000..78e81a2 --- /dev/null +++ b/compreface_utils/FaceUtils.py @@ -0,0 +1,6 @@ +# +def add_face_by_name(image_path,subject,face_collection): + face_collection.add(image_path=image_path, subject=subject) + + +# 分组 diff --git a/compreface_utils/config.yaml b/compreface_utils/config.yaml new file mode 100644 index 0000000..637816a --- /dev/null +++ b/compreface_utils/config.yaml @@ -0,0 +1,8 @@ +compreface_service: + DOMAIN: 'http://10.0.0.18' + PORT: '8000' + API_KEY: 'db1c448e-2076-4543-ae9f-11d8d7e7eb51' + +recognize_ip: + v1: '192.168.50.5:8088/config' + diff --git a/compreface_utils/test.py b/compreface_utils/test.py new file mode 100644 index 0000000..352b4d8 --- /dev/null +++ b/compreface_utils/test.py @@ -0,0 +1,76 @@ +import FaceUtils, DataUtils +from compreface import CompreFace +import yaml +from compreface.service import RecognitionService +from compreface.collections import FaceCollection +from compreface.collections.face_collections import Subjects +import cv2 +import tempfile +import json +import os +from flask import Flask, request, jsonify + +# with open('config.yaml', 'r') as file: +# configData = yaml.safe_load(file) +# DOMAIN: str = configData['compreface_service']['DOMAIN'] +# PORT: str = configData['compreface_service']['PORT'] +# API_KEY: str = configData['compreface_service']['API_KEY'] +# compre_face: CompreFace = CompreFace(DOMAIN, PORT) +# # recognition 是服务实例 +# recognition: RecognitionService = compre_face.init_face_recognition(API_KEY) +# # face_collection是人脸集合 +# face_collection: FaceCollection = recognition.get_face_collection() +# subjects: Subjects = recognition.get_subjects() +# +# recognition_face_data = recognition.recognize(image_path=r'C:\Users\admin\Desktop\项目\jingzhu\face_project\compreface_utils\5.jpg') +# print(recognition_face_data) +import cv2 + + +def draw_faces(image_path, recognition_data): + # 读取图像 + image = cv2.imread(r'C:\Users\admin\Desktop\imgs\jingzhuImgs\5.jpg') + + # 检查图像是否成功加载 + if image is None: + print("Failed to load image.") + return + + # 遍历识别结果中的每一个结果 + for face_data in recognition_data['result']: + # 获取边界框坐标 + box = face_data['box'] + x_min = box['x_min'] + y_min = box['y_min'] + x_max = box['x_max'] + y_max = box['y_max'] + + # 画出边界框 + cv2.rectangle(image, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2) + + # 获取名称(如果有) + if face_data['subjects']: + subject_name = face_data['subjects'][0]['subject'] + # 在框下方显示名字 + cv2.putText(image, subject_name, (x_min, y_max + 20), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) + + # 显示图像 + cv2.imwrite('out.jpg', image) + cv2.waitKey(0) + cv2.destroyAllWindows() + + +# 测试数据和函数 +recognition_face_data = { + 'result': [ + {'box': {'probability': 0.99981, 'x_max': 1207, 'y_max': 1348, 'x_min': 1092, 'y_min': 1234}, + 'subjects': [{'subject': 'liuxing', 'similarity': 0.45167}]}, + {'box': {'probability': 0.99575, 'x_max': 853, 'y_max': 1308, 'x_min': 759, 'y_min': 1220}, + 'subjects': [{'subject': 'liudehua', 'similarity': 0.9288}]}, + {'box': {'probability': 0.87615, 'x_max': 255, 'y_max': 1484, 'x_min': 175, 'y_min': 1388}, + 'subjects': [{'subject': 'tangzong', 'similarity': 0.48748}]} + ] +} + +# 调用函数 +draw_faces('0', recognition_face_data) \ No newline at end of file diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..3776781 --- /dev/null +++ b/config.yaml @@ -0,0 +1,8 @@ +compreface_service: + DOMAIN: 'http://10.0.0.202' + PORT: '8000' + API_KEY: 'ce04b456-88df-4df8-a7a2-69849111916f' + +recognize_ip: + v1: '192.168.50.5:8088/config' + diff --git a/faceApp.py b/faceApp.py new file mode 100644 index 0000000..74cea98 --- /dev/null +++ b/faceApp.py @@ -0,0 +1,237 @@ +from compreface_utils import FaceUtils, DataUtils +from compreface import CompreFace +from compreface.service import RecognitionService +from compreface.collections import FaceCollection +from compreface.collections.face_collections import Subjects +import yaml +import tempfile +import json +from flask_cors import CORS +import os +from flask import Flask, request, jsonify + +app = Flask(__name__) +CORS(app) + + +clock_in_dict = {} + +# 初始化 CompreFace 客户端 +with open('config.yaml', 'r') as file: + configData = yaml.safe_load(file) +DOMAIN: str = configData['compreface_service']['DOMAIN'] +PORT: str = configData['compreface_service']['PORT'] +API_KEY: str = configData['compreface_service']['API_KEY'] +compre_face: CompreFace = CompreFace(DOMAIN, PORT) +# recognition 是服务实例 +recognition: RecognitionService = compre_face.init_face_recognition(API_KEY) + + + + + +# 获取人员列表 +@app.route('/getSubjects') +def getSubjects(): + subjects: Subjects = recognition.get_subjects() + subjects_list = subjects.list() + return jsonify({"data": subjects_list}) + +# 添加人员 +@app.route('/addSubject', methods=['POST']) +def addSubject(): + subjects: Subjects = recognition.get_subjects() + data = request.json + subject_name = data.get('subject_name') + result = subjects.add(subject_name) + return jsonify({"data": result}) + +# 删除人员 +@app.route('/deleteSubject',methods=['POST']) +def deleteSubject(): + subjects: Subjects = recognition.get_subjects() + # face_collection是人脸集合 + face_collection: FaceCollection = recognition.get_face_collection() + data = request.json + subject_name = data.get('subject_name') + face_collection.delete_all(subject_name) + result = subjects.delete(subject_name) + return jsonify({"data": result}) + +# 更改人员名称 +@app.route('/renameSubject', methods=['POST']) +def renameSubject(): + subjects: Subjects = recognition.get_subjects() + data = request.json + old_subject_name = data.get('old_subject_name') + new_subject_name = data.get('new_subject_name') + result = subjects.update(old_subject_name, new_subject_name) + return jsonify({"data": result}) + + +# 按名字查询 +@app.route('/selectSubject', methods=['POST']) +def selectSubject(): + subjects: Subjects = recognition.get_subjects() + data = request.json + Query = data.get('query', []) + subject_list = subjects.list() + matching_subjects = [ + name for name in subject_list['subjects'] + if all(query in name for query in Query) + ] + return jsonify({"data": matching_subjects}),200 + + +# 获取图片id集合 +@app.route('/getFaceImgs', methods=['POST']) +def getFaceImgs(): + # face_collection是人脸集合 + face_collection: FaceCollection = recognition.get_face_collection() + data = request.json + subject_name = data.get('subject_name') + face_list = face_collection.list() + print(face_list) + filtered_ids = DataUtils.filter_images_by_subject(face_list, subject_name) + return jsonify({"data": filtered_ids}) + + +# 根据人名添加图片 +@app.route('/addFaceImg', methods=['POST']) +def addFaceImg(): + # face_collection是人脸集合 + face_collection: FaceCollection = recognition.get_face_collection() + # 获取图片文件和主题名称 + imgFile = request.files['img'] + subject_name = request.form.get('subject_name') + + # 检查是否成功获取了图片文件和主题名称 + if not imgFile or not subject_name: + return jsonify({'data': 'error'}), 400 + + try: + # 创建一个临时文件 + temp_dir = tempfile.mkdtemp() + temp_path = os.path.join(temp_dir, imgFile.filename) + imgFile.save(temp_path) + + # 这里可以继续执行你的人脸识别集合添加逻辑 + result = face_collection.add(image_path=temp_path, subject=subject_name) + print(result) + + + return jsonify({'data': result}) + finally: + # 删除临时文件和目录 + if os.path.exists(temp_path): + os.remove(temp_path) + os.rmdir(temp_dir) + + +# 根据image_id删除图片 +@app.route('/deleteFaceImg', methods=['POST']) +def deleteFaceImg(): + # face_collection是人脸集合 + face_collection: FaceCollection = recognition.get_face_collection() + data = request.json + image_id = data.get('image_id') + print(image_id) + result = face_collection.delete(image_id) + return jsonify({"data": result}) + + +# 修改识别配置 +@app.route('/config', methods=['POST']) +def config(): + data = request.json + start_time_config = data.get('start_time') + end_time_config = data.get('end_time') + frequency_face_config = data.get('frequency_face') + + + +# @app.route('/login', methods=['POST']) +# def login(): +# data = request.json +# username = data.get('username') +# password = data.get('password') +# if username == 'admin' and password == '12345678Aa': +# return 'success', 200 + + +# TODO +# 1. 先接收半个小时内的告警图片保存到本地 +# 2. 定时任务方法,将半个小时内的图片依次调用compreface接口,返回result 整理数据,删除本地图片 +# 2.1 整理数据 三种情况,工人,陌生人 ,脏数据 +# 置信值 > 0.8 ==>工人 0.5 < 置信值 < 0.8 ==>陌生人 置信值 < 0.5 ==>抛弃 + +@app.route('/compreface', methods=['POST']) +def receiveFrameToComprefaceOnly(): + if 'file' not in request.files: + return jsonify({"error": "No file part"}), 400 + + file = request.files['file'] + if file.filename == '': + return jsonify({"error": "No selected file"}), 400 + + if file: + # 保存文件到临时位置 + file_path = os.path.join("/tmp", file.filename) + file.save(file_path) + + # 使用 CompreFace SDK 进行面部识别 + result = recognition.recognize(file_path) + # 删除临时文件 + os.remove(file_path) + + return jsonify(result) + + + +if __name__ == '__main__': + app.run(port=12500 ,debug=True,host='0.0.0.0') + +# { +# "result" : [ { +# "age" : { +# "probability": 0.9308982491493225, +# "high": 32, +# "low": 25 +# }, +# "gender" : { +# "probability": 0.9898611307144165, +# "value": "female" +# }, +# "mask" : { +# "probability": 0.9999470710754395, +# "value": "without_mask" +# }, +# "embedding" : [ 9.424854069948196E-4, "...", -0.011415496468544006 ], +# "box" : { +# "probability" : 1.0,表示检测到的面部位置的置信度 TODO 可以通过这部分检测是否有人脸 +# "x_max" : 1420,表示检测到的面部在图像中的边界框坐标 TODO 画框 +# "y_max" : 1368, +# "x_min" : 548, +# "y_min" : 295 +# }, +# "landmarks" : [ [ 814, 713 ], [ 1104, 829 ], [ 832, 937 ], [ 704, 1030 ], [ 1017, 1133 ] ], +# "subjects" : [ { +# "similarity" : 0.97858, 百分之0.9的可能性是subject1 +# "subject" : "subject1" +# } ], +# "execution_time" : { +# "age" : 28.0, +# "gender" : 26.0, +# "detector" : 117.0, +# "calculator" : 45.0, +# "mask": 36.0 +# } +# } ], +# "plugins_versions" : { +# "age" : "agegender.AgeDetector", +# "gender" : "agegender.GenderDetector", +# "detector" : "facenet.FaceDetector", +# "calculator" : "facenet.Calculator", +# "mask": "facemask.MaskDetector" +# } +# } diff --git a/jingzhutest.py b/jingzhutest.py new file mode 100644 index 0000000..b07b1e5 --- /dev/null +++ b/jingzhutest.py @@ -0,0 +1,25 @@ +from compreface_utils import FaceUtils, DataUtils +from compreface import CompreFace +from compreface.service import RecognitionService +from compreface.collections import FaceCollection +from compreface.collections.face_collections import Subjects +import yaml +import tempfile +import json +from flask_cors import CORS +import os +from flask import Flask, request, jsonify + + +# 初始化 CompreFace 客户端 +with open('config.yaml', 'r') as file: + configData = yaml.safe_load(file) +DOMAIN: str = configData['compreface_service']['DOMAIN'] +PORT: str = configData['compreface_service']['PORT'] +API_KEY: str = configData['compreface_service']['API_KEY'] +compre_face: CompreFace = CompreFace(DOMAIN, PORT) +recognition: RecognitionService = compre_face.init_face_recognition(API_KEY) +face_collection: FaceCollection = recognition.get_face_collection() +face_list = face_collection.list() +print(face_list) +print(1) \ No newline at end of file