Add extreme clicking feature to draw box by 4 points (#1111)

* Add extreme clicking feature to draw box by 4 points

* Add documentation for extreme clicking
main
Jijoong Kim 6 years ago committed by GitHub
parent e062c2309e
commit 7f8b96d4e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -54,7 +54,8 @@ window.addEventListener('DOMContentLoaded', () => {
Object.defineProperty(instance, 'defaultType', { Object.defineProperty(instance, 'defaultType', {
get: () => instance._defaultType, get: () => instance._defaultType,
set: (type) => { set: (type) => {
if (!['box', 'points', 'polygon', 'polyline', 'auto_segmentation'].includes(type)) { if (!['box', 'box_by_4_points', 'points', 'polygon',
'polyline', 'auto_segmentation'].includes(type)) {
throw Error(`Unknown shape type found ${type}`); throw Error(`Unknown shape type found ${type}`);
} }
instance._defaultType = type; instance._defaultType = type;

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

@ -25,6 +25,7 @@
- [Annotation mode (advanced)](#annotation-mode-advanced) - [Annotation mode (advanced)](#annotation-mode-advanced)
- [Interpolation mode (advanced)](#interpolation-mode-advanced) - [Interpolation mode (advanced)](#interpolation-mode-advanced)
- [Attribute annotation mode (advanced)](#attribute-annotation-mode-advanced) - [Attribute annotation mode (advanced)](#attribute-annotation-mode-advanced)
- [Annotation with box by 4 points](#annotation-with-box-by-4-points)
- [Annotation with polygons](#annotation-with-polygons) - [Annotation with polygons](#annotation-with-polygons)
- [Annotation with polylines](#annotation-with-polylines) - [Annotation with polylines](#annotation-with-polylines)
- [Annotation with points](#annotation-with-points) - [Annotation with points](#annotation-with-points)
@ -934,6 +935,20 @@ To navigate between objects (pedestrians in the case), use the following shortcu
By default, objects in the mode are zoomed. Check By default, objects in the mode are zoomed. Check
``Open Menu`` —> ``Settings`` —> ``AAM Zoom Margin`` to adjust that. ``Open Menu`` —> ``Settings`` —> ``AAM Zoom Margin`` to adjust that.
## Annotation with box by 4 points
It is an efficient method of bounding box annotation, proposed
[here](https://arxiv.org/pdf/1708.02750.pdf).
Before starting, you need to be sure that ``Box by 4 points`` is selected.
![](static/documentation/images/image134.jpg)
Press ``N`` for entering drawing mode. Click exactly four extreme points:
the top, bottom, left- and right-most physical points on the object.
Drawing is automatically completed right after clicking the fourth point.
Press ``Esc`` to cancel editing.
![](static/documentation/images/gif016.gif)
## Annotation with polygons ## Annotation with polygons
It is used for semantic / instance segmentation. It is used for semantic / instance segmentation.

@ -54,7 +54,8 @@ class ShapeCreatorModel extends Listener {
} }
// FIXME: In the future we have to make some generic solution // FIXME: In the future we have to make some generic solution
if (this._defaultMode === 'interpolation' && ['box', 'points'].includes(this._defaultType)) { if (this._defaultMode === 'interpolation'
&& ['box', 'points', 'box_by_4_points'].includes(this._defaultType)) {
data.shapes = []; data.shapes = [];
data.shapes.push(Object.assign({}, result, data)); data.shapes.push(Object.assign({}, result, data));
this._shapeCollection.add(data, `interpolation_${this._defaultType}`); this._shapeCollection.add(data, `interpolation_${this._defaultType}`);
@ -125,7 +126,7 @@ class ShapeCreatorModel extends Listener {
} }
set defaultType(type) { set defaultType(type) {
if (!['box', 'points', 'polygon', 'polyline'].includes(type)) { if (!['box', 'box_by_4_points', 'points', 'polygon', 'polyline'].includes(type)) {
throw Error(`Unknown shape type found ${type}`); throw Error(`Unknown shape type found ${type}`);
} }
this._defaultType = type; this._defaultType = type;
@ -234,8 +235,8 @@ class ShapeCreatorView {
// FIXME: In the future we have to make some generic solution // FIXME: In the future we have to make some generic solution
const mode = this._modeSelector.prop('value'); const mode = this._modeSelector.prop('value');
const type = $(e.target).prop('value'); const type = $(e.target).prop('value');
if (type !== 'box' && !(type === 'points' && this._polyShapeSize === 1) if (type !== 'box' && type !== 'box_by_4_points'
&& mode !== 'annotation') { && !(type === 'points' && this._polyShapeSize === 1) && mode !== 'annotation') {
this._modeSelector.prop('value', 'annotation'); this._modeSelector.prop('value', 'annotation');
this._controller.setDefaultShapeMode('annotation'); this._controller.setDefaultShapeMode('annotation');
showMessage('Only the annotation mode allowed for the shape'); showMessage('Only the annotation mode allowed for the shape');
@ -252,7 +253,7 @@ class ShapeCreatorView {
const mode = $(e.target).prop('value'); const mode = $(e.target).prop('value');
const type = this._typeSelector.prop('value'); const type = this._typeSelector.prop('value');
if (mode !== 'annotation' && !(type === 'points' && this._polyShapeSize === 1) if (mode !== 'annotation' && !(type === 'points' && this._polyShapeSize === 1)
&& type !== 'box') { && type !== 'box' && type !== 'box_by_4_points') {
this._typeSelector.prop('value', 'box'); this._typeSelector.prop('value', 'box');
this._controller.setDefaultShapeType('box'); this._controller.setDefaultShapeType('box');
showMessage('Only boxes and single point allowed in the interpolation mode'); showMessage('Only boxes and single point allowed in the interpolation mode');
@ -492,7 +493,7 @@ class ShapeCreatorView {
ytl, ytl,
xbr, xbr,
ybr, ybr,
} };
if (this._mode === 'interpolation') { if (this._mode === 'interpolation') {
box.outside = false; box.outside = false;
@ -511,6 +512,67 @@ class ShapeCreatorView {
} }
}); });
break; break;
case 'box_by_4_points':
let numberOfPoints = 0;
this._drawInstance = this._frameContent.polyline().draw({ snapToGrid: 0.1 })
.addClass('shapeCreation').attr({
'stroke-width': 0,
}).on('drawstart', () => {
// init numberOfPoints as one on drawstart
numberOfPoints = 1;
}).on('drawpoint', (e) => {
// increase numberOfPoints by one on drawpoint
numberOfPoints += 1;
// finish if numberOfPoints are exactly four
if (numberOfPoints === 4) {
let actualPoints = window.cvat.translate.points.canvasToActual(e.target.getAttribute('points'));
actualPoints = PolyShapeModel.convertStringToNumberArray(actualPoints);
const { frameWidth, frameHeight } = window.cvat.player.geometry;
// init bounding box
const box = {
'xtl': frameWidth,
'ytl': frameHeight,
'xbr': 0,
'ybr': 0
};
for (const point of actualPoints) {
// clamp point
point.x = Math.clamp(point.x, 0, frameWidth);
point.y = Math.clamp(point.y, 0, frameHeight);
// update bounding box
box.xtl = Math.min(point.x, box.xtl);
box.ytl = Math.min(point.y, box.ytl);
box.xbr = Math.max(point.x, box.xbr);
box.ybr = Math.max(point.y, box.ybr);
}
if ((box.ybr - box.ytl) * (box.xbr - box.xtl) >= AREA_TRESHOLD) {
if (this._mode === 'interpolation') {
box.outside = false;
}
// finish drawing
this._controller.finish(box, this._type);
}
this._controller.switchCreateMode(true);
}
}).on('undopoint', () => {
if (numberOfPoints > 0) {
numberOfPoints -= 1;
}
}).off('drawdone').on('drawdone', () => {
if (numberOfPoints !== 4) {
showMessage('Click exactly four extreme points for an object');
this._controller.switchCreateMode(true);
} else {
throw Error('numberOfPoints is exactly four, but box drawing did not finish.');
}
});
this._createPolyEvents();
break;
case 'points': case 'points':
this._drawInstance = this._frameContent.polyline().draw({ snapToGrid: 0.1 }) this._drawInstance = this._frameContent.polyline().draw({ snapToGrid: 0.1 })
.addClass('shapeCreation').attr({ .addClass('shapeCreation').attr({

@ -3313,6 +3313,10 @@ function buildShapeModel(data, type, clientID, color) {
switch (type) { switch (type) {
case 'interpolation_box': case 'interpolation_box':
case 'annotation_box': case 'annotation_box':
case 'interpolation_box_by_4_points':
case 'annotation_box_by_4_points':
// convert type into 'box' if 'box_by_4_points'
type = type.replace('_by_4_points', '');
return new BoxModel(data, type, clientID, color); return new BoxModel(data, type, clientID, color);
case 'interpolation_points': case 'interpolation_points':
case 'annotation_points': case 'annotation_points':

@ -437,6 +437,7 @@
</select> </select>
<select id="shapeTypeSelector" class="regular h2"> <select id="shapeTypeSelector" class="regular h2">
<option value="box" class="regular" selected> Box </option> <option value="box" class="regular" selected> Box </option>
<option value="box_by_4_points" class="regular" selected> Box by 4 points </option>
<option value="polygon" class="regular"> Polygon </option> <option value="polygon" class="regular"> Polygon </option>
<option value="polyline" class="regular"> Polyline </option> <option value="polyline" class="regular"> Polyline </option>
<option value="points" class="regular"> Points </option> <option value="points" class="regular"> Points </option>

Loading…
Cancel
Save