Merge remote-tracking branch 'origin/release-0.3' into develop

main
Nikita Manovich 7 years ago
commit 641ad4bf57

@ -524,14 +524,15 @@ function uploadAnnotationRequest() {
$.ajax({ $.ajax({
url: '/get/task/' + window.cvat.dashboard.taskID, url: '/get/task/' + window.cvat.dashboard.taskID,
success: function(data) { success: function(data) {
let annotationParser = new AnnotationParser({ let annotationParser = new AnnotationParser(
{
start: 0, start: 0,
stop: data.size, stop: data.size,
image_meta_data: data.image_meta_data, image_meta_data: data.image_meta_data,
flipped: data.flipped flipped: data.flipped
}, },
new LabelsInfo(data.spec), new LabelsInfo(data.spec),
new ConstIdGenerator(-1), new ConstIdGenerator(-1)
); );
let asyncParse = function() { let asyncParse = function() {
@ -559,7 +560,7 @@ function uploadAnnotationRequest() {
overlay.remove(); overlay.remove();
}, },
}); });
} };
let asyncSaveChunk = function(start) { let asyncSaveChunk = function(start) {
const CHUNK_SIZE = 100000; const CHUNK_SIZE = 100000;

@ -472,6 +472,7 @@ class _Annotation:
group_id=box.group_id, group_id=box.group_id,
boxes=[box0, box1], boxes=[box0, box1],
attributes=box.attributes, attributes=box.attributes,
client_id=box.client_id,
) )
paths.append(path) paths.append(path)
@ -491,6 +492,7 @@ class _Annotation:
stop_frame=shape.frame + 1, stop_frame=shape.frame + 1,
group_id=shape.group_id, group_id=shape.group_id,
shapes=[shape0, shape1], shapes=[shape0, shape1],
client_id=shape.client_id,
attributes=shape.attributes, attributes=shape.attributes,
) )
paths.append(path) paths.append(path)
@ -2080,10 +2082,14 @@ class _AnnotationForTask(_Annotation):
im_w = im_meta_data['original_size'][0]['width'] im_w = im_meta_data['original_size'][0]['width']
im_h = im_meta_data['original_size'][0]['height'] im_h = im_meta_data['original_size'][0]['height']
counter = 0
for shape_type in ["boxes", "polygons", "polylines", "points"]: for shape_type in ["boxes", "polygons", "polylines", "points"]:
path_list = paths[shape_type] path_list = paths[shape_type]
for path in path_list: for path in path_list:
path_id = path.client_id if path.client_id != -1 else counter
counter += 1
dump_dict = OrderedDict([ dump_dict = OrderedDict([
("id", str(path_id)),
("label", path.label.name), ("label", path.label.name),
]) ])
if path.group_id: if path.group_id:

