Data validation on client and server (#51)

* Data validation on client and server
* Consistent uploading methods for task and for job
main
Boris Sekachev 8 years ago committed by GitHub
parent 72e5bf6661
commit 6e64bb31f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -761,14 +761,29 @@ class _AnnotationForJob(_Annotation):
label = _Label(self.db_labels[int(path['label_id'])])
boxes = []
frame = -1
has_boxes_on_prev_segm = False
last_box_on_prev_segm = None
has_box_on_start_frame = False
for box in path['shapes']:
if int(box['frame']) < self.start_frame:
has_boxes_on_prev_segm = True
if last_box_on_prev_segm is None or int(last_box_on_prev_segm["frame"]) < int(box["frame"]):
last_box_on_prev_segm = box
elif int(box['frame']) == self.start_frame:
has_box_on_start_frame = True
break
if has_boxes_on_prev_segm and not has_box_on_start_frame:
last_box_on_prev_segm["frame"] = self.start_frame
for box in path['shapes']:
if int(box['frame']) <= self.stop_frame:
if int(box['frame']) <= self.stop_frame and int(box['frame']) >= self.start_frame:
frame_idx = int(box['frame']) if db_task.mode == 'annotation' else 0
xtl, ytl, xbr, ybr = self._clamp_box(float(box['xtl']), float(box['ytl']),
float(box['xbr']), float(box['ybr']), image_meta['original_size'][frame_idx])
tracked_box = _TrackedBox(xtl, ytl, xbr, ybr, int(box['frame']), strtobool(str(box['occluded'])),
int(box['z_order']), strtobool(str(box['outside'])))
assert tracked_box.frame > frame
assert tracked_box.frame > frame
frame = tracked_box.frame
for attr in box['attributes']:
@ -780,7 +795,7 @@ class _AnnotationForJob(_Annotation):
boxes.append(tracked_box)
else:
self.logger.error("init_from_client: ignore frame #%d " +
"because stop_frame is %d", int(box['frame']), self.stop_frame)
"because it out of segment range [%d-%d]", int(box['frame']), self.start_frame, self.stop_frame)
attributes = []
for attr in path['attributes']:
@ -790,7 +805,7 @@ class _AnnotationForJob(_Annotation):
attributes.append(attr)
assert frame <= self.stop_frame
box_path = _BoxPath(label, int(path['frame']), self.stop_frame,
box_path = _BoxPath(label, min(list(map(lambda box: box.frame, boxes))), self.stop_frame,
int(path['group_id']), boxes, attributes)
self.box_paths.append(box_path)
@ -799,8 +814,23 @@ class _AnnotationForJob(_Annotation):
label = _Label(self.db_labels[int(path['label_id'])])
poly_shapes = []
frame = -1
has_shapes_on_prev_segm = False
last_shape_on_prev_segm = None
has_shape_on_start_frame = False
for poly_shape in path['shapes']:
if int(poly_shape['frame']) < self.start_frame:
has_shapes_on_prev_segm = True
if last_shape_on_prev_segm is None or int(last_shape_on_prev_segm["frame"]) < (poly_shape["frame"]):
last_shape_on_prev_segm = box
elif int(poly_shape['frame']) == self.start_frame:
has_shape_on_start_frame = True
break
if has_shapes_on_prev_segm and not has_shape_on_start_frame:
last_shape_on_prev_segm["frame"] = self.start_frame
for poly_shape in path['shapes']:
if int(poly_shape['frame']) <= self.stop_frame:
if int(poly_shape['frame']) <= self.stop_frame and int(poly_shape['frame']) >= self.start_frame:
frame_idx = int(poly_shape['frame']) if db_task.mode == 'annotation' else 0
points = self._clamp_poly(poly_shape['points'], image_meta['original_size'][frame_idx])
tracked_poly_shape = _TrackedPolyShape(points, int(poly_shape['frame']), strtobool(str(poly_shape['occluded'])),
@ -817,7 +847,7 @@ class _AnnotationForJob(_Annotation):
poly_shapes.append(tracked_poly_shape)
else:
self.logger.error("init_from_client: ignore frame #%d " +
"because stop_frame is %d", int(poly_shape['frame']), self.stop_frame)
"because it out of segment range [%d-%d]", int(poly_shape['frame']), self.start_frame, self.stop_frame)
attributes = []
for attr in path['attributes']:
@ -826,7 +856,7 @@ class _AnnotationForJob(_Annotation):
attr = _Attribute(spec, str(attr['value']))
attributes.append(attr)
poly_path = _PolyPath(label, int(path['frame']), self.stop_frame + 1,
poly_path = _PolyPath(label, min(list(map(lambda shape: shape.frame, poly_shapes))), self.stop_frame + 1,
int(path['group_id']), poly_shapes, attributes)
getattr(self, poly_path_type).append(poly_path)

@ -322,8 +322,6 @@ class AnnotationParser {
Ignore all frames more then stop.
*/
let significant = keyFrame || frame === this._startFrame;
significant = significant && frame >= this._startFrame;
significant = significant && frame <= this._stopFrame;
if (significant) {
let attributeList = this._getAttributeList(shape, labelId);
@ -348,7 +346,7 @@ class AnnotationParser {
path.attributes = pathAttributes;
if (type === 'boxes') {
let [xtl, ytl, xbr, ybr, occluded, z_order] = this._getBoxPosition(shape, frame);
let [xtl, ytl, xbr, ybr, occluded, z_order] = this._getBoxPosition(shape, Math.clamp(frame, this._startFrame, this._stopFrame));
path.shapes.push({
frame: frame,
occluded: occluded,
@ -362,7 +360,7 @@ class AnnotationParser {
});
}
else {
let [points, occluded, z_order] = this._getPolyPosition(shape, frame);
let [points, occluded, z_order] = this._getPolyPosition(shape, Math.clamp(frame, this._startFrame, this._stopFrame));
path.shapes.push({
frame: frame,
occluded: occluded,

@ -149,7 +149,7 @@ class ShapeBufferModel extends Listener {
this._collection.add(object, `annotation_${this._shape.type}`);
}
// Undo/redo code
// Undo/redo code
let model = this._collection.shapes.slice(-1)[0];
window.cvat.addAction('Paste Object', () => {
model.removed = true;

@ -1252,7 +1252,7 @@ class ShapeCollectionView {
let parents = {
uis: this._UIContent.parent(),
shapes: this._frameContent.node.parentNode
}
};
this._frameContent.node.parent = null;
this._UIContent.detach();

@ -22,7 +22,9 @@ class ShapeModel extends Listener {
this._type = type;
this._color = color;
this._label = data.label_id;
this._frame = data.frame;
this._frame = type.split('_')[0] === 'annotation' ? data.frame :
positions.filter((pos) => pos.frame < window.cvat.player.frames.start).length ?
window.cvat.player.frames.start : Math.min(...positions.map((pos) => pos.frame));
this._removed = false;
this._locked = false;
this._merging = false;
@ -333,7 +335,17 @@ class ShapeModel extends Listener {
let oldPos = Object.assign({}, this._positions[frame]);
window.cvat.addAction('Change Outside', () => {
if (!Object.keys(oldPos).length) {
// Frame hasn't been a keyframe, remove it from position and redestribute attributes
delete this._positions[frame];
this._frame = Math.min(...Object.keys(this._positions).map((el) => +el));
if (frame < this._frame && frame in this._attributes.mutable) {
this._attributes.mutable[this._frame] = this._attributes.mutable[frame];
}
if (frame in this._attributes.mutable) {
delete this._attributes.mutable[frame];
}
this._updateReason = 'outside';
this.notify();
}
@ -349,6 +361,15 @@ class ShapeModel extends Listener {
position.outside = !position.outside;
this.updatePosition(frame, position, true);
// Update the start frame if need and redestribute attributes
if (frame < this._frame) {
if (this._frame in this._attributes.mutable) {
this._attributes.mutable[frame] = this._attributes.mutable[this._frame];
delete(this._attributes.mutable[this._frame]);
}
this._frame = frame;
}
this._updateReason = 'outside';
this.notify();
}
@ -360,38 +381,28 @@ class ShapeModel extends Listener {
}
// Undo/redo code
let oldPos = Object.assign({}, this._positions[frame]);
window.cvat.addAction('Change Keyframe', () => {
if (!Object.keys(oldPos).length) {
delete this._positions[frame];
this._updateReason = 'outside';
this.notify();
}
else {
this.updatePosition(frame, oldPos, true);
this._updateReason = 'keyframe';
this.notify();
}
this.switchKeyFrame(frame);
}, () => {
this.switchKeyFrame(frame);
}, frame);
// End of undo/redo code
if (frame in this._positions && Object.keys(this._positions).length > 1) {
// If frame is first frame, need to redestribute attributes to new first frame
// If frame is first object frame, need redestribute attributes
if (frame === this._frame) {
this._frame = +Object.keys(this._positions).sort((a,b) => +a - +b)[1];
this._frame = Object.keys(this._positions).map((el) => +el).sort((a,b) => a - b)[1];
if (frame in this._attributes.mutable) {
this._attributes.mutable[this._frame] = this._attributes.mutable[frame];
delete(this._attributes.mutable[frame]);
}
}
delete(this._positions[frame]);
if (frame in this._attributes.mutable) {
delete(this._attributes.mutable[frame]);
}
}
else {
let position = this._interpolatePosition(frame);
this.updatePosition(frame, position, true);
if (frame < this._frame) {
if (this._frame in this._attributes.mutable) {
this._attributes.mutable[frame] = this._attributes.mutable[this._frame];
@ -399,9 +410,6 @@ class ShapeModel extends Listener {
}
this._frame = frame;
}
let position = this._interpolatePosition(frame);
this.updatePosition(frame, position, true);
}
this._updateReason = 'keyframe';
this.notify();
@ -803,17 +811,44 @@ class BoxModel extends ShapeModel {
static importPositions(positions) {
let imported = {};
if (this._type === 'interpolation_box') {
let last_key_in_prev_segm = null;
let segm_start = window.cvat.player.frames.start;
let segm_stop = window.cvat.player.frames.stop;
for (let pos of positions) {
imported[pos.frame] = {
xtl: pos.xtl,
ytl: pos.ytl,
xbr: pos.xbr,
ybr: pos.ybr,
occluded: pos.occluded,
outside: pos.outside,
z_order: pos.z_order,
let frame = pos.frame;
if (frame >= segm_start && frame <= segm_stop) {
imported[frame] = {
xtl: pos.xtl,
ytl: pos.ytl,
xbr: pos.xbr,
ybr: pos.ybr,
occluded: pos.occluded,
outside: pos.outside,
z_order: pos.z_order,
};
}
else {
console.log(`Frame ${frame} has been found in segment [${segm_start}-${segm_stop}]. It have been ignored.`);
if (!last_key_in_prev_segm || frame > last_key_in_prev_segm.frame) {
last_key_in_prev_segm = pos;
}
}
}
if (last_key_in_prev_segm && !(segm_start in imported)) {
imported[segm_start] = {
xtl: last_key_in_prev_segm.xtl,
ytl: last_key_in_prev_segm.ytl,
xbr: last_key_in_prev_segm.xbr,
ybr: last_key_in_prev_segm.ybr,
occluded: last_key_in_prev_segm.occluded,
outside: last_key_in_prev_segm.outside,
z_order: last_key_in_prev_segm.z_order,
};
}
return imported;
}
@ -837,6 +872,7 @@ class PolyShapeModel extends ShapeModel {
this._setupKeyFrames();
}
_interpolatePosition(frame) {
if (frame in this._positions) {
return Object.assign({}, this._positions[frame], {
@ -1036,14 +1072,37 @@ class PolyShapeModel extends ShapeModel {
static importPositions(positions) {
let imported = {};
if (this._type.startsWith('interpolation')) {
let last_key_in_prev_segm = null;
let segm_start = window.cvat.player.frames.start;
let segm_stop = window.cvat.player.frames.stop;
for (let pos of positions) {
imported[pos.frame] = {
points: pos.points,
occluded: pos.occluded,
outside: pos.outside,
z_order: pos.z_order,
let frame = pos.frame;
if (frame >= segm_start && frame <= segm_stop) {
imported[pos.frame] = {
points: pos.points,
occluded: pos.occluded,
outside: pos.outside,
z_order: pos.z_order,
};
}
else {
console.log(`Frame ${frame} has been found in segment [${segm_start}-${segm_stop}]. It have been ignored.`);
if (!last_key_in_prev_segm || frame > last_key_in_prev_segm.frame) {
last_key_in_prev_segm = pos;
}
}
}
if (last_key_in_prev_segm && !(segm_start in imported)) {
imported[segm_start] = {
points: last_key_in_prev_segm.points,
occluded: last_key_in_prev_segm.occluded,
outside: last_key_in_prev_segm.outside,
z_order: last_key_in_prev_segm.z_order,
};
}
return imported;
}

Loading…
Cancel
Save