Skip to content
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

CVAT.js implemented API methods and bug fixes #564

Merged
merged 10 commits into from
Jul 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
351 changes: 274 additions & 77 deletions cvatjs/src/annotations-collection.js

Large diffs are not rendered by default.

161 changes: 90 additions & 71 deletions cvatjs/src/annotations-objects.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,54 +9,22 @@

(() => {
const ObjectState = require('./object-state');
const { checkObjectType } = require('./common');

// Called with the Annotation context
function objectStateFactory(frame, data) {
const objectState = new ObjectState(data);

// Rewrite default implementations of save/delete
objectState.updateInCollection = this.save.bind(this, frame, objectState);
objectState.deleteFromCollection = this.delete.bind(this);
objectState.hidden = {
save: this.save.bind(this, frame, objectState),
delete: this.delete.bind(this),
up: this.up.bind(this, frame, objectState),
down: this.down.bind(this, frame, objectState),
};

return objectState;
}

function checkObjectType(name, value, type, instance) {
if (type) {
if (typeof (value) !== type) {
// specific case for integers which aren't native type in JS
if (type === 'integer' && Number.isInteger(value)) {
return;
}

if (value !== undefined) {
throw new window.cvat.exceptions.ArgumentError(
`Got ${typeof (value)} value for ${name}. `
+ `Expected ${type}`,
);
}

throw new window.cvat.exceptions.ArgumentError(
`Got undefined value for ${name}. `
+ `Expected ${type}`,
);
}
} else if (instance) {
if (!(value instanceof instance)) {
if (value !== undefined) {
throw new window.cvat.exceptions.ArgumentError(
`Got ${value.constructor.name} value for ${name}. `
+ `Expected instance of ${instance.name}`,
);
}

throw new window.cvat.exceptions.ArgumentError(
`Got undefined value for ${name}. `
+ `Expected instance of ${instance.name}`,
);
}
}
}

class Annotation {
constructor(data, clientID, injection) {
this.taskLabels = injection.labels;
Expand Down Expand Up @@ -92,19 +60,73 @@
}
}

class Shape extends Annotation {
class Drawn extends Annotation {
constructor(data, clientID, color, injection) {
super(data, clientID, injection);

this.collectionZ = injection.collectionZ;
const z = this._getZ(this.frame);
z.max = Math.max(z.max, this.zOrder || 0);
z.min = Math.min(z.min, this.zOrder || 0);

this.color = color;
this.shapeType = null;
}

_getZ(frame) {
this.collectionZ[frame] = this.collectionZ[frame] || {
max: 0,
min: 0,
};

return this.collectionZ[frame];
}

save() {
throw window.cvat.exceptions.ScriptingError(
'Is not implemented',
);
}

get() {
throw window.cvat.exceptions.ScriptingError(
'Is not implemented',
);
}

toJSON() {
throw window.cvat.exceptions.ScriptingError(
'Is not implemented',
);
}

// Increase ZOrder within frame
up(frame, objectState) {
const z = this._getZ(frame);
z.max++;
objectState.zOrder = z.max;
}

// Decrease ZOrder within frame
down(frame, objectState) {
const z = this._getZ(frame);
z.min--;
objectState.zOrder = z.min;
}
}

class Shape extends Drawn {
constructor(data, clientID, color, injection) {
super(data, clientID, color, injection);
this.points = data.points;
this.occluded = data.occluded;
this.zOrder = data.z_order;
this.color = color;
this.shape = null;
}

// Method is used to export data to the server
toJSON() {
return {
type: this.shapeType,
clientID: this.clientID,
occluded: this.occluded,
z_order: this.zOrder,
Expand Down Expand Up @@ -133,9 +155,10 @@
}

return {
type: window.cvat.enums.ObjectType.SHAPE,
shape: this.shape,
objectType: window.cvat.enums.ObjectType.SHAPE,
shapeType: this.shapeType,
clientID: this.clientID,
serverID: this.serverID,
occluded: this.occluded,
lock: this.lock,
zOrder: this.zOrder,
Expand Down Expand Up @@ -232,34 +255,30 @@
}
}

class Track extends Annotation {
class Track extends Drawn {
constructor(data, clientID, color, injection) {
super(data, clientID, injection);
super(data, clientID, color, injection);
this.shapes = data.shapes.reduce((shapeAccumulator, value) => {
shapeAccumulator[value.frame] = {
serverID: value.id,
occluded: value.occluded,
zOrder: value.z_order,
points: value.points,
frame: value.frame,
outside: value.outside,
attributes: value.attributes.reduce((attributeAccumulator, attr) => {
attributeAccumulator[attr.spec_id] = attr.value;
return attributeAccumulator;
}, {}),
};

return shapeAccumulator;
}, {});
const z = this._getZ(value.frame);
z.max = Math.max(z.max, value.z_order);
z.min = Math.min(z.min, value.z_order);

this.attributes = data.attributes.reduce((attributeAccumulator, attr) => {
attributeAccumulator[attr.spec_id] = attr.value;
return attributeAccumulator;
return shapeAccumulator;
}, {});

this.cache = {};
this.color = color;
this.shape = null;
}

// Method is used to export data to the server
Expand All @@ -280,7 +299,7 @@
}, []),
shapes: Object.keys(this.shapes).reduce((shapesAccumulator, frame) => {
shapesAccumulator.push({
type: this.shape,
type: this.shapeType,
occluded: this.shapes[frame].occluded,
z_order: this.shapes[frame].zOrder,
points: [...this.shapes[frame].points],
Expand Down Expand Up @@ -312,9 +331,10 @@
attributes: this.getAttributes(frame),
label: this.label,
group: this.group,
type: window.cvat.enums.ObjectType.TRACK,
shape: this.shape,
objectType: window.cvat.enums.ObjectType.TRACK,
shapeType: this.shapeType,
clientID: this.clientID,
serverID: this.serverID,
lock: this.lock,
color: this.color,
},
Expand Down Expand Up @@ -630,8 +650,9 @@
}

return {
type: window.cvat.enums.ObjectType.TAG,
objectType: window.cvat.enums.ObjectType.TAG,
clientID: this.clientID,
serverID: this.serverID,
lock: this.lock,
attributes: Object.assign({}, this.attributes),
label: this.label,
Expand Down Expand Up @@ -697,7 +718,7 @@
class RectangleShape extends Shape {
constructor(data, clientID, color, injection) {
super(data, clientID, color, injection);
this.shape = window.cvat.enums.ObjectShape.RECTANGLE;
this.shapeType = window.cvat.enums.ObjectShape.RECTANGLE;
}
}

Expand All @@ -710,28 +731,28 @@
class PolygonShape extends PolyShape {
constructor(data, clientID, color, injection) {
super(data, clientID, color, injection);
this.shape = window.cvat.enums.ObjectShape.POLYGON;
this.shapeType = window.cvat.enums.ObjectShape.POLYGON;
}
}

class PolylineShape extends PolyShape {
constructor(data, clientID, color, injection) {
super(data, clientID, color, injection);
this.shape = window.cvat.enums.ObjectShape.POLYLINE;
this.shapeType = window.cvat.enums.ObjectShape.POLYLINE;
}
}

class PointsShape extends PolyShape {
constructor(data, clientID, color, injection) {
super(data, clientID, color, injection);
this.shape = window.cvat.enums.ObjectShape.POINTS;
this.shapeType = window.cvat.enums.ObjectShape.POINTS;
}
}

class RectangleTrack extends Track {
constructor(data, clientID, color, injection) {
super(data, clientID, color, injection);
this.shape = window.cvat.enums.ObjectShape.RECTANGLE;
this.shapeType = window.cvat.enums.ObjectShape.RECTANGLE;
}

interpolatePosition(leftPosition, rightPosition, targetFrame) {
Expand Down Expand Up @@ -1142,25 +1163,21 @@
class PolygonTrack extends PolyTrack {
constructor(data, clientID, color, injection) {
super(data, clientID, color, injection);
this.shape = window.cvat.enums.ObjectShape.POLYGON;
this.shapeType = window.cvat.enums.ObjectShape.POLYGON;
}
}

class PolylineTrack extends PolyTrack {
constructor(data, clientID, color, injection) {
super(data, clientID, color, injection);
this.shape = window.cvat.enums.ObjectShape.POLYLINE;
}

appendMapping() {
// TODO after checking how it works with polygons
this.shapeType = window.cvat.enums.ObjectShape.POLYLINE;
}
}

class PointsTrack extends PolyTrack {
constructor(data, clientID, color, injection) {
super(data, clientID, color, injection);
this.shape = window.cvat.enums.ObjectShape.POINTS;
this.shapeType = window.cvat.enums.ObjectShape.POINTS;
}
}

Expand All @@ -1173,6 +1190,8 @@
PolygonTrack,
PolylineTrack,
PointsTrack,
Track,
Shape,
Tag,
objectStateFactory,
};
Expand Down
9 changes: 6 additions & 3 deletions cvatjs/src/annotations-saver.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

class AnnotationsSaver {
constructor(version, collection, session) {
this.session = session.constructor.name.toLowerCase();
this.sessionType = session instanceof window.cvat.classes.Task ? 'task' : 'job';
this.id = session.id;
this.version = version;
this.collection = collection;
Expand Down Expand Up @@ -42,7 +42,7 @@

async _request(data, action) {
const result = await serverProxy.annotations.updateAnnotations(
this.session,
this.sessionType,
this.id,
data,
action,
Expand Down Expand Up @@ -249,14 +249,17 @@
delete this.initialObjects[object.id];
}
}

this.hash = this._getHash();
onUpdate('Saving is done');
} catch (error) {
onUpdate(`Can not save annotations: ${error.message}`);
throw error;
}
}

hasUnsavedChanges() {
return this._getHash() !== this._hash;
return this._getHash() !== this.hash;
}
}

Expand Down
Loading