@@ -77,13 +77,73 @@ def serialize(self):
77
77
if serializer .is_valid (raise_exception = True ):
78
78
return serializer .data
79
79
80
+ @staticmethod
81
+ def _is_shape_inside (shape , start , stop ):
82
+ return start <= int (shape ['frame' ]) <= stop
83
+
84
+ @staticmethod
85
+ def _is_track_inside (track , start , stop ):
86
+ # a <= b
87
+ def has_overlap (a , b ):
88
+ return 0 <= min (b , stop ) - max (a , start )
89
+
90
+ prev_shape = None
91
+ for shape in track ['shapes' ]:
92
+ if prev_shape and not prev_shape ['outside' ] and \
93
+ has_overlap (prev_shape ['frame' ], shape ['frame' ]):
94
+ return True
95
+ prev_shape = shape
96
+
97
+ if not prev_shape ['outside' ] and prev_shape ['frame' ] <= stop :
98
+ return True
99
+
100
+ return False
101
+
102
+ @staticmethod
103
+ def _slice_track (track_ , start , stop ):
104
+ def filter_track_shapes (shapes ):
105
+ shapes = [s for s in shapes if AnnotationIR ._is_shape_inside (s , start , stop )]
106
+ drop_count = 0
107
+ for s in shapes :
108
+ if s ['outside' ]:
109
+ drop_count += 1
110
+ else :
111
+ break
112
+ # Need to leave the last shape if all shapes are outside
113
+ if drop_count == len (shapes ):
114
+ drop_count -= 1
115
+
116
+ return shapes [drop_count :]
117
+
118
+ track = copy .deepcopy (track_ )
119
+ segment_shapes = filter_track_shapes (track ['shapes' ])
120
+
121
+ if len (segment_shapes ) < len (track ['shapes' ]):
122
+ interpolated_shapes = TrackManager .get_interpolated_shapes (track , start , stop )
123
+ scoped_shapes = filter_track_shapes (interpolated_shapes )
124
+
125
+ if scoped_shapes :
126
+ if not scoped_shapes [0 ]['keyframe' ]:
127
+ segment_shapes .insert (0 , scoped_shapes [0 ])
128
+ if not scoped_shapes [- 1 ]['keyframe' ]:
129
+ segment_shapes .append (scoped_shapes [- 1 ])
130
+
131
+ # Should delete 'interpolation_shapes' and 'keyframe' keys because
132
+ # Track and TrackedShape models don't expect these fields
133
+ del track ['interpolated_shapes' ]
134
+ for shape in segment_shapes :
135
+ del shape ['keyframe' ]
136
+
137
+ track ['shapes' ] = segment_shapes
138
+ track ['frame' ] = track ['shapes' ][0 ]['frame' ]
139
+ return track
140
+
80
141
#makes a data copy from specified frame interval
81
142
def slice (self , start , stop ):
82
- is_frame_inside = lambda x : (start <= int (x ['frame' ]) <= stop )
83
143
splitted_data = AnnotationIR ()
84
- splitted_data .tags = copy .deepcopy (list ( filter ( is_frame_inside , self .tags )))
85
- splitted_data .shapes = copy .deepcopy (list ( filter ( is_frame_inside , self .shapes )))
86
- splitted_data .tracks = copy . deepcopy ( list ( filter ( lambda y : len ( list ( filter ( is_frame_inside , y [ 'shapes' ]))), self .tracks )))
144
+ splitted_data .tags = [ copy .deepcopy (t ) for t in self .tags if self . _is_shape_inside ( t , start , stop )]
145
+ splitted_data .shapes = [ copy .deepcopy (s ) for s in self .shapes if self . _is_shape_inside ( s , start , stop )]
146
+ splitted_data .tracks = [ self . _slice_track ( t , start , stop ) for t in self .tracks if self . _is_track_inside ( t , start , stop )]
87
147
88
148
return splitted_data
89
149
0 commit comments