-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdata_site.py.save
184 lines (156 loc) · 7.31 KB
/
data_site.py.save
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
from ast import Lambda
from faulthandler import disable
from crowd import Crowd
from pptracking_util import dist, ThinknessSigmoid, color_palette, DrawerManager
from scipy.spatial.distance import cdist
from collections import deque
from functools import cmp_to_key
import copy
from yolov5.utils.general import (cv2)
import numpy as np
import time
class Data:
def __init__(self, id, xy, vector, nearby):
self.id = id
self.xy = xy
self.vector = vector
self.nearby = nearby
# to check if two objects are same
def __eq__(self, other):
if self.id == other.id:
return True
return False
def __repr__(self):
return 'id:{}, nearby:{}\n'.format(self.id, [n.id for n in self.nearby])
class DataSites: #Data_position
def __init__(self, max):
self.curve_img = []
self.pdata_per_frame = []
self.records = deque()
self.frame_max = max
self.count_frame = 1
def draw_trace(self, curve_frame, im):
for frame in curve_frame:
for pp_data in frame:
id = pp_data.id
vector = pp_data.vector
start_xy = pp_data.xy
color = color_palette(id)
im = cv2.line(im , np.array(start_xy, dtype = int), np.array(start_xy + vector, dtype = int), color, 2)
return im
"""def draw_trace(self):
background = copy.deepcopy(self.background)
records = self.records
for rec in records:
for person in rec:
cv2.circle(background, ( rec[person][0],rec[person][1]), 10, color_palette(person), 15) #class
#person[0] -> x person[1] -> y person[2] -> pp_id
return background """
def add_record(self, record):
records = self.records
if len(records) > self.frame_max:
records.popleft()
records.append(record)
self.count_frame += 1
def trans_data2ppdata(self, dis_edge = 200, type = 0):
arrow_record = copy.deepcopy(self.records)
pdata_per_frame = []
count = 0
for fid in range(len(arrow_record)-1):
frame1 = arrow_record[fid]
frame2 = arrow_record[fid+1]
person_data = []
#找出每個pid的start位置以及位移量
for pid in frame1:
if pid in frame2:
count += 1
start_xy = np.array(frame1[pid])
dx = frame2[pid][0] - frame1[pid][0]
dy = frame2[pid][1] - frame1[pid][1]
vector = np.array([dx, dy])
nearby = []
data = Data(pid, start_xy, vector, nearby)
person_data.append(data)
"""
person_data = [data, data, data ,......]
data = {
"id": 1,
"start_xy": [100, 200],
"vertor" : [20, 50] ,
"nearby":[ data, data, ...]
}
"""
# find how many people surround each person
if type == 0 and len(person_data) > 0:
person_data = self.compute_nearby(person_data, dis_edge)
pdata_per_frame.append(person_data)
return pdata_per_frame
def compute_nearby(self, person_data, edge: int):
dis_array = [x.xy for x in person_data]
dis_array = cdist(dis_array, dis_array)
length = len(dis_array)
limit = length // 2 if length % 2 == 0 else length // 2 + 1
for row in range(limit):
for col in range(row + 1, length):
if dis_array[row][col] <= edge and person_data[row].id != person_data[col].id:
person_data[row].nearby.append(person_data[col])
person_data[col].nearby.append(person_data[row])
return person_data
def draw_crowd_arrow(self,background, color, distance_edge = 800):
background = np.array(background, dtype = np.uint8)
res_crowd_list = []
print("classify nearby distance: ", distance_edge)
# 取得每個frame中每個人的data
pdata_per_frame = self.trans_data2ppdata(distance_edge)
for pdatas in pdata_per_frame:
# TODO remove the people that don't move
# 這段用來找出 附近且走差不多方向 的人
for pp1 in pdatas:
# 周圍超過2人
if len(pp1.nearby) >= 2:
new_nearby = [pp1]
for near_pp in pp1.nearby:
# 找對應的pid,然後跟據條件合並向量
for pp2 in pdatas:
if pp2.id == near_pp.id:
vector2 = pp2.vector
vector = pp1.vector
if vector[0] == 0 and vector[1] == 0:
unit_vec1 = np.array([0, 0])
else:
unit_vec1 = vector / dist(vector)
if vector2[0] == 0 and vector2[1] == 0:
unit_vec2 = np.array([0, 0])
else:
unit_vec2 = vector2 / dist(vector2)
if dist(np.zeros(2),unit_vec1+ unit_vec2) >= 2**0.5: #不可超過90度
new_nearby.append(pp2)
break
pp1.nearby = sorted(new_nearby, key = cmp_to_key(lambda a, b: a.id- b.id))
for pp1 in pdatas:
if len(pp1.nearby) >= 2:
crowd = Crowd(pp1.nearby)
res_crowd_list.append(crowd)
if len(res_crowd_list) == 0:
continue
# find the largest crowd to init the arrow thinkness function
# remove duplicated crowd
# 去除重複物件的方法: https://minayu.site/2018/12/技術小筆記-利用eq-hash-解決去除重複物件object
largest_crowd = res_crowd_list[0]
for crowd in set(res_crowd_list):
if largest_crowd.size() < crowd.size():
largest_crowd = crowd
arrow_thinkness_func = ThinknessSigmoid(largest_crowd.size())
alpha, beta, gamma = 1, 0.3, 0
worker_manager = DrawerManager(background)
for crowd in set(res_crowd_list):
# arrow_mask = crowd.get_arrow_mask(background, color, thick_fun = arrow_thinkness_func.execute)
# background = cv2.addWeighted(background, alpha, arrow_mask, beta, gamma)
worker_manager.add_work(crowd, color, arrow_thinkness_func.execute)
time1 = time.time()
worker_manager.work()
time2 = time.time()
print("cost: ", time2 - time1,"second in drawing")
background = worker_manager.img
return background
#cv2.circle(影像, 圓心座標, 半徑, 顏色, 線條寬度)