Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into restapi
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikita Manovich committed Feb 12, 2019
2 parents 4b59dec + df10fe1 commit 70d4de3
Show file tree
Hide file tree
Showing 24 changed files with 707 additions and 27 deletions.
16 changes: 16 additions & 0 deletions .remarkrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
exports.settings = {bullet: '*', paddedTable: false}

exports.plugins = [
require('remark-preset-lint-recommended'),
require('remark-preset-lint-consistent'),
require('remark-validate-links'),
[require("remark-lint-no-dead-urls"), { skipOffline: true }],
[require("remark-lint-maximum-line-length"), 120],
[require("remark-lint-maximum-heading-length"), 120],
[require("remark-lint-list-item-indent"), "tab-size"],
[require("remark-lint-list-item-spacing"), false],
[require("remark-lint-strong-marker"), "*"],
[require("remark-lint-emphasis-marker"), "_"],
[require("remark-lint-unordered-list-marker-style"), "-"],
[require("remark-lint-ordered-list-marker-style"), "."],
]
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- OpenVINO auto annotation: it is possible to upload a custom model and annotate images automatically.
- Ability to rotate images/video in the client part (Ctrl+R, Shift+Ctrl+R shortcuts) (#305)
- The ReID application for automatic bounding box merging has been added (#299)
- Keyboard shortcuts to switch next/previous default shape type (box, polygon etc) [Alt + <, Alt + >] (#316)


### Changed
- Propagation setup has been moved from settings to bottom player panel
- Additional events like "Debug Info" or "Fit Image" have been added for analitics
- Optional using LFS for git annotation storages (#314)

### Deprecated
-
- "Flip images" flag in the create task dialog will be removed. Rotation functionality in client part have been added instead.

### Removed
-

### Fixed
- Django 2.1.5 (security fix, https://nvd.nist.gov/vuln/detail/CVE-2019-3498)
- Several scenarious which cause code 400 after undo/redo/save have been fixed (#315)

### Security
-
Expand Down
15 changes: 11 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,11 @@ RUN if [ "$WITH_TESTS" = "yes" ]; then \
COPY cvat/requirements/ /tmp/requirements/
COPY supervisord.conf mod_wsgi.conf wait-for-it.sh manage.py ${HOME}/
RUN pip3 install --no-cache-dir -r /tmp/requirements/${DJANGO_CONFIGURATION}.txt
COPY cvat/ ${HOME}/cvat

COPY ssh ${HOME}/.ssh

# Install git application dependencies
RUN apt-get update && \
apt-get install -y ssh netcat-openbsd git curl zip && \
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash && \
wget -qO /dev/stdout https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash && \
apt-get install -y git-lfs && \
git lfs install && \
rm -rf /var/lib/apt/lists/* && \
Expand All @@ -120,6 +117,16 @@ RUN apt-get update && \
echo export "GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o ConnectTimeout=30 -o ProxyCommand='nc -X 5 -x ${socks_proxy} %h %p'\"" >> ${HOME}/.bashrc; \
fi

# Download model for re-identification app
ENV REID_MODEL_DIR=${HOME}/reid
RUN if [ "$OPENVINO_TOOLKIT" = "yes" ]; then \
mkdir ${HOME}/reid && \
wget https://download.01.org/openvinotoolkit/2018_R5/open_model_zoo/person-reidentification-retail-0079/FP32/person-reidentification-retail-0079.xml -O reid/reid.xml && \
wget https://download.01.org/openvinotoolkit/2018_R5/open_model_zoo/person-reidentification-retail-0079/FP32/person-reidentification-retail-0079.bin -O reid/reid.bin; \
fi

COPY ssh ${HOME}/.ssh
COPY cvat/ ${HOME}/cvat
COPY tests ${HOME}/tests
RUN patch -p1 < ${HOME}/cvat/apps/engine/static/engine/js/3rdparty.patch
RUN chown -R ${USER}:${USER} .
Expand Down
11 changes: 8 additions & 3 deletions cvat/apps/engine/static/engine/js/annotationUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,12 @@ function buildAnnotationUI(job, shapeData, loadJobEvent) {
window.cvat.data = {
get: () => shapeCollectionModel.exportAll(),
set: (data) => {
shapeCollectionModel.empty();
for (let type in data) {
for (let shape of data[type]) {
shape.id = idGenerator.next();
}
}

shapeCollectionModel.import(data, false);
shapeCollectionModel.update();
},
Expand Down Expand Up @@ -246,7 +251,7 @@ function buildAnnotationUI(job, shapeData, loadJobEvent) {
}), job);
new PlayerView(playerModel, playerController, job);

let historyModel = new HistoryModel(playerModel);
let historyModel = new HistoryModel(playerModel, idGenerator);
let historyController = new HistoryController(historyModel);
new HistoryView(historyController, historyModel);

Expand Down Expand Up @@ -275,7 +280,7 @@ function buildAnnotationUI(job, shapeData, loadJobEvent) {

$(window).on('click', function(event) {
Logger.updateUserActivityTimer();
if (event.target.classList.contains('modal')) {
if (event.target.classList.contains('modal') && !event.target.classList.contains('force-modal')) {
event.target.classList.add('hidden');
}
});
Expand Down
11 changes: 8 additions & 3 deletions cvat/apps/engine/static/engine/js/history.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"use strict";

class HistoryModel extends Listener {
constructor(playerModel) {
constructor(playerModel, idGenerator) {
super('onHistoryUpdate', () => this );

this._deep = 128;
Expand All @@ -23,10 +23,15 @@ class HistoryModel extends Listener {
this._redo_stack = [];
this._locked = false;
this._player = playerModel;
this._idGenerator = idGenerator;

window.cvat.addAction = (name, undo, redo, frame) => this.addAction(name, undo, redo, frame);
}

generateId() {
return this._idGenerator.next();
}

undo() {
let frame = window.cvat.player.frames.current;
let undo = this._undo_stack.pop();
Expand All @@ -42,7 +47,7 @@ class HistoryModel extends Listener {
this._player.shift(undo.frame, true);
}
this._locked = true;
undo.undo();
undo.undo(this);
}
catch(err) {
this.notify();
Expand Down Expand Up @@ -73,7 +78,7 @@ class HistoryModel extends Listener {
this._player.shift(redo.frame, true);
}
this._locked = true;
redo.redo();
redo.redo(this);
}
catch(err) {
this.notify();
Expand Down
6 changes: 4 additions & 2 deletions cvat/apps/engine/static/engine/js/shapeBuffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,9 @@ class ShapeBufferModel extends Listener {
window.cvat.addAction('Paste Object', () => {
model.removed = true;
model.unsubscribe(this._collection);
}, () => {
}, (self) => {
model.subscribe(this._collection);
model.id = self.generateId();
model.removed = false;
}, window.cvat.player.frames.current);
// End of undo/redo code
Expand Down Expand Up @@ -247,8 +248,9 @@ class ShapeBufferModel extends Listener {
object.removed = true;
object.unsubscribe(this._collection);
}
}, () => {
}, (self) => {
for (let object of addedObjects) {
object.id = self.generateId();
object.removed = false;
object.subscribe(this._collection);
}
Expand Down
33 changes: 31 additions & 2 deletions cvat/apps/engine/static/engine/js/shapeCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -814,14 +814,16 @@ class ShapeCollectionModel extends Listener {
// Undo/redo code
let newShapes = this._shapes.slice(-list.length);
let originalShape = this._activeShape;
window.cvat.addAction('Split Object', () => {
window.cvat.addAction('Split Object', (self) => {
for (let shape of newShapes) {
shape.removed = true;
shape.unsubscribe(this);
}
originalShape.id = self.generateId();
originalShape.removed = false;
}, () => {
}, (self) => {
for (let shape of newShapes) {
shape.id = self.generateId();
shape.removed = false;
shape.subscribe(this);
}
Expand Down Expand Up @@ -963,6 +965,30 @@ class ShapeCollectionController {
}
}.bind(this));

let nextShapeType = Logger.shortkeyLogDecorator(function(e) {
if (window.cvat.mode === null) {
let next = $('#shapeTypeSelector option:selected').next();
if (!next.length) {
next = $('#shapeTypeSelector option').first();
}

next.prop('selected', true);
next.trigger('change');
}
}.bind(this));

let prevShapeType = Logger.shortkeyLogDecorator(function(e) {
if (window.cvat.mode === null) {
let prev = $('#shapeTypeSelector option:selected').prev();
if (!prev.length) {
prev = $('#shapeTypeSelector option').last();
}

prev.prop('selected', true);
prev.trigger('change');
}
}.bind(this));

let shortkeys = window.cvat.config.shortkeys;
Mousetrap.bind(shortkeys["switch_lock_property"].value, switchLockHandler.bind(this), 'keydown');
Mousetrap.bind(shortkeys["switch_all_lock_property"].value, switchAllLockHandler.bind(this), 'keydown');
Expand All @@ -975,6 +1001,9 @@ class ShapeCollectionController {
Mousetrap.bind(shortkeys["change_shape_label"].value, switchLabelHandler.bind(this), 'keydown');
Mousetrap.bind(shortkeys["delete_shape"].value, removeActiveHandler.bind(this), 'keydown');
Mousetrap.bind(shortkeys["change_shape_color"].value, changeShapeColorHandler.bind(this), 'keydown');
Mousetrap.bind(shortkeys['next_shape_type'].value, nextShapeType.bind(this), 'keydown');
Mousetrap.bind(shortkeys['prev_shape_type'].value, prevShapeType.bind(this), 'keydown');


if (window.cvat.job.z_order) {
Mousetrap.bind(shortkeys["inc_z"].value, incZHandler.bind(this), 'keydown');
Expand Down
3 changes: 2 additions & 1 deletion cvat/apps/engine/static/engine/js/shapeCreator.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ class ShapeCreatorModel extends Listener {
window.cvat.addAction('Draw Object', () => {
model.removed = true;
model.unsubscribe(this._shapeCollection);
}, () => {
}, (self) => {
model.subscribe(this._shapeCollection);
model.id = self.generateId();
model.removed = false;
}, window.cvat.player.frames.current);
// End of undo/redo code
Expand Down
6 changes: 4 additions & 2 deletions cvat/apps/engine/static/engine/js/shapeMerger.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,20 +167,22 @@ class ShapeMergerModel extends Listener {
let shapes = this._shapesForMerge;

// Undo/redo code
window.cvat.addAction('Merge Objects', () => {
window.cvat.addAction('Merge Objects', (self) => {
model.unsubscribe(this._collectionModel);
model.removed = true;
for (let shape of shapes) {
shape.id = self.generateId();
shape.removed = false;
shape.subscribe(this._collectionModel);
}
this._collectionModel.update();
}, () => {
}, (self) => {
for (let shape of shapes) {
shape.removed = true;
shape.unsubscribe(this._collectionModel);
}
model.subscribe(this._collectionModel);
model.id = self.generateId();
model.removed = false;
}, window.cvat.player.frames.current);
// End of undo/redo code
Expand Down
8 changes: 6 additions & 2 deletions cvat/apps/engine/static/engine/js/shapes.js
Original file line number Diff line number Diff line change
Expand Up @@ -476,11 +476,11 @@ class ShapeModel extends Listener {
this.removed = true;

// Undo/redo code
window.cvat.addAction('Remove Object', () => {
window.cvat.addAction('Remove Object', (self) => {
this.id = self.generateId();
this.removed = false;
}, () => {
this.removed = true;

}, window.cvat.player.frames.current);
// End of undo/redo code
}
Expand Down Expand Up @@ -574,6 +574,10 @@ class ShapeModel extends Listener {
return this._id;
}

set id(value) {
this._id = value;
}

get frame() {
return this._frame;
}
Expand Down
12 changes: 12 additions & 0 deletions cvat/apps/engine/static/engine/js/userConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,18 @@ class Config {
view_value: 'Ctrl + Shift + R',
description: 'counter clockwise image rotation'
},

next_shape_type: {
value: ['alt+.'],
view_value: 'Alt + >',
description: 'switch next default shape type'
},

prev_shape_type: {
value: ['alt+,'],
view_value: 'Alt + <',
description: 'switch previous default shape type'
},
};

if (window.cvat && window.cvat.job && window.cvat.job.z_order) {
Expand Down
32 changes: 25 additions & 7 deletions cvat/apps/git/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class Git:
__diffs_dir = None
__annotation_file = None
__sync_date = None
__lfs = None

def __init__(self, db_git, tid, user):
self.__db_git = db_git
Expand All @@ -66,6 +67,7 @@ def __init__(self, db_git, tid, user):
self.__branch_name = 'cvat_{}_{}'.format(tid, self.__task_name)
self.__annotation_file = os.path.join(self.__cwd, self.__path)
self.__sync_date = db_git.sync_date
self.__lfs = db_git.lfs


# Method parses an got URL.
Expand Down Expand Up @@ -256,6 +258,28 @@ def _accumulate(source, target, target_key):
if os.path.exists(self.__annotation_file):
os.remove(self.__annotation_file)

# Initialize LFS if need
if self.__lfs:
updated = False
lfs_settings = ["*.xml\tfilter=lfs diff=lfs merge=lfs -text\n", "*.zip\tfilter=lfs diff=lfs merge=lfs -text\n"]
if not os.path.isfile(os.path.join(self.__cwd, ".gitattributes")):
with open(os.path.join(self.__cwd, ".gitattributes"), "w") as gitattributes:
gitattributes.writelines(lfs_settings)
updated = True
else:
with open(os.path.join(self.__cwd, ".gitattributes"), "r+") as gitattributes:
lines = gitattributes.readlines()
for setting in lfs_settings:
if setting not in lines:
updated = True
lines.append(setting)
gitattributes.seek(0)
gitattributes.writelines(lines)
gitattributes.truncate()

if updated:
self.__rep.git.add(['.gitattributes'])

# Dump an annotation
dump(self.__tid, format, scheme, host, OrderedDict())
dump_name = Task.objects.get(pk = self.__tid).get_dump_path()
Expand All @@ -268,8 +292,6 @@ def _accumulate(source, target, target_key):
else:
raise Exception("Got unknown annotation file type")

# Setup LFS for *.zip files
self.__rep.git.lfs("track", self.__path)
self.__rep.git.add(self.__annotation_file)

# Merge diffs
Expand All @@ -279,12 +301,7 @@ def _accumulate(source, target, target_key):
diff = json.loads(f.read())
_accumulate(diff, summary_diff, None)

# Commit and push
self.__rep.index.add([
'.gitattributes',
])
self.__rep.index.commit("CVAT Annotation updated by {}. Summary: {}".format(self.__user["name"], str(summary_diff)))

self.__rep.git.push("origin", self.__branch_name, "--force")

shutil.rmtree(self.__diffs_dir, True)
Expand Down Expand Up @@ -344,6 +361,7 @@ def _initial_create(tid, params):
db_git.url = git_path
db_git.path = path
db_git.task = db_task
db_git.lfs = params["use_lfs"].lower() == "true"

try:
_git = Git(db_git, tid, user)
Expand Down
Loading

0 comments on commit 70d4de3

Please sign in to comment.