最新可用
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
import json
|
||||
|
||||
from fastapi import APIRouter, Query, HTTPException
|
||||
from fastapi import APIRouter, Query, HTTPException,Request
|
||||
from mysql.connector import Error as MySQLError
|
||||
|
||||
from ds.db import db
|
||||
@ -108,7 +108,7 @@ def update_online_status_by_ip(client_ip: str, online_status: int) -> bool:
|
||||
# 原有接口保持不变
|
||||
# ------------------------------
|
||||
@router.post("/add", response_model=APIResponse, summary="创建设备信息")
|
||||
async def create_device(device_data: DeviceCreateRequest):
|
||||
async def create_device(device_data: DeviceCreateRequest, request: Request): # 注入Request对象
|
||||
# 原有代码保持不变
|
||||
conn = None
|
||||
cursor = None
|
||||
@ -125,11 +125,10 @@ async def create_device(device_data: DeviceCreateRequest):
|
||||
return APIResponse(
|
||||
code=200,
|
||||
message=f"设备IP {device_data.ip} 已存在,返回已有设备信息",
|
||||
data=DeviceResponse(**existing_device)
|
||||
data=DeviceResponse(** existing_device)
|
||||
)
|
||||
|
||||
from fastapi import Request
|
||||
request = Request(scope={"type": "http"})
|
||||
# 直接使用注入的request对象获取用户代理
|
||||
user_agent = request.headers.get("User-Agent", "").lower()
|
||||
|
||||
if user_agent == "default":
|
||||
@ -184,7 +183,6 @@ async def create_device(device_data: DeviceCreateRequest):
|
||||
finally:
|
||||
db.close_connection(conn, cursor)
|
||||
|
||||
|
||||
@router.get("/", response_model=APIResponse, summary="获取设备列表(支持筛选分页)")
|
||||
async def get_device_list(
|
||||
page: int = Query(1, ge=1, description="页码,默认第1页"),
|
||||
|
@ -6,15 +6,15 @@ from schema.face_schema import FaceCreateRequest, FaceUpdateRequest, FaceRespons
|
||||
from schema.response_schema import APIResponse
|
||||
from middle.auth_middleware import get_current_user
|
||||
from schema.user_schema import UserResponse
|
||||
from ocr.feature_extraction import BinaryFaceFeatureHandler
|
||||
|
||||
from util.face_util import add_binary_data,get_average_feature
|
||||
#初始化实例
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/faces",
|
||||
tags=["人脸管理"]
|
||||
)
|
||||
|
||||
# 创建 BinaryFaceFeatureHandler 的实例
|
||||
binary_face_feature_handler = BinaryFaceFeatureHandler()
|
||||
|
||||
|
||||
# ------------------------------
|
||||
@ -33,6 +33,8 @@ async def create_face(
|
||||
- ID 由数据库自动生成,无需前端传入
|
||||
- 暂不处理文件内容,eigenvalue 设为 None
|
||||
"""
|
||||
|
||||
# 调用你的方法
|
||||
conn = None
|
||||
cursor = None
|
||||
try:
|
||||
@ -45,14 +47,24 @@ async def create_face(
|
||||
# 把文件转为二进制数组
|
||||
file_content = await file.read()
|
||||
|
||||
# 调用人脸识别得到特征值
|
||||
# 计算特征值
|
||||
flag, eigenvalue = add_binary_data(file_content)
|
||||
|
||||
if flag == False:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="未检测到人脸"
|
||||
)
|
||||
|
||||
# 打印数组长度
|
||||
print(f"文件大小:{len(file_content)} 字节")
|
||||
|
||||
# 2. 插入数据库:无需传 ID(自增),只传 name 和 eigenvalue(None)
|
||||
insert_query = """
|
||||
INSERT INTO face (name, eigenvalue)
|
||||
VALUES (%s, %s)
|
||||
"""
|
||||
cursor.execute(insert_query, (face_create.name, None))
|
||||
cursor.execute(insert_query, (face_create.name, str(eigenvalue)))
|
||||
conn.commit()
|
||||
|
||||
# 3. 获取数据库自动生成的 ID(关键:用 LAST_INSERT_ID() 查刚插入的记录)
|
||||
@ -60,19 +72,45 @@ async def create_face(
|
||||
cursor.execute(select_new_query)
|
||||
created_face = cursor.fetchone()
|
||||
|
||||
if not created_face:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="创建人脸记录成功,但无法获取新创建的记录"
|
||||
)
|
||||
|
||||
return APIResponse(
|
||||
code=201,
|
||||
message=f"人脸记录创建成功(ID:{created_face['id']},文件名:{file.filename})",
|
||||
data=FaceResponse(**created_face)
|
||||
data=FaceResponse(** created_face)
|
||||
)
|
||||
except MySQLError as e:
|
||||
if conn:
|
||||
conn.rollback()
|
||||
raise Exception(f"创建人脸记录失败:{str(e)}") from e
|
||||
# 改为使用HTTPException
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"创建人脸记录失败:{str(e)}"
|
||||
) from e
|
||||
except Exception as e:
|
||||
# 捕获其他可能的异常
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"服务器错误:{str(e)}"
|
||||
) from e
|
||||
finally:
|
||||
await file.close() # 关闭文件流
|
||||
db.close_connection(conn, cursor)
|
||||
|
||||
# 调用人脸识别得到特征值(这里可以添加你的人脸识别逻辑)
|
||||
flag, eigenvalue = add_binary_data(file_content)
|
||||
if flag == False:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="未检测到人脸"
|
||||
)
|
||||
|
||||
# 将 eigenvalue 转为 str
|
||||
eigenvalue = str(eigenvalue)
|
||||
|
||||
# ------------------------------
|
||||
# 2. 获取单个人脸记录(不变,用自增ID查询)
|
||||
@ -104,18 +142,21 @@ async def get_face(
|
||||
data=FaceResponse(**face)
|
||||
)
|
||||
except MySQLError as e:
|
||||
raise Exception(f"查询人脸记录失败:{str(e)}") from e
|
||||
# 改为使用HTTPException
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"查询人脸记录失败:{str(e)}"
|
||||
) from e
|
||||
finally:
|
||||
db.close_connection(conn, cursor)
|
||||
|
||||
|
||||
# 后续 3.获取所有、4.更新、5.删除 接口(不变,仅用数据库自增的 ID 操作,无需修改)
|
||||
# 后续 3.获取所有、4.更新、5.删除 接口(修复异常处理)
|
||||
# ------------------------------
|
||||
# 3. 获取所有人脸记录(不变)
|
||||
# ------------------------------
|
||||
@router.get("", response_model=APIResponse, summary="获取所有人脸记录")
|
||||
async def get_all_faces(
|
||||
current_user: UserResponse = Depends(get_current_user)
|
||||
):
|
||||
conn = None
|
||||
cursor = None
|
||||
@ -130,10 +171,13 @@ async def get_all_faces(
|
||||
return APIResponse(
|
||||
code=200,
|
||||
message="所有人脸记录查询成功",
|
||||
data=[FaceResponse(**face) for face in faces]
|
||||
data=[FaceResponse(** face) for face in faces]
|
||||
)
|
||||
except MySQLError as e:
|
||||
raise Exception(f"查询所有人脸记录失败:{str(e)}") from e
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"查询所有人脸记录失败:{str(e)}"
|
||||
) from e
|
||||
finally:
|
||||
db.close_connection(conn, cursor)
|
||||
|
||||
@ -194,7 +238,10 @@ async def update_face(
|
||||
except MySQLError as e:
|
||||
if conn:
|
||||
conn.rollback()
|
||||
raise Exception(f"更新人脸记录失败:{str(e)}") from e
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"更新人脸记录失败:{str(e)}"
|
||||
) from e
|
||||
finally:
|
||||
db.close_connection(conn, cursor)
|
||||
|
||||
@ -234,7 +281,10 @@ async def delete_face(
|
||||
except MySQLError as e:
|
||||
if conn:
|
||||
conn.rollback()
|
||||
raise Exception(f"删除人脸记录失败:{str(e)}") from e
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=f"删除人脸记录失败:{str(e)}"
|
||||
) from e
|
||||
finally:
|
||||
db.close_connection(conn, cursor)
|
||||
|
||||
@ -249,38 +299,43 @@ def get_all_face_name_with_eigenvalue() -> dict:
|
||||
conn = None
|
||||
cursor = None
|
||||
try:
|
||||
# 1. 建立数据库连接并获取游标(dictionary=True使结果以字典形式返回)
|
||||
conn = db.get_connection()
|
||||
cursor = conn.cursor(dictionary=True)
|
||||
|
||||
# 只查询需要的字段,提高效率
|
||||
# 2. 执行SQL查询:只获取name非空的记录,减少数据传输
|
||||
query = "SELECT name, eigenvalue FROM face WHERE name IS NOT NULL"
|
||||
cursor.execute(query)
|
||||
faces = cursor.fetchall()
|
||||
faces = cursor.fetchall() # 返回结果:列表套字典,如 [{"name":"张三","eigenvalue":...}, ...]
|
||||
|
||||
# 先收集所有名称对应的特征值列表(处理重复名称)
|
||||
# 3. 收集同一名称对应的所有特征值(处理名称重复场景)
|
||||
name_to_eigenvalues = {}
|
||||
for face in faces:
|
||||
name = face["name"]
|
||||
eigenvalue = face["eigenvalue"]
|
||||
# 若名称已存在,追加特征值;否则新建列表存储
|
||||
if name in name_to_eigenvalues:
|
||||
name_to_eigenvalues[name].append(eigenvalue)
|
||||
else:
|
||||
name_to_eigenvalues[name] = [eigenvalue]
|
||||
|
||||
# 构建最终字典:重复名称取平均特征值,唯一名称直接取特征值
|
||||
# 4. 构建最终字典:重复名称取平均,唯一名称直接取特征值
|
||||
face_dict = {}
|
||||
for name, eigenvalues in name_to_eigenvalues.items():
|
||||
print("调用的特征值是:" + eigenvalues)
|
||||
|
||||
# 处理特征值:多个则求平均,单个则直接使用
|
||||
if len(eigenvalues) > 1:
|
||||
# 调用平均特征值计算方法
|
||||
face_dict[name] = binary_face_feature_handler.get_average_feature(eigenvalues)
|
||||
# 调用外部方法计算平均特征值(需确保binary_face_feature_handler已正确导入)
|
||||
face_dict[name] = get_average_feature(eigenvalues)
|
||||
else:
|
||||
# 取列表中唯一的特征值(避免value为列表类型)
|
||||
face_dict[name] = eigenvalues[0]
|
||||
|
||||
return face_dict
|
||||
|
||||
except MySQLError as e:
|
||||
# 捕获数据库异常,添加上下文信息后重新抛出(便于定位问题)
|
||||
raise Exception(f"获取人脸名称与特征值失败:{str(e)}") from e
|
||||
finally:
|
||||
# 确保资源释放
|
||||
db.close_connection(conn, cursor)
|
||||
# 5. 无论是否异常,均释放数据库连接和游标(避免资源泄漏)
|
||||
db.close_connection(conn, cursor)
|
Reference in New Issue
Block a user