整体提交仓库

This commit is contained in:
haotian 2025-10-13 09:07:21 +08:00
parent 77a06bf2ae
commit 44b6f24739
8 changed files with 302 additions and 1 deletions

View File

@ -0,0 +1,11 @@
from urllib.parse import urlparse
url = "https://192.168.10.251:8001/artemis/test_v1"
parsed = urlparse(url)
path_and_query = parsed.path
if parsed.query:
path_and_query += "?" + parsed.query
print(path_and_query)

View File

@ -0,0 +1,25 @@
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
import datetime
import time
def my_job():
print("任务执行时间:", datetime.datetime.now())
if __name__ == '__main__':
scheduler = BlockingScheduler(timezone="Asia/Shanghai")
# # 每天凌晨 1 点执行
# scheduler.add_job(my_job, trigger="cron", hour=1, minute=0)
# 或者用 CronTrigger
trigger = CronTrigger(minute='*', second=0)
scheduler.add_job(my_job, trigger=trigger)
scheduler.start()
try:
while True:
time.sleep(1)
except (KeyboardInterrupt, SystemExit):
scheduler.shutdown()

View File

@ -0,0 +1,5 @@
import os
txt_path = "./test/image_base64.txt"
print(os.path.dirname(txt_path))
# os.makedirs(, exist_ok=True)

View File

@ -0,0 +1,18 @@
{
"result": [
{
"pose": {
"pitch": -13.898311223378556,
"roll": 0.8241647740114217,
"yaw": 0.30893387084981927
},
"box": {
"probability": 0.9989770650863647,
"x_max": 874,
"y_max": 1127,
"x_min": 375,
"y_min": 418
}
}
]
}

View File

@ -0,0 +1,33 @@
{
"result": [
{
"gender": {
"probability": 1.0,
"value": "male"
},
"box": {
"probability": 0.99898,
"x_max": 874,
"y_max": 1127,
"x_min": 375,
"y_min": 418
},
"subjects": [
{
"subject": "刘昊天_访客",
"similarity": 0.99991
}
],
"execution_time": {
"gender": 3.0,
"detector": 32.0,
"calculator": 9.0
}
}
],
"plugins_versions": {
"gender": "insightface.GenderDetector",
"detector": "insightface.FaceDetector@retinaface_r50_v1",
"calculator": "insightface.Calculator@arcface-r100-msfdrop75"
}
}

View File

@ -0,0 +1,79 @@
"""
系统定时任务
"""
from config.get_scheduler import scheduler
from apscheduler.triggers.cron import CronTrigger
from apscheduler.triggers.interval import IntervalTrigger
from module_admin.service.haikang_service import HaiKangService
from module_admin.service.compreface_service import ComprefaceService
from utils.log_util import logger
# 定时获取访客图片并上传compreface
async def download_visitor_image_and_upload_compreface():
"""
定时任务获取海康访客图片并上传到compreface进行人脸识别
同时删除已过期的访客人脸数据
执行频率每2分钟一次
"""
try:
logger.info('开始执行定时任务获取访客图片并上传compreface')
# 获取所有有效状态的访客图片visitorStatus=1表示正常状态
visitor_name_list = await HaiKangService.get_all_visitor_pictures(visitorStatus=1)
logger.info(f'获取到 {len(visitor_name_list)} 张有效访客图片')
# 如果有新的访客图片将访客图片上传到compreface
if visitor_name_list:
result = await ComprefaceService.face_addition_batch_service(visitor_name_list)
logger.info(f'访客图片上传compreface结果: {result}')
else:
logger.info('没有新的访客图片需要处理')
# 删除过期的访客人脸数据
# 从visitor_name_list中提取所有访客的名字
active_visitor_names = [name for _, name in visitor_name_list] if visitor_name_list else []
logger.info(f'开始删除过期访客人脸,当前有效访客数量: {len(active_visitor_names)}')
delete_result = await ComprefaceService.delete_expired_visitor_faces_service(active_visitor_names)
if delete_result.get('error'):
logger.error(f'删除过期访客失败: {delete_result.get("error")}')
else:
logger.info(
f'删除过期访客完成 - 成功删除: {delete_result.get("deleted_count")} 个, '
f'失败: {delete_result.get("failed_count")}'
)
if delete_result.get('deleted_subjects'):
logger.info(f'已删除的访客: {", ".join(delete_result.get("deleted_subjects"))}')
if delete_result.get('failed_subjects'):
logger.warning(f'删除失败的访客: {delete_result.get("failed_subjects")}')
logger.info('定时任务执行完成获取访客图片并上传compreface')
except Exception as e:
logger.error(f'定时任务执行失败获取访客图片并上传compreface - {str(e)}', exc_info=True)
# 初始化定时任务
def init_scheduled_tasks():
"""
初始化所有定时任务
在应用启动时调用此方法
"""
# 添加访客图片上传任务每2分钟执行一次
scheduler.add_job(
func=download_visitor_image_and_upload_compreface,
trigger=IntervalTrigger(minutes=2),
id='download_visitor_image_task',
name='定时获取访客图片并上传compreface',
replace_existing=True,
max_instances=1, # 同一时间只允许一个实例运行
)
logger.info('定时任务已添加download_visitor_image_and_upload_compreface (每2分钟执行一次)')