@ -798,9 +798,14 @@ class PlayerView {
this._playerUI.on('contextmenu.playerContextMenu', (e) => { this._playerUI.on('contextmenu.playerContextMenu', (e) => {
if (!window.cvat.mode) { if (!window.cvat.mode) {
$('.custom-menu').hide(100); $('.custom-menu').hide(100);
this._contextMenuUI.finish().show(100).offset({ this._contextMenuUI.finish().show(100);
top: e.pageY - 10, let x = Math.min(e.pageX, this._playerUI[0].offsetWidth -
left: e.pageX - 10, this._contextMenuUI[0].scrollWidth);
let y = Math.min(e.pageY, this._playerUI[0].offsetHeight -
this._contextMenuUI[0].scrollHeight);
this._contextMenuUI.offset({
left: x,
top: y,
}); });
e.preventDefault(); e.preventDefault();
} }

@ -50,7 +50,7 @@ class ShapeBufferModel extends Listener {
} }
} }
_makeObject(box, points, trackedObj) { _makeObject(box, points, isTracked) {
if (!this._shape.type) { if (!this._shape.type) {
return null; return null;
} }
@ -75,7 +75,7 @@ class ShapeBufferModel extends Listener {
box.frame = window.cvat.player.frames.current; box.frame = window.cvat.player.frames.current;
box.z_order = this._collection.zOrder(box.frame).max; box.z_order = this._collection.zOrder(box.frame).max;
if (trackedObj) { if (isTracked) {
object.shapes = []; object.shapes = [];
object.shapes.push(Object.assign(box, { object.shapes.push(Object.assign(box, {
outside: false, outside: false,
@ -180,18 +180,49 @@ class ShapeBufferModel extends Listener {
let startFrame = window.cvat.player.frames.start; let startFrame = window.cvat.player.frames.start;
let originalImageSize = imageSizes[object.frame - startFrame] || imageSizes[0]; let originalImageSize = imageSizes[object.frame - startFrame] || imageSizes[0];
// Getting normalized coordinates [0..1]
let normalized = {};
if (this._shape.type === 'box') {
normalized.xtl = object.xtl / originalImageSize.width;
normalized.ytl = object.ytl / originalImageSize.height;
normalized.xbr = object.xbr / originalImageSize.width;
normalized.ybr = object.ybr / originalImageSize.height;
}
else {
normalized.points = [];
for (let point of PolyShapeModel.convertStringToNumberArray(object.points)) {
normalized.points.push({
x: point.x / originalImageSize.width,
y: point.y / originalImageSize.height,
});
}
}
let addedObjects = []; let addedObjects = [];
while (numOfFrames > 0 && (object.frame + 1 <= window.cvat.player.frames.stop)) { while (numOfFrames > 0 && (object.frame + 1 <= window.cvat.player.frames.stop)) {
object.frame ++; object.frame ++;
numOfFrames --; numOfFrames --;
// Propagate only for frames with same size object.z_order = this._collection.zOrder(object.frame).max;
let imageSize = imageSizes[object.frame - startFrame] || imageSizes[0]; let imageSize = imageSizes[object.frame - startFrame] || imageSizes[0];
if ((imageSize.width != originalImageSize.width) || (imageSize.height != originalImageSize.height)) { let position = {};
continue; if (this._shape.type === 'box') {
position.xtl = normalized.xtl * imageSize.width;
position.ytl = normalized.ytl * imageSize.height;
position.xbr = normalized.xbr * imageSize.width;
position.ybr = normalized.ybr * imageSize.height;
} }
else {
object.z_order = this._collection.zOrder(object.frame).max; position.points = [];
for (let point of normalized.points) {
position.points.push({
x: point.x * imageSize.width,
y: point.y * imageSize.height,
});
}
position.points = PolyShapeModel.convertNumberArrayToString(position.points);
}
Object.assign(object, position);
this._collection.add(object, `annotation_${this._shape.type}`); this._collection.add(object, `annotation_${this._shape.type}`);
addedObjects.push(this._collection.shapes.slice(-1)[0]); addedObjects.push(this._collection.shapes.slice(-1)[0]);
} }
@ -251,8 +282,24 @@ class ShapeBufferController {
let propagateHandler = Logger.shortkeyLogDecorator(function() { let propagateHandler = Logger.shortkeyLogDecorator(function() {
if (!propagateDialogShowed) { if (!propagateDialogShowed) {
if (this._model.copyToBuffer()) { if (this._model.copyToBuffer()) {
let curFrame = window.cvat.player.frames.current;
let startFrame = window.cvat.player.frames.start;
let endFrame = Math.min(window.cvat.player.frames.stop, curFrame + this._model.propagateFrames);
let imageSizes = window.cvat.job.images.original_size;
let message = `Propagate up to ${endFrame} frame. `;
let refSize = imageSizes[curFrame - startFrame] || imageSizes[0];
for (let _frame = curFrame + 1; _frame <= endFrame; _frame ++) {
let size = imageSizes[_frame - startFrame] || imageSizes[0];
if ((size.width != refSize.width) || (size.height != refSize.height) ) {
message += 'Some covered frames have another resolution. Shapes in them can differ from reference. ';
break;
}
}
message += 'Are you sure?';
propagateDialogShowed = true; propagateDialogShowed = true;
confirm(`Propagate to ${this._model.propagateFrames} frames. Are you sure?`, () => { confirm(message, () => {
this._model.propagateToFrames(); this._model.propagateToFrames();
propagateDialogShowed = false; propagateDialogShowed = false;
}, () => propagateDialogShowed = false); }, () => propagateDialogShowed = false);
@ -402,7 +449,7 @@ class ShapeBufferView {
let area = w * h; let area = w * h;
let type = this._shape.type; let type = this._shape.type;
if (area > AREA_TRESHOLD || type === 'points' || type === 'polyline' && (w >= AREA_TRESHOLD || h >= AREA_TRESHOLD)) { if (area >= AREA_TRESHOLD || type === 'points' || type === 'polyline' && (w >= AREA_TRESHOLD || h >= AREA_TRESHOLD)) {
this._controller.pasteToFrame(e, null, actualPoints); this._controller.pasteToFrame(e, null, actualPoints);
} }
else { else {

@ -1423,6 +1423,7 @@ class ShapeView extends Listener {
this._pointContextMenu = $('#pointContextMenu'); this._pointContextMenu = $('#pointContextMenu');
this._rightBorderFrame = $('#playerFrame')[0].offsetWidth; this._rightBorderFrame = $('#playerFrame')[0].offsetWidth;
this._bottomBorderFrame = $('#playerFrame')[0].offsetHeight;
shapeModel.subscribe(this); shapeModel.subscribe(this);
} }
@ -1541,9 +1542,12 @@ class ShapeView extends Listener {
dragPolyItem.addClass('hidden'); dragPolyItem.addClass('hidden');
} }
this._shapeContextMenu.finish().show(100).offset({ this._shapeContextMenu.finish().show(100);
top: e.pageY - 10, let x = Math.min(e.pageX, this._rightBorderFrame - this._shapeContextMenu[0].scrollWidth);
left: e.pageX - 10, let y = Math.min(e.pageY, this._bottomBorderFrame - this._shapeContextMenu[0].scrollHeight);
this._shapeContextMenu.offset({
left: x,
top: y,
}); });
e.preventDefault(); e.preventDefault();
@ -2437,7 +2441,7 @@ class ShapeView extends Listener {
if (this._uis.text && this._uis.text.node.parentElement) { if (this._uis.text && this._uis.text.node.parentElement) {
let revscale = 1 / scale; let revscale = 1 / scale;
let shapeBBox = this._uis.shape.node.getBBox(); let shapeBBox = this._uis.shape.node.getBBox();
let textBBox = this._uis.text.node.getBBox() let textBBox = this._uis.text.node.getBBox();
let x = shapeBBox.x + shapeBBox.width + TEXT_MARGIN * revscale; let x = shapeBBox.x + shapeBBox.width + TEXT_MARGIN * revscale;
let y = shapeBBox.y; let y = shapeBBox.y;
@ -2826,9 +2830,12 @@ class PolyShapeView extends ShapeView {
this._pointContextMenu.attr('point_idx', point.index()); this._pointContextMenu.attr('point_idx', point.index());
this._pointContextMenu.attr('dom_point_id', point.attr('id')); this._pointContextMenu.attr('dom_point_id', point.attr('id'));
this._pointContextMenu.finish().show(100).offset({ this._pointContextMenu.finish().show(100);
top: e.pageY - 20, let x = Math.min(e.pageX, this._rightBorderFrame - this._pointContextMenu[0].scrollWidth);
left: e.pageX - 20, let y = Math.min(e.pageY, this._bottomBorderFrame - this._pointContextMenu[0].scrollHeight);
this._pointContextMenu.offset({
left: x,
top: y,
}); });
e.preventDefault(); e.preventDefault();
@ -3037,14 +3044,15 @@ class PointsView extends PolyShapeView {
return; return;
} }
this._uis.points = this._scenes.svg.group().fill(this._appearance.fill || this._appearance.colors.shape) this._uis.points = this._scenes.svg.group()
.fill(this._appearance.fill || this._appearance.colors.shape)
.on('click', () => { .on('click', () => {
this._positionateMenus(); this._positionateMenus();
this._controller.click(); this._controller.click();
}).attr({
'z_order': position.z_order
}).addClass('pointTempGroup'); }).addClass('pointTempGroup');
this._uis.points.node.setAttribute('z_order', position.z_order);
let points = PolyShapeModel.convertStringToNumberArray(position.points); let points = PolyShapeModel.convertStringToNumberArray(position.points);
for (let point of points) { for (let point of points) {
let radius = POINT_RADIUS * 2 / window.cvat.player.geometry.scale; let radius = POINT_RADIUS * 2 / window.cvat.player.geometry.scale;
@ -3079,7 +3087,7 @@ class PointsView extends PolyShapeView {
let interpolation = this._controller.interpolate(window.cvat.player.frames.current); let interpolation = this._controller.interpolate(window.cvat.player.frames.current);
if (interpolation.position.points) { if (interpolation.position.points) {
let points = window.cvat.translate.points.actualToCanvas(interpolation.position.points); let points = window.cvat.translate.points.actualToCanvas(interpolation.position.points);
this._drawPointMarkers(Object.assign(interpolation.position.points, {points: points})); this._drawPointMarkers(Object.assign(interpolation.position, {points: points}));
} }
} }
} }

@ -26,6 +26,7 @@ from django.db import transaction
from ffmpy import FFmpeg from ffmpy import FFmpeg
from pyunpack import Archive from pyunpack import Archive
from distutils.dir_util import copy_tree from distutils.dir_util import copy_tree
from collections import OrderedDict
from . import models from . import models
from .log import slogger from .log import slogger
@ -154,7 +155,7 @@ def get(tid):
"""Get the task as dictionary of attributes""" """Get the task as dictionary of attributes"""
db_task = models.Task.objects.get(pk=tid) db_task = models.Task.objects.get(pk=tid)
if db_task: if db_task:
db_labels = db_task.label_set.prefetch_related('attributespec_set').all() db_labels = db_task.label_set.prefetch_related('attributespec_set').order_by('-pk').all()
im_meta_data = get_image_meta_cache(db_task) im_meta_data = get_image_meta_cache(db_task)
attributes = {} attributes = {}
for db_label in db_labels: for db_label in db_labels:
@ -174,7 +175,7 @@ def get(tid):
response = { response = {
"status": db_task.status, "status": db_task.status,
"spec": { "spec": {
"labels": { db_label.id:db_label.name for db_label in db_labels }, "labels": OrderedDict((db_label.id, db_label.name) for db_label in db_labels),
"attributes": attributes "attributes": attributes
}, },
"size": db_task.size, "size": db_task.size,
@ -228,7 +229,7 @@ def get_job(jid):
if db_task.mode == 'annotation': if db_task.mode == 'annotation':
im_meta_data['original_size'] = im_meta_data['original_size'][db_segment.start_frame:db_segment.stop_frame + 1] im_meta_data['original_size'] = im_meta_data['original_size'][db_segment.start_frame:db_segment.stop_frame + 1]
db_labels = db_task.label_set.prefetch_related('attributespec_set').all() db_labels = db_task.label_set.prefetch_related('attributespec_set').order_by('-pk').all()
attributes = {} attributes = {}
for db_label in db_labels: for db_label in db_labels:
attributes[db_label.id] = {} attributes[db_label.id] = {}
@ -237,7 +238,7 @@ def get_job(jid):
response = { response = {
"status": db_job.status, "status": db_job.status,
"labels": { db_label.id:db_label.name for db_label in db_labels }, "labels": OrderedDict((db_label.id, db_label.name) for db_label in db_labels),
"stop": db_segment.stop_frame, "stop": db_segment.stop_frame,
"taskid": db_task.id, "taskid": db_task.id,
"slug": db_task.name, "slug": db_task.name,
@ -375,7 +376,7 @@ def _get_frame_path(frame, base_dir):
return path return path
def _parse_labels(labels): def _parse_labels(labels):
parsed_labels = {} parsed_labels = OrderedDict()
last_label = "" last_label = ""
for token in shlex.split(labels): for token in shlex.split(labels):

@ -52,6 +52,8 @@ module.exports = {
'createExportContainer': true, 'createExportContainer': true,
'ExportType': true, 'ExportType': true,
'getExportTargetContainer': true, 'getExportTargetContainer': true,
'IncrementIdGenerator': true,
'ConstIdGenerator': true,
// from shapeCollection.js // from shapeCollection.js
'ShapeCollectionModel': true, 'ShapeCollectionModel': true,
'ShapeCollectionController': true, 'ShapeCollectionController': true,

Loading…
Cancel
Save