2
2
import sys
3
3
import os
4
4
import scipy
5
- from scipy .signal import find_peaks , peak_prominences
5
+ from scipy .signal import find_peaks_cwt
6
6
import matplotlib .pyplot as plt
7
- from defaultlist import defaultlist
8
7
from headbang .params import DEFAULTS
9
8
10
9
openpose_install_path = "/home/sevagh/thirdparty-repos/openpose"
17
16
18
17
class OpenposeDetector :
19
18
undef_coord_default = numpy .nan
19
+ object_limit = 3
20
+ min_confidence = 0.5
20
21
21
22
def __init__ (
22
23
self ,
23
24
n_frames ,
24
25
keypoints = DEFAULTS ["pose_keypoints" ],
25
- obj_limit = DEFAULTS ["detected_object_limit" ],
26
- adaptive_prominence_ratio = DEFAULTS ["adaptive_prominence_ratio" ],
27
- openpose_confidence_threshold = DEFAULTS ["openpose_confidence_thresh" ],
28
- peak_width = DEFAULTS ["peak_width" ],
29
26
):
30
27
config = {}
31
- # config["dir"] = openpose_install_path
32
28
config ["logging_level" ] = 3
33
- config ["net_resolution" ] = "320x320" # 320x176
34
- # config["output_resolution"] = "-1x768" # 320x176
29
+ config ["net_resolution" ] = "320x320"
35
30
config ["model_pose" ] = "BODY_25"
36
31
config ["alpha_pose" ] = 0.6
37
32
config ["scale_gap" ] = 0.3
38
33
config ["scale_number" ] = 1
39
- # config["keypoint_scale"] = 4 # scale to -1,1
40
34
config ["render_threshold" ] = 0.05
41
- config [
42
- "num_gpu_start"
43
- ] = 0 # If GPU version is built, and multiple GPUs are available, set the ID here
35
+ config ["num_gpu_start" ] = 0
44
36
config ["disable_blending" ] = False
45
37
46
38
config ["model_folder" ] = openpose_dir + "/models/"
@@ -51,13 +43,8 @@ def __init__(
51
43
self .keypoints = [int (i ) for i in keypoints .split ("," )]
52
44
53
45
self .n_frames = int (n_frames )
54
- self .all_y_coords = [[ OpenposeDetector .undef_coord_default ] * self .n_frames ]
46
+ self .all_y_coords = [OpenposeDetector .undef_coord_default ] * self .n_frames
55
47
self .frame_idx = 0
56
- self .obj_limit = obj_limit
57
-
58
- self .confidence_threshold = openpose_confidence_threshold
59
- self .adaptive_prominence_ratio = adaptive_prominence_ratio
60
- self .peak_width = peak_width
61
48
62
49
def detect_pose (self , image ):
63
50
datum = op .Datum ()
@@ -68,76 +55,40 @@ def detect_pose(self, image):
68
55
return datum .poseKeypoints , datum .cvOutputData
69
56
70
57
def process_frame (self , frame ):
71
- tracked_objects = None
72
58
multiple_detected_poses , outframe = self .detect_pose (frame )
73
59
74
- median_x = None
75
- median_y = None
76
-
77
60
if multiple_detected_poses is not None :
78
- # array of (x, y) coordinates of the head/neck
79
- multiple_poses_of_interest = [
80
- [
81
- (d [0 ], d [1 ])
82
- for i , d in enumerate (single_detected_poses )
83
- if i in self .keypoints and d [2 ] > self .confidence_threshold
84
- ]
85
- for single_detected_poses in multiple_detected_poses
86
- ]
87
-
88
- if multiple_poses_of_interest :
89
- for i , poses_of_interest in enumerate (multiple_poses_of_interest ):
90
- poses_of_interest = numpy .asarray (poses_of_interest )
91
- median_coords = numpy .median (poses_of_interest , axis = 0 )
92
- if not numpy .any (numpy .isnan (median_coords )):
93
- median_y = median_coords [1 ]
94
- y_norm = median_y / frame .shape [0 ]
95
- try :
96
- self .all_y_coords [i ][self .frame_idx ] = y_norm
97
- except IndexError :
98
- self .all_y_coords .append (
99
- [OpenposeDetector .undef_coord_default ] * self .n_frames
100
- )
101
- self .all_y_coords [i ][self .frame_idx ] = y_norm
61
+ poses_of_interest = []
62
+
63
+ # collect (x, y) coordinates of the head, median across the first object_limit objects
64
+ for detected_poses in multiple_detected_poses [
65
+ : OpenposeDetector .object_limit
66
+ ]:
67
+ for keypoint , d in enumerate (detected_poses ):
68
+ if (
69
+ keypoint in self .keypoints
70
+ and d [2 ] > OpenposeDetector .min_confidence
71
+ ):
72
+ poses_of_interest .append ((d [0 ], d [1 ]))
73
+
74
+ poses_of_interest = numpy .asarray (poses_of_interest )
75
+ median_coords = numpy .median (poses_of_interest , axis = 0 )
76
+
77
+ if not numpy .any (numpy .isnan (median_coords )):
78
+ median_y = median_coords [1 ]
79
+ y_norm = median_y / frame .shape [0 ]
80
+ self .all_y_coords [self .frame_idx ] = y_norm
102
81
103
82
self .frame_idx += 1
104
83
return outframe
105
84
106
85
def find_peaks (self ):
107
- peaks = [None ] * len (self .all_y_coords )
108
- prominences = [None ] * len (self .all_y_coords )
109
- adjusted_y_coords = [None ] * len (self .all_y_coords )
110
-
111
- for i , y_coords in enumerate (self .all_y_coords ):
112
- min_coord = numpy .nanmin (y_coords )
113
- max_coord = numpy .nanmax (y_coords )
114
-
115
- # adaptive peak prominence - X% of max displacement
116
- adaptive_prominence = self .adaptive_prominence_ratio * (
117
- max_coord - min_coord
118
- )
119
-
120
- adjusted_y_coords [i ] = numpy .nan_to_num (y_coords , nan = min_coord )
86
+ min_coord = numpy .nanmin (self .all_y_coords )
87
+ adjusted_y_coords = numpy .nan_to_num (self .all_y_coords , nan = min_coord )
121
88
122
- peaks [i ], _ = find_peaks (
123
- adjusted_y_coords [i ],
124
- prominence = adaptive_prominence ,
125
- wlen = self .peak_width ,
126
- )
127
-
128
- prominences [i ], _ , _ = peak_prominences (adjusted_y_coords [i ], peaks [i ])
129
-
130
- top_ycoords_and_peaks = [
131
- (ycrds , pks )
132
- for _ , pks , ycrds in sorted (
133
- zip (prominences , peaks , adjusted_y_coords ),
134
- key = lambda triplet : sum (triplet [0 ]),
135
- reverse = True ,
136
- )
137
- ]
138
-
139
- # only track up to obj_limit objects
140
- return top_ycoords_and_peaks [: self .obj_limit ]
89
+ # wavelets are good for peaks
90
+ # https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2631518/
91
+ return find_peaks_cwt (adjusted_y_coords , numpy .arange (5 , 10 ))
141
92
142
93
def plot_ycoords (self ):
143
94
plt .figure (1 )
@@ -147,20 +98,17 @@ def plot_ycoords(self):
147
98
plt .ylabel ("y coord" )
148
99
149
100
frames = numpy .arange (self .n_frames )
150
- best_coords_and_peaks = self .find_peaks ()
151
-
152
- for i , coordspeaks in enumerate (best_coords_and_peaks ):
153
- y_coords , peaks = coordspeaks
154
- y_coords = numpy .asarray (y_coords )
155
- plt .plot (
156
- frames ,
157
- y_coords ,
158
- "-D" ,
159
- label = "obj {0}" .format (i ),
160
- markevery = peaks ,
161
- mec = "black" ,
162
- mfc = "black" ,
163
- )
101
+ peaks = self .find_peaks ()
102
+
103
+ y_coords = numpy .asarray (self .all_y_coords )
104
+
105
+ plt .plot (
106
+ frames ,
107
+ y_coords ,
108
+ "-D" ,
109
+ markevery = peaks ,
110
+ mec = "black" ,
111
+ )
164
112
165
113
plt .legend ()
166
114
plt .show ()
0 commit comments