AIlib2/utilsK/crowdGather.py

166 lines
6.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import sys
from pathlib import Path
import math
import cv2
import numpy as np
import torch
import math
import time
FILE = Path(__file__).absolute()
#sys.path.append(FILE.parents[0].as_posix()) # add yolov5/ to path
def calculate_distance(point1, point2):
"""计算两个点之间的欧氏距离"""
point= center_coordinate(point1)
point=np.array(point)
other_point = center_coordinate(point2)
other_point = np.array(other_point)
return np.linalg.norm(point - other_point)
def find_clusters(preds, min_distance):
"""按照最小距离将点分成簇"""
points=preds
points=np.array(points)
clusters = []
used_points = set()
for i, point in enumerate(points):
if i not in used_points: # 如果该点未被使用过
cluster = [point]
used_points.add(i)
# 寻找与该点距离小于等于min_distance的其他点
for j, other_point in enumerate(points):
if j not in used_points:
if all(calculate_distance(point, other_point) <= min_distance
for point in cluster):
cluster.append(other_point)
used_points.add(j)
clusters.append(cluster)
return clusters
def center_coordinate(boundbxs):
'''
根据检测矩形框,得到其矩形长度和宽度
输入两个对角坐标xyxy
输出矩形框重点坐标xy
'''
boundbxs_x1 = boundbxs[0]
boundbxs_y1 = boundbxs[1]
boundbxs_x2 = boundbxs[2]
boundbxs_y2 = boundbxs[3]
center_x = 0.5 * (boundbxs_x1 + boundbxs_x2)
center_y = 0.5 * (boundbxs_y1 + boundbxs_y2)
return [center_x, center_y]
def get_bounding_rectangle(rectangles):
'''
通过输入多个矩形的对角坐标,得到这几个矩形的外包矩形对角坐标
输入:点簇列表 (嵌套列表)
输出:多个矩形的外包矩形对角坐标 (列表)
'''
min_x, max_x, min_y, max_y = float('inf'), float('-inf'), float('inf'), float('-inf')
for rect in rectangles:
x1, y1, x2, y2,c1,t1 = rect
min_x = min(min_x, min(x1, x2))
max_x = max(max_x, max(x1, x2))
min_y = min(min_y, min(y1, y2))
max_y = max(max_y, max(y1, y2))
return [min_x, min_y, max_x, max_y]
def calculate_score(input_value):
'''
计算人群聚集置信度检测出3-10人内按照0.85-1的上升趋势取值
当检测超过10人直接判断分数为1.
'''
if input_value == 3:
output_value=0.85
elif input_value == 4:
output_value=0.9
elif 5<= input_value <=10:
output_value = 0.9+(input_value-4)*0.015
else:
output_value=1
return output_value
def gather_post_process(predsList, pars):
'''
后处理程序针对检测出的pedestrian进行人员聚集的算法检测按照类别'crowd_people'增加predsList
①原类别:
['ForestSpot', 'PestTree', 'pedestrian', 'fire', 'smog','cloud']=[0,1,2,3,4,5]
②处理后的类别汇总:
['ForestSpot', 'PestTree', 'pedestrian', 'fire', 'smog','cloud','crowd_people']=[0,1,2,3,4,5,6]
输入:
preds 一张图像的检测结果为嵌套列表tensor包括x_y_x_y_conf_class
imgwidth,imgheight 图像的原始宽度及长度
输出:检测结果(将其中未悬挂国旗的显示)
'''
t0=time.time()
predsList = predsList[0]
predsList = [x for x in predsList if int(x[5]) !=5 ]##把类别“云朵”去除
# 1、过滤掉类别2以外的目标只保留行人
preds = [ x for x in predsList if int(x[5]) ==pars['pedestrianId'] ]
if len(preds)< pars['crowdThreshold']:
return predsList,'gaher postTime:No gathering'
preds = np.array(preds)
longs = np.mean(np.max(preds[:,2:4]-preds[:,0:2]))
distanceThreshold = pars['distancePersonScale']*longs
# 2、查找点簇
clusters = find_clusters(preds, distanceThreshold)
clusters_crowd = []
# 3、输出点簇信息点簇中数量超过阈值判断人员聚集
for i, cluster in enumerate(clusters):
if len(cluster) >= pars['crowdThreshold']: # 超过一定人数,即为人员聚集
#print(f"Cluster {i + 1}: {len(cluster)} points")
clusters_crowd.append(cluster)
#print(clusters_crowd)
# 4、根据得到的人员聚集点簇合并其他类别检测结果
for i in range(len(clusters_crowd)):
xyxy = get_bounding_rectangle(clusters_crowd[i]) # 人群聚集包围框
#score = calculate_score(len(clusters_crowd[i])) # 人群聚集置信度
score = len(clusters_crowd[i])
xyxy.append(score) # 人群聚集置信度
xyxy.append(pars['gatherId']) # 人群聚集类别
predsList.append(xyxy)
# 5、输出最终类别共7类用于绘图显示
output_predslist = predsList
#print('craoGaher line131:',output_predslist)
t1=time.time()
return output_predslist,'gaher postTime:%.1f ms'%( (t1-t0)*1000 )
if __name__ == "__main__":
t1 = time.time()
# 对应vendor1_20240529_99.jpg检测结果
preds=[[224.19933, 148.30751, 278.19156, 199.87828, 0.87625, 2.00000],
[362.67139, 161.25760, 417.72357, 211.51706, 0.86919, 2.00000],
[437.00131, 256.19083, 487.88870, 307.72897, 0.85786, 2.00000],
[442.64606, 335.78168, 493.75720, 371.41418, 0.85245, 2.00000],
[324.58362, 256.18488, 357.72626, 294.08929, 0.84512, 2.00000],
[343.59781, 301.06506, 371.04105, 350.01086, 0.84207, 2.00000],
[301.35858, 210.64088, 332.64862, 250.78883, 0.84063, 2.00000],
[406.02994, 216.91214, 439.44455, 249.26077, 0.83698, 2.00000],
[321.53494, 99.68467, 354.67477, 135.53226, 0.82515, 2.00000],
[253.97131, 202.65234, 302.06055, 233.30634, 0.81498, 2.00000],
[365.62521, 66.42108, 442.02292, 127.37558, 0.79556, 1.00000]]
#preds=torch.tensor(preds) #返回的预测结果
imgwidth=1920
imgheight=1680
pars={'imgSize':(imgwidth,imgheight),'pedestrianId':2,'crowdThreshold':4,'gatherId':6,'distancePersonScale':2.0}
'''
pedestrianId 为行人识别的类别;
crowdThreshold为设置的判断人员聚集的人数阈值默认4人为聚集
distanceThreshold为设置的判断人员聚集的距离阈值为了测试默认300像素内为聚集(可自行设置)
'''
yyy=gather_post_process(preds,pars) #送入后处理函数
t2 = time.time()
ttt = t2 - t1
print('时间', ttt * 1000)