-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed uploading track annotations for multi-segment tasks #1396
Changes from 7 commits
c39e38f
d4820d4
d9d0699
4f4f3ca
705bd7d
3eec428
bd228e1
976a820
bf1e0a3
f4ed055
bae93c0
ae65237
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,13 +77,57 @@ def serialize(self): | |
if serializer.is_valid(raise_exception=True): | ||
return serializer.data | ||
|
||
@staticmethod | ||
def _is_shape_inside(shape, start, stop): | ||
return start <= int(shape['frame']) <= stop | ||
|
||
@staticmethod | ||
def _is_track_inside(track, start, stop): | ||
# a <= b | ||
def has_overlap(a, b): | ||
return 0 <= min(b, stop) - max(a, start) | ||
|
||
prev_shape = None | ||
for shape in track['shapes']: | ||
if prev_shape and not prev_shape['outside'] and \ | ||
has_overlap(prev_shape['frame'], shape['frame']): | ||
return True | ||
prev_shape = shape | ||
|
||
if not prev_shape["outside"] and prev_shape['frame'] <= stop: | ||
return True | ||
|
||
return False | ||
|
||
@staticmethod | ||
def _slice_track(track_, start, stop): | ||
track = copy.deepcopy(track_) | ||
segment_shapes = [s for s in track['shapes'] if AnnotationIR._is_shape_inside(s, start, stop)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @azhavoro , if we have a track with only one shape with the frame less than start, segment_shapes will be empty. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this case will be handled later in 113 line There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potentially in the line we can get first shape with outside == True. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added filter to remove starting shapes with outside==True after processing |
||
|
||
if len(segment_shapes) < len(track['shapes']): | ||
interpolated_shapes = TrackManager.get_interpolated_shapes(track, start, stop) | ||
|
||
for shape in interpolated_shapes: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @azhavoro , could you please think how to reorganize the code below? It looks messy. It seems that get_interpolated_shapes doesn't respect start and stop by a reason. Thus let's filter them:
If scoped_shapes empty then nothing to do. Otherwise if Let's assign Of course I didn't check the logic. You need just improve your code and I hope the code above will give you some ideas how to do that. |
||
if shape['frame'] == start and \ | ||
(not segment_shapes or segment_shapes[0]['frame'] > start): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible that here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added filter to remove starting shapes with outside==True after processing |
||
segment_shapes.insert(0, shape) | ||
elif shape['frame'] == stop and \ | ||
(not segment_shapes or segment_shapes[-1]['frame'] < stop): | ||
segment_shapes.append(shape) | ||
del track['interpolated_shapes'] | ||
for shape in segment_shapes: | ||
del shape['keyframe'] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why should we delete the property for all segment_shapes? Could you please add a comment? |
||
|
||
track['shapes'] = segment_shapes | ||
track['frame'] = track['shapes'][0]['frame'] | ||
return track | ||
|
||
#makes a data copy from specified frame interval | ||
def slice(self, start, stop): | ||
is_frame_inside = lambda x: (start <= int(x['frame']) <= stop) | ||
splitted_data = AnnotationIR() | ||
splitted_data.tags = copy.deepcopy(list(filter(is_frame_inside, self.tags))) | ||
splitted_data.shapes = copy.deepcopy(list(filter(is_frame_inside, self.shapes))) | ||
splitted_data.tracks = copy.deepcopy(list(filter(lambda y: len(list(filter(is_frame_inside, y['shapes']))), self.tracks))) | ||
splitted_data.tags = [copy.deepcopy(t) for t in self.tags if self._is_shape_inside(t, start, stop)] | ||
splitted_data.shapes = [copy.deepcopy(s) for s in self.shapes if self._is_shape_inside(s, start, stop)] | ||
splitted_data.tracks = [self._slice_track(t, start, stop) for t in self.tracks if self._is_track_inside(t, start, stop)] | ||
|
||
return splitted_data | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One tricky case here. Should we return True here for shapes with outside == True?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added filter to remove starting shapes with outside==True after processing