246 lines
9.7 KiB
Python
Raw Normal View History

# func命名规范以func开头以postgres 中ai_model_list表的id 结尾。针对识别结果做二次功能计算
import numpy as np
# 人员聚集或者车辆聚集的计算方法中心点互相间的距离小于最小对角线2倍即为聚集
# coordinate_boxes 就是坐标集合
# 需要注意coordinate_boxes 的坐标集合,分别是 x1y1x2y2
def detect_crowd(coordinate_boxes, N=3, threshold_factor=2.0):
# 计算中心点和对角线长度
centers = []
diagonals = []
for box in coordinate_boxes:
x1, y1, x2, y2 = box
cx = (x1 + x2) / 2
cy = (y1 + y2) / 2
centers.append((cx, cy))
width = x2 - x1
height = y2 - y1
diagonal = np.sqrt(width ** 2 + height ** 2)
diagonals.append(diagonal)
# 构建邻接矩阵
n = len(centers)
adjacency_matrix = np.zeros((n, n), dtype=bool)
for i in range(n):
for j in range(i + 1, n):
dist = np.sqrt((centers[i][0] - centers[j][0]) ** 2 + (centers[i][1] - centers[j][1]) ** 2)
threshold = threshold_factor * min(diagonals[i], diagonals[j])
if dist < threshold:
adjacency_matrix[i][j] = True
adjacency_matrix[j][i] = True
# 查找聚集群组
visited = [False] * n
crowd_groups = []
for i in range(n):
if not visited[i]:
stack = [i]
group = []
while stack:
person = stack.pop()
if not visited[person]:
visited[person] = True
group.append(person)
for neighbor in range(n):
if adjacency_matrix[person][neighbor] and not visited[neighbor]:
stack.append(neighbor)
if len(group) >= N:
crowd_groups.append(group)
return len(crowd_groups) > 0, crowd_groups
# # 示例测试 前两个点事左上角的x、y后两个点是右下角x、y
# person_boxes = [
# [100, 100, 150, 200], # 人1
# [110, 220, 190, 420], # 人2与人1聚集
# #
# # [150, 220, 210, 420], # 人2与人1聚集
# # [190, 220, 230, 420], # 人2与人1聚集
# # [230, 220, 250, 420], # 人2与人1聚集
# [400, 300, 350, 400], # 人3孤立
# ]
# has_crowd, groups = detect_crowd(person_boxes, N=3)
# 通用方法,发现即记录事件
def func_100000(results, cls_id_list, type_name_list, func_id_10001, list_track_id,func_id=-1):
box_count = []
draw_detail = []
cls_count = 0
result_boxes = results.boxes
if result_boxes is not None:
# result_boxes= results.boxes
# yolo11 的bug检测到结果就是results.boxes 是 torch.Tensor包含边界框坐标当没有检测到目标时results.boxes 可能被设置为空列表 [],导致类型变为 list。
# yolo11 使用二次修改后的值本身就是list
if isinstance(result_boxes, list) and len(result_boxes) == 0:
return None
if isinstance(result_boxes, list) and len(result_boxes) >0:
boxes = result_boxes
else:
boxes = result_boxes.tolist()
for i, box in enumerate(boxes):
# print(boxes[i])
# print(results.confs[i])
# print(results.clss[i])
if results.clss[i] in cls_id_list:
cls_count = cls_count + 1
ind = int(results.clss[i])
trickier_detail = {
# "track_id": results.track_ids[i],
"confidence": results.confs[i],
"cls_id": i,
"type_name": type_name_list[ind],
"box": boxes[i]
}
draw_detail.append(trickier_detail)
if len(draw_detail) > 0:
box_count.append(draw_detail)
if func_id>0:
func_id_10001=func_id
if len(box_count) > 0:
cal_result = {
"model_id": func_id_10001,
"type_name": type_name_list,
"cls_count": cls_count,
"box_count": box_count
}
# message_json = json.dumps(cal_result, indent=4)
return cal_result
else:
return None
# func_10004 、 func_100005,人员、车辆、视频、图片 使用同一套逻辑,方法可以复用
# 逻辑为 中心点互相间的距离小于对角线2倍即判断为聚集
# local_cache 为一个包含track_id的list有变化就更新
def func_100004(results, cls_id_list, type_name_list, func_id_10004, N, local_cache):
# try:
box_count = []
draw_detail = []
cls_count = 0
coordinate_boxes = [] # 所有的 box的坐标集合
coordinate_track_id = [] # 所有的track_id
# crowd_coordinate_list=[] # 识别后的聚集的坐标的集合
# crowd_track_id_list=[] #识别后的track_id的集合
l_cache = [] # track_id的集合
if results.boxes is not None:
result_boxes = results.boxes
# yolo11 的bug检测到结果就是results.boxes 是 torch.Tensor包含边界框坐标当没有检测到目标时results.boxes 可能被设置为空列表 [],导致类型变为 list。
if isinstance(result_boxes, list) or len(result_boxes) == 0:
return None,None
boxes = result_boxes.tolist()
# if boxes is None:
# print("boxes is None")
for i, box in enumerate(boxes):
ind = int(results.clss[i])
if ind in cls_id_list:
cls_count = cls_count + 1
# x1, y1, x2, y2 = map(int, box.xyxy[0].tolist())
x1 = box[0]
y1 = box[1]
x2 = box[2]
y2 = box[3]
track_id = results.track_ids[i]
l_cache.append(track_id)
trickier_detail = {
"track_id": track_id,
"confidence": results.confs[i],
"cls_id": ind,
"type_name": type_name_list[ind], # 伪代码,后续需要修改
"box": boxes[i]
}
coordinate_boxes.append([x1, y1, x2, y2])
coordinate_track_id.append(track_id)
draw_detail.append(trickier_detail)
if len(draw_detail) > 0:
box_count.append(draw_detail)
if l_cache is not None and local_cache is not None and set(l_cache) == set(local_cache):
# if set(l_cache) == set(local_cache): # 判断元素是否相等,如果相等,就表示人员、车辆没变化
return None, None
if len(box_count) > 0:
cal_result = {
"model_id": func_id_10004,
"type_name": type_name_list,
"cls_count": cls_count,
"box_count": box_count
}
return cal_result, local_cache
else:
return None, local_cache
# except Exception as infer_err:
# print(f"推理错误1111: {infer_err}")
# func_10004 、 func_100005,人员、车辆、视频、图片 使用同一套逻辑,方法可以复用
# 逻辑为 中心点互相间的距离小于对角线2倍即判断为聚集
# local_cache 为一个包含track_id的list有变化就更新
def func_100021(results, cls_id_list, type_name_list, func_id_10004, N):
box_count = []
draw_detail = []
cls_count = 0
coordinate_boxes = [] # 所有的 box的坐标集合
coordinate_track_id = [] # 所有的track_id
crowd_coordinate_list = [] # 识别后的聚集的坐标的集合
crowd_track_id_list = [] # 识别后的track_id的集合
if results.boxes is not None:
result_boxes = results.boxes
# yolo11 的bug检测到结果就是results.boxes 是 torch.Tensor包含边界框坐标当没有检测到目标时results.boxes 可能被设置为空列表 [],导致类型变为 list。
if isinstance(result_boxes, list) or len(result_boxes) == 0:
return None
boxes = result_boxes.tolist()
for i, box in enumerate(boxes):
ind = int(results.clss[i])
if ind in cls_id_list:
cls_count = cls_count + 1
# x1, y1, x2, y2 = map(int, box.xyxy[0].tolist())
x1 = box[0]
y1 = box[1]
x2 = box[2]
y2 = box[3]
track_id = results.track_ids[i]
trickier_detail = {
"track_id": track_id,
"confidence": results.confs[i],
"cls_id": ind,
"type_name": type_name_list[ind], # 伪代码,后续需要修改
"box": boxes[i]
}
coordinate_boxes.append([x1, y1, x2, y2])
coordinate_track_id.append(track_id)
draw_detail.append(trickier_detail)
if len(draw_detail) > 0:
box_count.append(draw_detail)
if len(coordinate_boxes) > 0:
detect_result, detect_list = detect_crowd(coordinate_boxes, N)
if detect_result:
if detect_list is not None:
for i, value in enumerate(detect_list):
crowd_coordinate_list.append(coordinate_boxes[i])
crowd_track_id_list.append(coordinate_track_id[i])
if len(box_count) > 0:
cal_result = {
"model_id": func_id_10004,
"type_name": type_name_list,
"cls_count": cls_count,
"box_count": box_count
}
if len(crowd_coordinate_list) > 0:
cal_result["crowd_coordinate_list"] = crowd_coordinate_list
cal_result["crowd_track_id_list"] = crowd_track_id_list
# message_json = json.dumps(cal_result, indent=4)
return cal_result
else:
return None