Display of Annotation Type (#1192)

main
Priya4607 6 years ago committed by GitHub
parent a3448a20ad
commit 6a1e7af5c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -6,7 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [1.1.0-beta] - Unreleased ## [1.1.0-beta] - Unreleased
### Added ### Added
- - Source type support for tags, shapes and tracks (<https://github.com/opencv/cvat/pull/1192>)
- Source type support for CVAT Dumper/Loader (<https://github.com/opencv/cvat/pull/1192>)
### Changed ### Changed
- Smaller object details (<https://github.com/opencv/cvat/pull/1877>) - Smaller object details (<https://github.com/opencv/cvat/pull/1877>)

@ -189,7 +189,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
} }
private onEditDone(state: any, points: number[]): void { private onEditDone(state: any, points: number[]): void {
if (state && points) { if (state && points) {
const event: CustomEvent = new CustomEvent('canvas.edited', { const event: CustomEvent = new CustomEvent('canvas.edited', {
bubbles: false, bubbles: false,
cancelable: true, cancelable: true,
@ -1732,14 +1732,14 @@ export class CanvasViewImpl implements CanvasView, Listener {
private addText(state: any): SVG.Text { private addText(state: any): SVG.Text {
const { undefinedAttrValue } = this.configuration; const { undefinedAttrValue } = this.configuration;
const { label, clientID, attributes } = state; const { label, clientID, attributes, source } = state;
const attrNames = label.attributes.reduce((acc: any, val: any): void => { const attrNames = label.attributes.reduce((acc: any, val: any): void => {
acc[val.id] = val.name; acc[val.id] = val.name;
return acc; return acc;
}, {}); }, {});
return this.adoptedText.text((block): void => { return this.adoptedText.text((block): void => {
block.tspan(`${label.name} ${clientID}`).style('text-transform', 'uppercase'); block.tspan(`${label.name} ${clientID} (${source})`).style('text-transform', 'uppercase');
for (const attrID of Object.keys(attributes)) { for (const attrID of Object.keys(attributes)) {
const value = attributes[attrID] === undefinedAttrValue const value = attributes[attrID] === undefinedAttrValue
? '' : attributes[attrID]; ? '' : attributes[attrID];

@ -402,6 +402,7 @@
frame: Math.min.apply(null, Object.keys(keyframes).map((frame) => +frame)), frame: Math.min.apply(null, Object.keys(keyframes).map((frame) => +frame)),
shapes: Object.values(keyframes), shapes: Object.values(keyframes),
group: 0, group: 0,
source: objectStates[0].source,
label_id: label.id, label_id: label.id,
attributes: Object.keys(objectStates[0].attributes) attributes: Object.keys(objectStates[0].attributes)
.reduce((accumulator, attrID) => { .reduce((accumulator, attrID) => {
@ -763,6 +764,7 @@
points: [...state.points], points: [...state.points],
type: state.shapeType, type: state.shapeType,
z_order: state.zOrder, z_order: state.zOrder,
source: state.source,
}); });
} else if (state.objectType === 'track') { } else if (state.objectType === 'track') {
constructed.tracks.push({ constructed.tracks.push({
@ -770,6 +772,7 @@
.filter((attr) => !labelAttributes[attr.spec_id].mutable), .filter((attr) => !labelAttributes[attr.spec_id].mutable),
frame: state.frame, frame: state.frame,
group: 0, group: 0,
source: state.source,
label_id: state.label.id, label_id: state.label.id,
shapes: [{ shapes: [{
attributes: attributes attributes: attributes

@ -183,6 +183,7 @@
this.removed = false; this.removed = false;
this.lock = false; this.lock = false;
this.color = color; this.color = color;
this.source = data.source;
this.updated = Date.now(); this.updated = Date.now();
this.attributes = data.attributes.reduce((attributeAccumulator, attr) => { this.attributes = data.attributes.reduce((attributeAccumulator, attr) => {
attributeAccumulator[attr.spec_id] = attr.value; attributeAccumulator[attr.spec_id] = attr.value;
@ -295,6 +296,21 @@
}, [this.clientID], frame); }, [this.clientID], frame);
} }
_saveSource(source, frame) {
const undoSource = this.source;
const redoSource = source;
this.history.do(HistoryActions.CHANGED_SOURCE, () => {
this.source = undoSource;
this.updated = Date.now();
}, () => {
this.source = redoSource;
this.updated = Date.now();
}, [this.clientID], frame);
this.source = source;
}
_validateStateBeforeSave(frame, data, updated) { _validateStateBeforeSave(frame, data, updated) {
let fittedPoints = []; let fittedPoints = [];
@ -381,6 +397,10 @@
} }
} }
if (updated.source) {
checkObjectType('source', data.source, 'string', null);
}
return fittedPoints; return fittedPoints;
} }
@ -396,7 +416,8 @@
updateTimestamp(updated) { updateTimestamp(updated) {
const anyChanges = updated.label || updated.attributes || updated.points const anyChanges = updated.label || updated.attributes || updated.points
|| updated.outside || updated.occluded || updated.keyframe || updated.outside || updated.occluded || updated.keyframe
|| updated.zOrder || updated.hidden || updated.lock || updated.pinned; || updated.zOrder || updated.hidden || updated.lock || updated.pinned
|| updated.source;
if (anyChanges) { if (anyChanges) {
this.updated = Date.now(); this.updated = Date.now();
@ -492,6 +513,7 @@
frame: this.frame, frame: this.frame,
label_id: this.label.id, label_id: this.label.id,
group: this.group, group: this.group,
source: this.source,
}; };
} }
@ -520,6 +542,7 @@
updated: this.updated, updated: this.updated,
pinned: this.pinned, pinned: this.pinned,
frame, frame,
source: this.source,
}; };
} }
@ -619,6 +642,10 @@
this._saveHidden(data.hidden, frame); this._saveHidden(data.hidden, frame);
} }
if (updated.source) {
this._saveSource(data.source, frame);
}
this.updateTimestamp(updated); this.updateTimestamp(updated);
updated.reset(); updated.reset();
@ -659,6 +686,7 @@
frame: this.frame, frame: this.frame,
label_id: this.label.id, label_id: this.label.id,
group: this.group, group: this.group,
source: this.source,
attributes: Object.keys(this.attributes).reduce((attributeAccumulator, attrId) => { attributes: Object.keys(this.attributes).reduce((attributeAccumulator, attrId) => {
if (!labelAttributes[attrId].mutable) { if (!labelAttributes[attrId].mutable) {
attributeAccumulator.push({ attributeAccumulator.push({
@ -726,6 +754,7 @@
last, last,
}, },
frame, frame,
source: this.source,
}; };
} }
@ -1034,6 +1063,7 @@
outside: current.outside, outside: current.outside,
occluded: current.occluded, occluded: current.occluded,
attributes: {}, attributes: {},
source: current.source,
} : undefined; } : undefined;
if (redoShape) { if (redoShape) {
@ -1098,6 +1128,10 @@
this._saveAttributes(data.attributes, frame); this._saveAttributes(data.attributes, frame);
} }
if (updated.source) {
this._saveSource(data.source, frame);
}
if (updated.keyframe) { if (updated.keyframe) {
this._saveKeyframe(frame, data.keyframe); this._saveKeyframe(frame, data.keyframe);
} }
@ -1164,6 +1198,7 @@
frame: this.frame, frame: this.frame,
label_id: this.label.id, label_id: this.label.id,
group: this.group, group: this.group,
source: this.source,
attributes: Object.keys(this.attributes).reduce((attributeAccumulator, attrId) => { attributes: Object.keys(this.attributes).reduce((attributeAccumulator, attrId) => {
attributeAccumulator.push({ attributeAccumulator.push({
spec_id: attrId, spec_id: attrId,
@ -1194,6 +1229,7 @@
color: this.color, color: this.color,
updated: this.updated, updated: this.updated,
frame, frame,
source: this.source,
}; };
} }
@ -1228,6 +1264,10 @@
this._saveColor(data.color, frame); this._saveColor(data.color, frame);
} }
if (updated.source) {
this._saveSource(data.source, frame);
}
this.updateTimestamp(updated); this.updateTimestamp(updated);
updated.reset(); updated.reset();

@ -104,7 +104,7 @@
const keys = ['id', 'label_id', 'group', 'frame', const keys = ['id', 'label_id', 'group', 'frame',
'occluded', 'z_order', 'points', 'type', 'shapes', 'occluded', 'z_order', 'points', 'type', 'shapes',
'attributes', 'value', 'spec_id', 'outside']; 'attributes', 'value', 'spec_id', 'source', 'outside'];
// Find created and updated objects // Find created and updated objects
for (const type of Object.keys(exported)) { for (const type of Object.keys(exported)) {

@ -31,6 +31,7 @@ function build() {
LogType, LogType,
HistoryActions, HistoryActions,
colors, colors,
source,
} = require('./enums'); } = require('./enums');
const { const {
@ -531,6 +532,7 @@ function build() {
LogType, LogType,
HistoryActions, HistoryActions,
colors, colors,
source,
}, },
/** /**
* Namespace is used for access to exceptions * Namespace is used for access to exceptions

@ -104,6 +104,20 @@
CUBOID: 'cuboid', CUBOID: 'cuboid',
}); });
/**
* Annotation type
* @enum {string}
* @name source
* @memberof module:API.cvat.enums
* @property {string} MANUAL 'manual'
* @property {string} AUTO 'auto'
* @readonly
*/
const source = Object.freeze({
MANUAL:'manual',
AUTO:'auto',
});
/** /**
* Logger event types * Logger event types
* @enum {string} * @enum {string}
@ -190,6 +204,7 @@
* @property {string} CHANGED_LOCK Changed lock * @property {string} CHANGED_LOCK Changed lock
* @property {string} CHANGED_COLOR Changed color * @property {string} CHANGED_COLOR Changed color
* @property {string} CHANGED_HIDDEN Changed hidden * @property {string} CHANGED_HIDDEN Changed hidden
* @property {string} CHANGED_SOURCE Changed source
* @property {string} MERGED_OBJECTS Merged objects * @property {string} MERGED_OBJECTS Merged objects
* @property {string} SPLITTED_TRACK Splitted track * @property {string} SPLITTED_TRACK Splitted track
* @property {string} GROUPED_OBJECTS Grouped objects * @property {string} GROUPED_OBJECTS Grouped objects
@ -209,6 +224,7 @@
CHANGED_PINNED: 'Changed pinned', CHANGED_PINNED: 'Changed pinned',
CHANGED_COLOR: 'Changed color', CHANGED_COLOR: 'Changed color',
CHANGED_HIDDEN: 'Changed hidden', CHANGED_HIDDEN: 'Changed hidden',
CHANGED_SOURCE: 'Changed source',
MERGED_OBJECTS: 'Merged objects', MERGED_OBJECTS: 'Merged objects',
SPLITTED_TRACK: 'Splitted track', SPLITTED_TRACK: 'Splitted track',
GROUPED_OBJECTS: 'Grouped objects', GROUPED_OBJECTS: 'Grouped objects',
@ -241,5 +257,6 @@
LogType, LogType,
HistoryActions, HistoryActions,
colors, colors,
source,
}; };
})(); })();

@ -22,7 +22,7 @@
* </br> Necessary fields: objectType, shapeType, frame, updated, group * </br> Necessary fields: objectType, shapeType, frame, updated, group
* </br> Optional fields: keyframes, clientID, serverID * </br> Optional fields: keyframes, clientID, serverID
* </br> Optional fields which can be set later: points, zOrder, outside, * </br> Optional fields which can be set later: points, zOrder, outside,
* occluded, hidden, attributes, lock, label, color, keyframe * occluded, hidden, attributes, lock, label, color, keyframe, source
*/ */
constructor(serialized) { constructor(serialized) {
const data = { const data = {
@ -39,6 +39,7 @@
color: null, color: null,
hidden: null, hidden: null,
pinned: null, pinned: null,
source: null,
keyframes: serialized.keyframes, keyframes: serialized.keyframes,
group: serialized.group, group: serialized.group,
updated: serialized.updated, updated: serialized.updated,
@ -68,6 +69,7 @@
this.lock = false; this.lock = false;
this.color = false; this.color = false;
this.hidden = false; this.hidden = false;
this.source = false;
return reset; return reset;
}, },
@ -109,6 +111,20 @@
*/ */
get: () => data.shapeType, get: () => data.shapeType,
}, },
source: {
/**
* @name source
* @type {module:API.cvat.enums.source}
* @memberof module:API.cvat.classes.ObjectState
* @readonly
* @instance
*/
get: () => data.source,
set: (source) => {
data.updateFlags.source = true;
data.source = source;
},
},
clientID: { clientID: {
/** /**
* @name clientID * @name clientID
@ -343,6 +359,7 @@
this.label = serialized.label; this.label = serialized.label;
this.lock = serialized.lock; this.lock = serialized.lock;
this.source = serialized.source;
if (typeof (serialized.zOrder) === 'number') { if (typeof (serialized.zOrder) === 'number') {
this.zOrder = serialized.zOrder; this.zOrder = serialized.zOrder;

@ -485,6 +485,7 @@ export function propagateObjectAsync(
label: objectState.label, label: objectState.label,
zOrder: objectState.zOrder, zOrder: objectState.zOrder,
frame: from, frame: from,
source: objectState.source,
}; };
await sessionInstance.logger.log( await sessionInstance.logger.log(

@ -324,6 +324,7 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
.filter((label: any) => label.id === activeLabelID)[0]; .filter((label: any) => label.id === activeLabelID)[0];
state.occluded = state.occluded || false; state.occluded = state.occluded || false;
state.frame = frame; state.frame = frame;
state.source = 'manual';
const objectState = new cvat.classes.ObjectState(state); const objectState = new cvat.classes.ObjectState(state);
onCreateAnnotations(jobInstance, frame, [objectState]); onCreateAnnotations(jobInstance, frame, [objectState]);
}; };
@ -500,6 +501,7 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
points, points,
} = event.detail; } = event.detail;
state.points = points; state.points = points;
state.source = 'manual';
onUpdateAnnotations([state]); onUpdateAnnotations([state]);
}; };

@ -21,13 +21,13 @@ from .annotation import AnnotationManager, TrackManager
class TaskData: class TaskData:
Attribute = namedtuple('Attribute', 'name, value') Attribute = namedtuple('Attribute', 'name, value')
LabeledShape = namedtuple( LabeledShape = namedtuple(
'LabeledShape', 'type, frame, label, points, occluded, attributes, group, z_order') 'LabeledShape', 'type, frame, label, points, occluded, attributes, source, group, z_order')
LabeledShape.__new__.__defaults__ = (0, 0) LabeledShape.__new__.__defaults__ = (0, 0)
TrackedShape = namedtuple( TrackedShape = namedtuple(
'TrackedShape', 'type, frame, points, occluded, outside, keyframe, attributes, group, z_order, label, track_id') 'TrackedShape', 'type, frame, points, occluded, outside, keyframe, attributes, source, group, z_order, label, track_id')
TrackedShape.__new__.__defaults__ = (0, 0, None, 0) TrackedShape.__new__.__defaults__ = ('manual', 0, 0, None, 0)
Track = namedtuple('Track', 'label, group, shapes') Track = namedtuple('Track', 'label, group, source, shapes')
Tag = namedtuple('Tag', 'frame, label, attributes, group') Tag = namedtuple('Tag', 'frame, label, attributes, source, group')
Tag.__new__.__defaults__ = (0, ) Tag.__new__.__defaults__ = (0, )
Frame = namedtuple( Frame = namedtuple(
'Frame', 'idx, frame, name, width, height, labeled_shapes, tags') 'Frame', 'idx, frame, name, width, height, labeled_shapes, tags')
@ -217,6 +217,7 @@ class TaskData:
outside=shape.get("outside", False), outside=shape.get("outside", False),
keyframe=shape.get("keyframe", True), keyframe=shape.get("keyframe", True),
track_id=shape["track_id"], track_id=shape["track_id"],
source=shape.get("source", "manual"),
attributes=self._export_attributes(shape["attributes"]), attributes=self._export_attributes(shape["attributes"]),
) )
@ -229,6 +230,7 @@ class TaskData:
occluded=shape["occluded"], occluded=shape["occluded"],
z_order=shape.get("z_order", 0), z_order=shape.get("z_order", 0),
group=shape.get("group", 0), group=shape.get("group", 0),
source=shape["source"],
attributes=self._export_attributes(shape["attributes"]), attributes=self._export_attributes(shape["attributes"]),
) )
@ -237,6 +239,7 @@ class TaskData:
frame=self.abs_frame_id(tag["frame"]), frame=self.abs_frame_id(tag["frame"]),
label=self._get_label_name(tag["label_id"]), label=self._get_label_name(tag["label_id"]),
group=tag.get("group", 0), group=tag.get("group", 0),
source=tag["source"],
attributes=self._export_attributes(tag["attributes"]), attributes=self._export_attributes(tag["attributes"]),
) )
@ -290,11 +293,13 @@ class TaskData:
tracked_shape["attributes"] += track["attributes"] tracked_shape["attributes"] += track["attributes"]
tracked_shape["track_id"] = idx tracked_shape["track_id"] = idx
tracked_shape["group"] = track["group"] tracked_shape["group"] = track["group"]
tracked_shape["source"] = track["source"]
tracked_shape["label_id"] = track["label_id"] tracked_shape["label_id"] = track["label_id"]
yield TaskData.Track( yield TaskData.Track(
label=self._get_label_name(track["label_id"]), label=self._get_label_name(track["label_id"]),
group=track["group"], group=track["group"],
source=track["source"],
shapes=[self._export_tracked_shape(shape) shapes=[self._export_tracked_shape(shape)
for shape in tracked_shapes], for shape in tracked_shapes],
) )
@ -650,6 +655,7 @@ def import_dm_annotations(dm_dataset, task_data):
occluded=ann.attributes.get('occluded') == True, occluded=ann.attributes.get('occluded') == True,
z_order=ann.z_order, z_order=ann.z_order,
group=group_map.get(ann.group, 0), group=group_map.get(ann.group, 0),
source='manual',
attributes=[task_data.Attribute(name=n, value=str(v)) attributes=[task_data.Attribute(name=n, value=str(v))
for n, v in ann.attributes.items()], for n, v in ann.attributes.items()],
)) ))
@ -658,6 +664,7 @@ def import_dm_annotations(dm_dataset, task_data):
frame=frame_number, frame=frame_number,
label=label_cat.items[ann.label].name, label=label_cat.items[ann.label].name,
group=group_map.get(ann.group, 0), group=group_map.get(ann.group, 0),
source='manual',
attributes=[task_data.Attribute(name=n, value=str(v)) attributes=[task_data.Attribute(name=n, value=str(v))
for n, v in ann.attributes.items()], for n, v in ann.attributes.items()],
)) ))

@ -190,6 +190,7 @@ def dump_as_cvat_annotation(file_object, annotations):
dump_data = OrderedDict([ dump_data = OrderedDict([
("label", shape.label), ("label", shape.label),
("occluded", str(int(shape.occluded))), ("occluded", str(int(shape.occluded))),
("source", shape.source),
]) ])
if shape.type == "rectangle": if shape.type == "rectangle":
@ -269,6 +270,7 @@ def dump_as_cvat_annotation(file_object, annotations):
for tag in frame_annotation.tags: for tag in frame_annotation.tags:
tag_data = OrderedDict([ tag_data = OrderedDict([
("label", tag.label), ("label", tag.label),
("source", tag.source),
]) ])
if tag.group: if tag.group:
tag_data["group_id"] = str(tag.group) tag_data["group_id"] = str(tag.group)
@ -294,6 +296,7 @@ def dump_as_cvat_interpolation(file_object, annotations):
dump_data = OrderedDict([ dump_data = OrderedDict([
("id", str(track_id)), ("id", str(track_id)),
("label", track.label), ("label", track.label),
("source", track.source),
]) ])
if track.group: if track.group:
@ -385,6 +388,7 @@ def dump_as_cvat_interpolation(file_object, annotations):
dump_track(counter, annotations.Track( dump_track(counter, annotations.Track(
label=shape.label, label=shape.label,
group=shape.group, group=shape.group,
source=shape.source,
shapes=[annotations.TrackedShape( shapes=[annotations.TrackedShape(
type=shape.type, type=shape.type,
points=shape.points, points=shape.points,
@ -430,6 +434,7 @@ def load(file_object, annotations):
track = annotations.Track( track = annotations.Track(
label=el.attrib['label'], label=el.attrib['label'],
group=int(el.attrib.get('group_id', 0)), group=int(el.attrib.get('group_id', 0)),
source=el.attrib.get('source', 'manual'),
shapes=[], shapes=[],
) )
elif el.tag == 'image': elif el.tag == 'image':
@ -448,6 +453,7 @@ def load(file_object, annotations):
'label': el.attrib['label'], 'label': el.attrib['label'],
'group': int(el.attrib.get('group_id', 0)), 'group': int(el.attrib.get('group_id', 0)),
'attributes': attributes, 'attributes': attributes,
'source': str(el.attrib.get('source', 'manual'))
} }
elif ev == 'end': elif ev == 'end':
if el.tag == 'attribute' and attributes is not None: if el.tag == 'attribute' and attributes is not None:
@ -464,6 +470,7 @@ def load(file_object, annotations):
shape['frame'] = frame_id shape['frame'] = frame_id
shape['label'] = el.attrib['label'] shape['label'] = el.attrib['label']
shape['group'] = int(el.attrib.get('group_id', 0)) shape['group'] = int(el.attrib.get('group_id', 0))
shape['source'] = str(el.attrib.get('source', 'manual'))
shape['type'] = 'rectangle' if el.tag == 'box' else el.tag shape['type'] = 'rectangle' if el.tag == 'box' else el.tag
shape['occluded'] = el.attrib['occluded'] == '1' shape['occluded'] = el.attrib['occluded'] == '1'

@ -54,6 +54,7 @@ def _import(src_file, task_data):
group=0, group=0,
frame=frame_number, frame=frame_number,
attributes=[], attributes=[],
source='manual',
)) ))
continue continue
@ -66,12 +67,13 @@ def _import(src_file, task_data):
z_order=ann.z_order, z_order=ann.z_order,
frame=frame_number, frame=frame_number,
attributes=[], attributes=[],
source='manual',
) )
# build trajectories as lists of shapes in track dict # build trajectories as lists of shapes in track dict
if track_id not in tracks: if track_id not in tracks:
tracks[track_id] = task_data.Track( tracks[track_id] = task_data.Track(
label_cat.items[ann.label].name, 0, []) label_cat.items[ann.label].name, 0, 'manual', [])
tracks[track_id].shapes.append(shape) tracks[track_id].shapes.append(shape)
for track in tracks.values(): for track in tracks.values():

@ -381,6 +381,7 @@ class JobAnnotation:
'frame', 'frame',
'label_id', 'label_id',
'group', 'group',
'source',
'labeledimageattributeval__spec_id', 'labeledimageattributeval__spec_id',
'labeledimageattributeval__value', 'labeledimageattributeval__value',
'labeledimageattributeval__id', 'labeledimageattributeval__id',
@ -415,6 +416,7 @@ class JobAnnotation:
'type', 'type',
'frame', 'frame',
'group', 'group',
'source',
'occluded', 'occluded',
'z_order', 'z_order',
'points', 'points',
@ -451,6 +453,7 @@ class JobAnnotation:
"frame", "frame",
"label_id", "label_id",
"group", "group",
"source",
"labeledtrackattributeval__spec_id", "labeledtrackattributeval__spec_id",
"labeledtrackattributeval__value", "labeledtrackattributeval__value",
"labeledtrackattributeval__id", "labeledtrackattributeval__id",

@ -163,6 +163,7 @@ class TaskExportTest(_DbTestBase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -181,6 +182,7 @@ class TaskExportTest(_DbTestBase):
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3], "points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3],
"type": "polygon", "type": "polygon",
@ -190,6 +192,7 @@ class TaskExportTest(_DbTestBase):
"frame": 1, "frame": 1,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": 1, "group": 1,
"source": "manual",
"attributes": [], "attributes": [],
"points": [100, 300.222, 400, 500, 1, 3], "points": [100, 300.222, 400, 500, 1, 3],
"type": "points", "type": "points",
@ -199,6 +202,7 @@ class TaskExportTest(_DbTestBase):
"frame": 1, "frame": 1,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": 1, "group": 1,
"source": "manual",
"attributes": [], "attributes": [],
"points": [2.0, 2.1, 400, 500, 1, 3], "points": [2.0, 2.1, 400, 500, 1, 3],
"type": "polyline", "type": "polyline",
@ -210,6 +214,7 @@ class TaskExportTest(_DbTestBase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -244,6 +249,7 @@ class TaskExportTest(_DbTestBase):
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"shapes": [ "shapes": [
{ {

@ -13,6 +13,7 @@ class TrackManagerTest(TestCase):
"frame": 0, "frame": 0,
"label_id": 0, "label_id": 0,
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"shapes": [ "shapes": [
{ {
@ -44,6 +45,7 @@ class TrackManagerTest(TestCase):
"label_id": 0, "label_id": 0,
"group": None, "group": None,
"attributes": [], "attributes": [],
"source": "manual",
"shapes": [ "shapes": [
{ {
"frame": 0, "frame": 0,
@ -74,6 +76,7 @@ class TrackManagerTest(TestCase):
"label_id": 0, "label_id": 0,
"group": None, "group": None,
"attributes": [], "attributes": [],
"source": "manual",
"shapes": [ "shapes": [
{ {
"frame": 0, "frame": 0,
@ -104,6 +107,7 @@ class TrackManagerTest(TestCase):
"label_id": 0, "label_id": 0,
"group": None, "group": None,
"attributes": [], "attributes": [],
"source": "manual",
"shapes": [ "shapes": [
{ {
"frame": 0, "frame": 0,

@ -0,0 +1,28 @@
# Generated by Django 2.2.10 on 2020-07-19 15:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('engine', '0026_auto_20200719_1511'),
]
operations = [
migrations.AddField(
model_name='labeledimage',
name='source',
field=models.CharField(choices=[('auto', 'AUTO'), ('manual', 'MANUAL')], default='manual', max_length=16, null=True),
),
migrations.AddField(
model_name='labeledshape',
name='source',
field=models.CharField(choices=[('auto', 'AUTO'), ('manual', 'MANUAL')], default='manual', max_length=16, null=True),
),
migrations.AddField(
model_name='labeledtrack',
name='source',
field=models.CharField(choices=[('auto', 'AUTO'), ('manual', 'MANUAL')], default='manual', max_length=16, null=True),
),
]

@ -302,12 +302,24 @@ class ShapeType(str, Enum):
def __str__(self): def __str__(self):
return self.value return self.value
class source(str, Enum):
AUTO = 'auto'
MANUAL = 'manual'
@classmethod
def choices(self):
return tuple((x.value, x.name) for x in self)
def __str__(self):
return self.value
class Annotation(models.Model): class Annotation(models.Model):
id = models.BigAutoField(primary_key=True) id = models.BigAutoField(primary_key=True)
job = models.ForeignKey(Job, on_delete=models.CASCADE) job = models.ForeignKey(Job, on_delete=models.CASCADE)
label = models.ForeignKey(Label, on_delete=models.CASCADE) label = models.ForeignKey(Label, on_delete=models.CASCADE)
frame = models.PositiveIntegerField() frame = models.PositiveIntegerField()
group = models.PositiveIntegerField(null=True) group = models.PositiveIntegerField(null=True)
source = models.CharField(max_length=16, choices=source.choices(), default="manual", null=True)
class Meta: class Meta:
abstract = True abstract = True

@ -409,6 +409,7 @@ class AnnotationSerializer(serializers.Serializer):
frame = serializers.IntegerField(min_value=0) frame = serializers.IntegerField(min_value=0)
label_id = serializers.IntegerField(min_value=0) label_id = serializers.IntegerField(min_value=0)
group = serializers.IntegerField(min_value=0, allow_null=True) group = serializers.IntegerField(min_value=0, allow_null=True)
source = serializers.CharField(default = 'manual')
class LabeledImageSerializer(AnnotationSerializer): class LabeledImageSerializer(AnnotationSerializer):
attributes = AttributeValSerializer(many=True, attributes = AttributeValSerializer(many=True,

@ -2100,6 +2100,7 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [] "attributes": []
} }
], ],
@ -2108,6 +2109,7 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -2126,6 +2128,7 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3], "points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3],
"type": "polygon", "type": "polygon",
@ -2137,6 +2140,7 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -2171,6 +2175,7 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"shapes": [ "shapes": [
{ {
@ -2220,6 +2225,7 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [] "attributes": []
} }
], ],
@ -2228,6 +2234,7 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -2240,16 +2247,17 @@ class JobAnnotationAPITestCase(APITestCase):
], ],
"points": [1.0, 2.1, 100, 300.222], "points": [1.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": False "occluded": False,
}, },
{ {
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3], "points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3],
"type": "polygon", "type": "polygon",
"occluded": False "occluded": False,
}, },
], ],
"tracks": [ "tracks": [
@ -2257,6 +2265,7 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -2283,7 +2292,7 @@ class JobAnnotationAPITestCase(APITestCase):
"points": [2.0, 2.1, 100, 300.222], "points": [2.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": True, "occluded": True,
"outside": True "outside": True,
}, },
] ]
}, },
@ -2291,6 +2300,7 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"shapes": [ "shapes": [
{ {
@ -2299,7 +2309,7 @@ class JobAnnotationAPITestCase(APITestCase):
"points": [1.0, 2.1, 100, 300.222], "points": [1.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": False, "occluded": False,
"outside": False "outside": False,
} }
] ]
}, },
@ -2361,7 +2371,8 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 0, "frame": 0,
"label_id": 11010101, "label_id": 11010101,
"group": None, "group": None,
"attributes": [] "source": "manual",
"attributes": [],
} }
], ],
"shapes": [ "shapes": [
@ -2369,6 +2380,7 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": 32234234, "spec_id": 32234234,
@ -2381,16 +2393,17 @@ class JobAnnotationAPITestCase(APITestCase):
], ],
"points": [1.0, 2.1, 100, 300.222], "points": [1.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": False "occluded": False,
}, },
{ {
"frame": 1, "frame": 1,
"label_id": 1212121, "label_id": 1212121,
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3], "points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3],
"type": "polygon", "type": "polygon",
"occluded": False "occluded": False,
}, },
], ],
"tracks": [ "tracks": [
@ -2398,6 +2411,7 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 0, "frame": 0,
"label_id": 0, "label_id": 0,
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"shapes": [ "shapes": [
{ {
@ -2423,7 +2437,7 @@ class JobAnnotationAPITestCase(APITestCase):
"points": [2.0, 2.1, 100, 300.222], "points": [2.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": True, "occluded": True,
"outside": True "outside": True,
}, },
] ]
}, },
@ -2431,6 +2445,7 @@ class JobAnnotationAPITestCase(APITestCase):
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"shapes": [ "shapes": [
{ {
@ -2439,7 +2454,7 @@ class JobAnnotationAPITestCase(APITestCase):
"points": [1.0, 2.1, 100, 300.222], "points": [1.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": False, "occluded": False,
"outside": False "outside": False,
} }
] ]
}, },
@ -2574,7 +2589,8 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"attributes": [] "source": "manual",
"attributes": [],
} }
], ],
"shapes": [ "shapes": [
@ -2582,6 +2598,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -2594,16 +2611,17 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
], ],
"points": [1.0, 2.1, 100, 300.222], "points": [1.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": False "occluded": False,
}, },
{ {
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3], "points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3],
"type": "polygon", "type": "polygon",
"occluded": False "occluded": False,
}, },
], ],
"tracks": [ "tracks": [
@ -2611,6 +2629,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -2637,7 +2656,8 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"points": [2.0, 2.1, 100, 300.222], "points": [2.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": True, "occluded": True,
"outside": True "outside": True,
}, },
] ]
}, },
@ -2645,6 +2665,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"shapes": [ "shapes": [
{ {
@ -2653,7 +2674,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"points": [1.0, 2.1, 100, 300.222], "points": [1.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": False, "occluded": False,
"outside": False "outside": False,
} }
] ]
}, },
@ -2694,7 +2715,8 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"attributes": [] "source": "manual",
"attributes": [],
} }
], ],
"shapes": [ "shapes": [
@ -2702,6 +2724,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -2714,16 +2737,17 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
], ],
"points": [1.0, 2.1, 100, 300.222], "points": [1.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": False "occluded": False,
}, },
{ {
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3], "points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3],
"type": "polygon", "type": "polygon",
"occluded": False "occluded": False,
}, },
], ],
"tracks": [ "tracks": [
@ -2731,6 +2755,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -2757,7 +2782,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"points": [2.0, 2.1, 100, 300.222], "points": [2.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": True, "occluded": True,
"outside": True "outside": True,
}, },
] ]
}, },
@ -2765,6 +2790,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"shapes": [ "shapes": [
{ {
@ -2773,7 +2799,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"points": [1.0, 2.1, 100, 300.222], "points": [1.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": False, "occluded": False,
"outside": False "outside": False,
} }
] ]
}, },
@ -2835,7 +2861,8 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 0, "frame": 0,
"label_id": 11010101, "label_id": 11010101,
"group": None, "group": None,
"attributes": [] "source": "manual",
"attributes": [],
} }
], ],
"shapes": [ "shapes": [
@ -2843,6 +2870,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": 32234234, "spec_id": 32234234,
@ -2855,16 +2883,17 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
], ],
"points": [1.0, 2.1, 100, 300.222], "points": [1.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": False "occluded": False,
}, },
{ {
"frame": 1, "frame": 1,
"label_id": 1212121, "label_id": 1212121,
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3], "points": [2.0, 2.1, 100, 300.222, 400, 500, 1, 3],
"type": "polygon", "type": "polygon",
"occluded": False "occluded": False,
}, },
], ],
"tracks": [ "tracks": [
@ -2872,6 +2901,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 0, "frame": 0,
"label_id": 0, "label_id": 0,
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"shapes": [ "shapes": [
{ {
@ -2897,7 +2927,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"points": [2.0, 2.1, 100, 300.222], "points": [2.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": True, "occluded": True,
"outside": True "outside": True,
}, },
] ]
}, },
@ -2905,6 +2935,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": None, "group": None,
"source": "manual",
"attributes": [], "attributes": [],
"shapes": [ "shapes": [
{ {
@ -2913,7 +2944,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"points": [1.0, 2.1, 100, 300.222], "points": [1.0, 2.1, 100, 300.222],
"type": "rectangle", "type": "rectangle",
"occluded": False, "occluded": False,
"outside": False "outside": False,
} }
] ]
}, },
@ -2940,6 +2971,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": 0, "group": 0,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -2992,6 +3024,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": 0, "group": 0,
"source": "manual",
"attributes": [], "attributes": [],
"shapes": [ "shapes": [
{ {
@ -3000,7 +3033,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"points": [1.0, 2.1, 50.2, 36.6], "points": [1.0, 2.1, 50.2, 36.6],
"type": "rectangle", "type": "rectangle",
"occluded": False, "occluded": False,
"outside": False "outside": False,
}, },
{ {
"frame": 1, "frame": 1,
@ -3016,7 +3049,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"points": [1.0, 2.1, 51, 36.6], "points": [1.0, 2.1, 51, 36.6],
"type": "rectangle", "type": "rectangle",
"occluded": False, "occluded": False,
"outside": True "outside": True,
} }
] ]
}] }]
@ -3025,6 +3058,7 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
"frame": 0, "frame": 0,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": 0, "group": 0,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -3037,33 +3071,36 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
], ],
"points": [1.0, 2.1, 10.6, 53.22], "points": [1.0, 2.1, 10.6, 53.22],
"type": "rectangle", "type": "rectangle",
"occluded": False "occluded": False,
}] }]
rectangle_shapes_wo_attrs = [{ rectangle_shapes_wo_attrs = [{
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": 0, "group": 0,
"source": "manual",
"attributes": [], "attributes": [],
"points": [2.0, 2.1, 40, 50.7], "points": [2.0, 2.1, 40, 50.7],
"type": "rectangle", "type": "rectangle",
"occluded": False "occluded": False,
}] }]
polygon_shapes_wo_attrs = [{ polygon_shapes_wo_attrs = [{
"frame": 1, "frame": 1,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": 0, "group": 0,
"source": "manual",
"attributes": [], "attributes": [],
"points": [2.0, 2.1, 100, 30.22, 40, 77, 1, 3], "points": [2.0, 2.1, 100, 30.22, 40, 77, 1, 3],
"type": "polygon", "type": "polygon",
"occluded": False "occluded": False,
}] }]
polygon_shapes_with_attrs = [{ polygon_shapes_with_attrs = [{
"frame": 2, "frame": 2,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": 1, "group": 1,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],
@ -3076,28 +3113,31 @@ class TaskAnnotationAPITestCase(JobAnnotationAPITestCase):
], ],
"points": [20.0, 0.1, 10, 3.22, 4, 7, 10, 30, 1, 2, 4.44, 5.55], "points": [20.0, 0.1, 10, 3.22, 4, 7, 10, 30, 1, 2, 4.44, 5.55],
"type": "polygon", "type": "polygon",
"occluded": True "occluded": True,
}, },
{ {
"frame": 2, "frame": 2,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": 1, "group": 1,
"source": "manual",
"attributes": [], "attributes": [],
"points": [4, 7, 10, 30, 4, 5.55], "points": [4, 7, 10, 30, 4, 5.55],
"type": "polygon", "type": "polygon",
"occluded": False "occluded": False,
}] }]
tags_wo_attrs = [{ tags_wo_attrs = [{
"frame": 2, "frame": 2,
"label_id": task["labels"][1]["id"], "label_id": task["labels"][1]["id"],
"group": 0, "group": 0,
"attributes": [] "source": "manual",
"attributes": [],
}] }]
tags_with_attrs = [{ tags_with_attrs = [{
"frame": 1, "frame": 1,
"label_id": task["labels"][0]["id"], "label_id": task["labels"][0]["id"],
"group": 3, "group": 3,
"source": "manual",
"attributes": [ "attributes": [
{ {
"spec_id": task["labels"][0]["attributes"][0]["id"], "spec_id": task["labels"][0]["attributes"][0]["id"],

@ -174,6 +174,7 @@ def convert_to_cvat_format(data):
"group": None, "group": None,
"occluded": False, "occluded": False,
"attributes": [], "attributes": [],
"source": "auto",
}) })
return result return result

Loading…
Cancel
Save