Skip to content

Commit

Permalink
Merge branch 'develop' into dk/cuboid-resize-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ActiveChooN authored Feb 5, 2021
2 parents 9e0b599 + c3b88ad commit cf62d72
Show file tree
Hide file tree
Showing 100 changed files with 14,472 additions and 498 deletions.
9 changes: 7 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- CVAT-3D: support lidar data on the server side (<https://github.com/openvinotoolkit/cvat/pull/2534>)
- CVAT-3D: Load all frames corresponding to the job instance
(<https://github.com/openvinotoolkit/cvat/pull/2645>)
- Intelligent scissors with OpenCV javascript (<https://github.com/openvinotoolkit/cvat/pull/2689>)

### Changed

- Updated HTTPS install README section (cleanup and described more robust deploy)
- Logstash is improved for using with configurable elasticsearch outputs (<https://github.com/openvinotoolkit/cvat/pull/2531>)

### Deprecated

Expand All @@ -31,7 +35,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed filters select overflow (<https://github.com/openvinotoolkit/cvat/pull/2614>)
- Fixed tasks in project autoannotation (<https://github.com/openvinotoolkit/cvat/pull/2725>)
- Cuboids are missed in annotations statistics (<https://github.com/openvinotoolkit/cvat/pull/2704>)
- The list of files attached to the task is not displayed (<https://github.com/openvinotoolkit/cvat/pull/2706>)
- The list of files attached to the task is not displayed (<https://github.com/openvinotoolkit/cvat/pul
- A couple of css-related issues (top bar disappear, wrong arrow position on collapse elements) (<https://github.com/openvinotoolkit/cvat/pull/2736>)
- Issue with point region doesn't work in Firefox (<https://github.com/openvinotoolkit/cvat/pull/2727>)
- Fixed cuboid perpective change (<https://github.com/openvinotoolkit/cvat/pull/2733>)

### Security
Expand Down Expand Up @@ -124,7 +130,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added auto inference of url schema from host in CLI, if provided (<https://github.com/openvinotoolkit/cvat/pull/2240>)
- Track frames in skips between annotation is presented in MOT and MOTS formats are marked `outside` (<https://github.com/openvinotoolkit/cvat/pull/2198>)
- UI packages installation with `npm ci` instead of `npm install` (<https://github.com/openvinotoolkit/cvat/pull/2350>)
- Logstash is improved for using with configurable elasticsearch outputs (<https://github.com/openvinotoolkit/cvat/pull/2531>)

### Removed

Expand Down
6 changes: 6 additions & 0 deletions Dockerfile.ui
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ RUN apk add python3 g++ make
# Install dependencies
COPY cvat-core/package*.json /tmp/cvat-core/
COPY cvat-canvas/package*.json /tmp/cvat-canvas/
COPY cvat-canvas3d/package*.json /tmp/cvat-canvas3d/
COPY cvat-ui/package*.json /tmp/cvat-ui/
COPY cvat-data/package*.json /tmp/cvat-data/

Expand All @@ -35,13 +36,18 @@ RUN npm ci
WORKDIR /tmp/cvat-canvas/
RUN npm ci

# Install cvat-canvas dependencies
WORKDIR /tmp/cvat-canvas3d/
RUN npm ci

# Install cvat-ui dependencies
WORKDIR /tmp/cvat-ui/
RUN npm ci

# Build source code
COPY cvat-data/ /tmp/cvat-data/
COPY cvat-core/ /tmp/cvat-core/
COPY cvat-canvas3d/ /tmp/cvat-canvas3d/
COPY cvat-canvas/ /tmp/cvat-canvas/
COPY cvat-ui/ /tmp/cvat-ui/
RUN npm run build
Expand Down
1 change: 0 additions & 1 deletion cvat-canvas/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
src/*.js
dist
340 changes: 0 additions & 340 deletions cvat-canvas/images/states.svg

This file was deleted.

2 changes: 1 addition & 1 deletion cvat-canvas/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cvat-canvas/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-canvas",
"version": "2.2.2",
"version": "2.3.1",
"description": "Part of Computer Vision Annotation Tool which presents its canvas library",
"main": "src/canvas.ts",
"scripts": {
Expand Down
4 changes: 4 additions & 0 deletions cvat-canvas/src/scss/canvas.scss
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ polyline.cvat_shape_drawing_opacity {
stroke: red;
}

.cvat_canvas_threshold {
stroke: red;
}

.cvat_canvas_shape_grouping {
@extend .cvat_shape_action_dasharray;
@extend .cvat_shape_action_opacity;
Expand Down
6 changes: 5 additions & 1 deletion cvat-canvas/src/typescript/canvasModel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2019-2020 Intel Corporation
// Copyright (C) 2019-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -76,6 +76,10 @@ export interface InteractionData {
crosshair?: boolean;
minPosVertices?: number;
minNegVertices?: number;
enableNegVertices?: boolean;
enableThreshold?: boolean;
enableSliding?: boolean;
allowRemoveOnlyLast?: boolean;
}

export interface InteractionResult {
Expand Down
3 changes: 3 additions & 0 deletions cvat-canvas/src/typescript/canvasView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
shapes: InteractionResult[] | null,
shapesUpdated: boolean = true,
isDone: boolean = false,
threshold: number | null = null,
): void {
const { zLayer } = this.controller;
if (Array.isArray(shapes)) {
Expand All @@ -176,6 +177,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
isDone,
shapes,
zOrder: zLayer || 0,
threshold,
},
});

Expand Down Expand Up @@ -1050,6 +1052,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
});

this.content.addEventListener('wheel', (event): void => {
if (event.ctrlKey) return;
const { offset } = this.controller.geometry;
const point = translateToSVG(this.content, [event.clientX, event.clientY]);
self.controller.zoom(point[0] - offset, point[1] - offset, event.deltaY > 0 ? -1 : 1);
Expand Down
107 changes: 100 additions & 7 deletions cvat-canvas/src/typescript/interactionHandler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT

Expand All @@ -24,6 +24,8 @@ export class InteractionHandlerImpl implements InteractionHandler {
private interactionShapes: SVG.Shape[];
private currentInteractionShape: SVG.Shape | null;
private crosshair: Crosshair;
private threshold: SVG.Rect | null;
private thresholdRectSize: number;

private prepareResult(): InteractionResult[] {
return this.interactionShapes.map(
Expand Down Expand Up @@ -63,12 +65,21 @@ export class InteractionHandlerImpl implements InteractionHandler {
return enabled && !ctrlKey && !!interactionShapes.length;
}

const minimumVerticesAchieved =
(typeof minPosVertices === 'undefined' || minPosVertices <= positiveShapes.length) &&
(typeof minNegVertices === 'undefined' || minPosVertices <= negativeShapes.length);
const minPosVerticesAchieved = typeof minPosVertices === 'undefined' || minPosVertices <= positiveShapes.length;
const minNegVerticesAchieved = typeof minNegVertices === 'undefined' || minPosVertices <= negativeShapes.length;
const minimumVerticesAchieved = minPosVerticesAchieved && minNegVerticesAchieved;
return enabled && !ctrlKey && minimumVerticesAchieved && shapesWereUpdated;
}

private addThreshold(): void {
const { x, y } = this.cursorPosition;
this.threshold = this.canvas
.rect(this.thresholdRectSize, this.thresholdRectSize)
.fill('none')
.addClass('cvat_canvas_threshold');
this.threshold.center(x, y);
}

private addCrosshair(): void {
const { x, y } = this.cursorPosition;
this.crosshair.show(this.canvas, x, y, this.geometry.scale);
Expand All @@ -80,9 +91,12 @@ export class InteractionHandlerImpl implements InteractionHandler {

private interactPoints(): void {
const eventListener = (e: MouseEvent): void => {
if ((e.button === 0 || e.button === 2) && !e.altKey) {
if ((e.button === 0 || (e.button === 2 && this.interactionData.enableNegVertices)) && !e.altKey) {
e.preventDefault();
const [cx, cy] = translateToSVG((this.canvas.node as any) as SVGSVGElement, [e.clientX, e.clientY]);
if (!this.isWithingFrame(cx, cy)) return;
if (!this.isWithinThreshold(cx, cy)) return;

this.currentInteractionShape = this.canvas
.circle((consts.BASE_POINT_SIZE * 2) / this.geometry.scale)
.center(cx, cy)
Expand All @@ -101,6 +115,12 @@ export class InteractionHandlerImpl implements InteractionHandler {

const self = this.currentInteractionShape;
self.on('mouseenter', (): void => {
if (this.interactionData.allowRemoveOnlyLast) {
if (this.interactionShapes.indexOf(self) !== this.interactionShapes.length - 1) {
return;
}
}

self.attr({
'stroke-width': consts.POINTS_SELECTED_STROKE_WIDTH / this.geometry.scale,
});
Expand Down Expand Up @@ -166,6 +186,10 @@ export class InteractionHandlerImpl implements InteractionHandler {
if (this.interactionData.crosshair) {
this.addCrosshair();
}

if (this.interactionData.enableThreshold) {
this.addThreshold();
}
}

private startInteraction(): void {
Expand All @@ -183,6 +207,11 @@ export class InteractionHandlerImpl implements InteractionHandler {
this.removeCrosshair();
}

if (this.threshold) {
this.threshold.remove();
this.threshold = null;
}

this.canvas.off('mousedown.interaction');
this.interactionShapes.forEach((shape: SVG.Shape): SVG.Shape => shape.remove());
this.interactionShapes = [];
Expand All @@ -192,14 +221,39 @@ export class InteractionHandlerImpl implements InteractionHandler {
}
}

private isWithinThreshold(x: number, y: number): boolean {
const [prev] = this.interactionShapes.slice(-1);
if (!this.interactionData.enableThreshold || !prev) {
return true;
}

const [prevCx, prevCy] = [(prev as SVG.Circle).cx(), (prev as SVG.Circle).cy()];
const xDiff = Math.abs(prevCx - x);
const yDiff = Math.abs(prevCy - y);

return xDiff < this.thresholdRectSize / 2 && yDiff < this.thresholdRectSize / 2;
}

private isWithingFrame(x: number, y: number): boolean {
const { offset, image } = this.geometry;
const { width, height } = image;
const [imageX, imageY] = [Math.round(x - offset), Math.round(y - offset)];
return imageX >= 0 && imageX < width && imageY >= 0 && imageY < height;
}

public constructor(
onInteraction: (shapes: InteractionResult[] | null, shapesUpdated?: boolean, isDone?: boolean) => void,
onInteraction: (
shapes: InteractionResult[] | null,
shapesUpdated?: boolean,
isDone?: boolean,
threshold?: number,
) => void,
canvas: SVG.Container,
geometry: Geometry,
) {
this.onInteraction = (shapes: InteractionResult[] | null, shapesUpdated?: boolean, isDone?: boolean): void => {
this.shapesWereUpdated = false;
onInteraction(shapes, shapesUpdated, isDone);
onInteraction(shapes, shapesUpdated, isDone, this.threshold ? this.thresholdRectSize / 2 : null);
};
this.canvas = canvas;
this.geometry = geometry;
Expand All @@ -208,6 +262,8 @@ export class InteractionHandlerImpl implements InteractionHandler {
this.interactionData = { enabled: false };
this.currentInteractionShape = null;
this.crosshair = new Crosshair();
this.threshold = null;
this.thresholdRectSize = 300;
this.cursorPosition = {
x: 0,
y: 0,
Expand All @@ -219,6 +275,43 @@ export class InteractionHandlerImpl implements InteractionHandler {
if (this.crosshair) {
this.crosshair.move(x, y);
}
if (this.threshold) {
this.threshold.center(x, y);
}

if (this.interactionData.enableSliding && this.interactionShapes.length) {
if (this.isWithingFrame(x, y)) {
if (this.interactionData.enableThreshold && !this.isWithinThreshold(x, y)) return;
this.onInteraction(
[
...this.prepareResult(),
{
points: [x - this.geometry.offset, y - this.geometry.offset],
shapeType: 'points',
button: 0,
},
],
true,
false,
);
}
}
});

this.canvas.on('wheel.interaction', (e: WheelEvent): void => {
if (e.ctrlKey) {
if (this.threshold) {
const { x, y } = this.cursorPosition;
e.preventDefault();
if (e.deltaY > 0) {
this.thresholdRectSize *= 6 / 5;
} else {
this.thresholdRectSize *= 5 / 6;
}
this.threshold.size(this.thresholdRectSize, this.thresholdRectSize);
this.threshold.center(x, y);
}
}
});

document.body.addEventListener('keyup', (e: KeyboardEvent): void => {
Expand Down
6 changes: 3 additions & 3 deletions cvat-canvas/src/typescript/regionSelector.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2020 Intel Corporation
// Copyright (C) 2020-2021 Intel Corporation
//
// SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -66,7 +66,7 @@ export class RegionSelectorImpl implements RegionSelector {
'stroke-width': consts.BASE_STROKE_WIDTH / this.geometry.scale,
})
.addClass('cvat_canvas_shape_region_selection');
this.selectionRect.attr({ ...this.startSelectionPoint });
this.selectionRect.attr({ ...this.startSelectionPoint, width: 1, height: 1 });
}
};

Expand All @@ -78,7 +78,7 @@ export class RegionSelectorImpl implements RegionSelector {
} = this.selectionRect.bbox();
this.selectionRect.remove();
this.selectionRect = null;
if (w === 0 && h === 0) {
if (w <= 1 && h <= 1) {
this.onRegionSelected([x - offset, y - offset]);
} else {
this.onRegionSelected([x - offset, y - offset, x2 - offset, y2 - offset]);
Expand Down
1 change: 1 addition & 0 deletions cvat-canvas3d/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
webpack.config.js
46 changes: 46 additions & 0 deletions cvat-canvas3d/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (C) 2021 Intel Corporation
//
// SPDX-License-Identifier: MIT

module.exports = {
env: {
node: true,
},
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 6,
},
plugins: ['@typescript-eslint', 'import'],
extends: [
'plugin:@typescript-eslint/recommended',
'airbnb-typescript/base',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
],
rules: {
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/indent': ['warn', 4],
'no-plusplus': 0,
'no-restricted-syntax': [
0,
{
selector: 'ForOfStatement',
},
],
'max-len': ['error', { code: 120 }],
'no-continue': 0,
'func-names': 0,
'no-console': 0, // this rule deprecates console.log, console.warn etc. because 'it is not good in production code'
'lines-between-class-members': 0,
'import/prefer-default-export': 0, // works incorrect with interfaces
'newline-per-chained-call': 0, // makes code uglier
},
settings: {
'import/resolver': {
node: {
extensions: ['.ts', '.js', '.json'],
},
},
},
};
1 change: 1 addition & 0 deletions cvat-canvas3d/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist
Loading

0 comments on commit cf62d72

Please sign in to comment.