View File

@ -0,0 +1,130 @@
from utils.compreface_util import ComprefaceUtil
from config.env import ComprefaceConfig
class ComprefaceService(ComprefaceUtil):
"""compreface服务类"""
# 人脸检测
@classmethod
async def face_detection_service(cls, image, options: dict = {}):
""" 人脸检测
Args:
image_path (str): 图片路径
options (dict, optional): 检测参数. Defaults to {}.
Returns:
[type]: [description]
"""
options={
"limit": 0,
"det_prob_threshold": 0.8,
"prediction_count": 1,
# 可选参数 age,gender,landmarks,calculator
"face_plugins": "pose",
"status": "false",
}
result = await ComprefaceUtil.face_detection(image, options)
return result["result"]
# 人脸识别
@classmethod
async def face_recognition_service(cls, image, options: dict = {}):
""" 人脸识别
Args:
image_path (str): 图片路径
options (dict, optional): 参数. Defaults to {}.
Returns:
[type]: [description]
"""
result = await ComprefaceUtil.face_recognition(image, options)
subject = result.get('result')[0].get('subjects')[0]
name = subject.get('subject')
similarity = subject.get('similarity')
if similarity < ComprefaceConfig.COMPREFACE_SIMILARITY_THRESHOLD:
return {
"name": "未知",
"role": "陌生人"
}
else:
t = name.split("_")
return {
"name": t[0],
"role": t[1] if len(t) > 1 else "员工"
}
# 添加图像到人脸库
@classmethod
async def face_addition_service(cls, image, name):
result = await ComprefaceUtil.face_addition(image, name)
return result
# 批量添加图像到人脸库
@classmethod
async def face_addition_batch_service(cls, t):
result_list = []
for image, name in t:
result = await ComprefaceUtil.face_addition(image, name)
result_list.append(result)
return result_list
# 删除过期的访客人脸
@classmethod
async def delete_expired_visitor_faces_service(cls, active_visitor_names: list):
"""删除CompreFace中已过期的访客人脸数据
Args:
active_visitor_names (list): 当前有效的访客名字列表
Returns:
dict: 包含删除成功和失败的subject列表
"""
try:
# 获取CompreFace中所有的subjects
all_subjects_result = await ComprefaceUtil.get_all_subjects()
all_subjects = all_subjects_result.get('subjects', [])
deleted_subjects = []
failed_subjects = []
# 遍历所有subjects删除不在active_visitor_names中的访客
for subject in all_subjects:
# 假设访客的subject格式为 "姓名_访客" 或 "姓名"
# 只删除访客类型的人脸,员工人脸不删除
if subject not in active_visitor_names:
# 如果subject不在活跃访客列表中且不是员工员工一般包含"_员工"等标识)
# 这里假设访客没有特殊后缀,或者可以根据实际情况调整判断逻辑
# 如果subject包含"_员工"等标识,则跳过
if "_员工" in subject or "_职员" in subject or "_工作人员" in subject:
continue
try:
# 删除该subject
await ComprefaceUtil.delete_subject(subject)
deleted_subjects.append(subject)
except Exception as e:
failed_subjects.append({"subject": subject, "error": str(e)})
return {
"deleted_count": len(deleted_subjects),
"deleted_subjects": deleted_subjects,
"failed_count": len(failed_subjects),
"failed_subjects": failed_subjects
}
except Exception as e:
return {
"error": f"删除过期访客失败: {str(e)}",
"deleted_count": 0,
"deleted_subjects": [],
"failed_count": 0,
"failed_subjects": []
}

View File

@ -492,7 +492,7 @@ class HaikangUtil:
os.makedirs(save_path, exist_ok=True)
name = save_path.split('/')[-1]
save_path = os.path.join(save_path, name+".jpg")
save_path = os.path.join(save_path, name+"_访客"+".jpg")
with open(save_path, 'wb') as f:
for chunk in back.iter_bytes(chunk_size=8192):