Skip to content

Commit

Permalink
Added new tools to join masks together and to slice a polygon/mask in…
Browse files Browse the repository at this point in the history
…to two parts (cvat-ai#7084)
  • Loading branch information
bsekachev committed Nov 14, 2023
1 parent 4e2df00 commit 401989d
Show file tree
Hide file tree
Showing 87 changed files with 3,000 additions and 1,479 deletions.
6 changes: 6 additions & 0 deletions changelog.d/20231108_134600_boris_join_slice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
### Added

- Implemented a feature allowing to slice one polygon/mask shape into two parts
(<https://github.com/opencv/cvat/pull/7084>)
- Implemented a feature allowing to join several masks into a single one
(<https://github.com/opencv/cvat/pull/7084>)
193 changes: 36 additions & 157 deletions cvat-canvas/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,144 +22,16 @@ yarn run build
yarn run build --mode=development # without a minification
```

## Using

Canvas itself handles:

- Shape context menu (PKM)
- Image moving (mousedrag)
- Image resizing (mousewheel)
- Image fit (dblclick)
- Remove point (PKM)
- Polyshape editing (Shift + LKM)

### API Methods

```ts
enum RectDrawingMethod {
CLASSIC = 'By 2 points',
EXTREME_POINTS = 'By 4 points'
}

enum CuboidDrawingMethod {
CLASSIC = 'From rectangle',
CORNER_POINTS = 'By 4 points',
}

enum Mode {
IDLE = 'idle',
DRAG = 'drag',
RESIZE = 'resize',
DRAW = 'draw',
EDIT = 'edit',
MERGE = 'merge',
SPLIT = 'split',
GROUP = 'group',
INTERACT = 'interact',
SELECT_ROI = 'select_roi',
DRAG_CANVAS = 'drag_canvas',
ZOOM_CANVAS = 'zoom_canvas',
}

interface Configuration {
smoothImage?: boolean;
autoborders?: boolean;
displayAllText?: boolean;
textFontSize?: number;
textPosition?: 'auto' | 'center';
textContent?: string;
undefinedAttrValue?: string;
showProjections?: boolean;
forceDisableEditing?: boolean;
intelligentPolygonCrop?: boolean;
forceFrameUpdate?: boolean;
creationOpacity?: number;
CSSImageFilter?: string;
}

interface DrawData {
enabled: boolean;
shapeType?: string;
rectDrawingMethod?: RectDrawingMethod;
cuboidDrawingMethod?: CuboidDrawingMethod;
numberOfPoints?: number;
initialState?: any;
crosshair?: boolean;
}

interface InteractionData {
shapeType: string;
minVertices?: number;
}

interface GroupData {
enabled: boolean;
resetGroup?: boolean;
}

interface MergeData {
enabled: boolean;
}

interface SplitData {
enabled: boolean;
}

interface InteractionResult {
points: number[];
shapeType: string;
button: number;
};

interface DrawnData {
shapeType: string;
points: number[];
objectType?: string;
occluded?: boolean;
attributes?: [index: number]: string;
label?: Label;
color?: string;
}

interface Canvas {
html(): HTMLDivElement;
setup(frameData: any, objectStates: any[], zLayer?: number): void;
setupReviewROIs(reviewROIs: Record<number, number[]>): void;
activate(clientID: number | null, attributeID?: number): void;
rotate(rotationAngle: number): void;
focus(clientID: number, padding?: number): void;
fit(): void;
grid(stepX: number, stepY: number): void;

interact(interactionData: InteractionData): void;
draw(drawData: DrawData): void;
group(groupData: GroupData): void;
split(splitData: SplitData): void;
merge(mergeData: MergeData): void;
select(objectState: any): void;

fitCanvas(): void;
bitmap(enable: boolean): void;
selectROI(enable: boolean): void;
dragCanvas(enable: boolean): void;
zoomCanvas(enable: boolean): void;

mode(): Mode;
cancel(): void;
configure(configuration: Configuration): void;
isAbleToChangeFrame(): boolean;
destroy(): void;

readonly geometry: Geometry;
}
```
For API methods, their arguments and return types, please look at ``canvas.ts``.

### API CSS

- All drawn objects (shapes, tracks) have an id `cvat_canvas_shape_{objectState.clientID}`
- Drawn shapes and tracks have classes `cvat_canvas_shape`,
`cvat_canvas_shape_activated`,
`cvat_canvas_shape_grouping`,
`cvat_canvas_shape_selection`,
`cvat_canvas_shape_merging`,
`cvat_canvas_shape_drawing`,
`cvat_canvas_shape_occluded`
Expand All @@ -185,10 +57,12 @@ Standard JS events are used.
- canvas.drawn => {state: DrawnData}
- canvas.interacted => {shapes: InteractionResult[]}
- canvas.editstart
- canvas.edited => {state: ObjectState, points: number[]}
- canvas.splitted => {state: ObjectState}
- canvas.groupped => {states: ObjectState[]}
- canvas.merged => {states: ObjectState[]}
- canvas.edited => {state: ObjectState, points: number[], rotation?: number}
- canvas.splitted => {state: ObjectState, frame: number, duration: number}
- canvas.groupped => {states: ObjectState[], duration: number}
- canvas.joined => {states: ObjectState[], points: number[], duration: number}
- canvas.sliced => {state: ObjectState, results: number[][], duration: number}
- canvas.merged => {states: ObjectState[], duration: number}
- canvas.canceled
- canvas.dragstart
- canvas.dragstop
Expand All @@ -197,11 +71,13 @@ Standard JS events are used.
- canvas.zoom
- canvas.reshape
- canvas.fit
- canvas.regionselected => {points: number[]}
- canvas.dragshape => {id: number}
- canvas.roiselected => {points: number[]}
- canvas.resizeshape => {id: number}
- canvas.contextmenu => { mouseEvent: MouseEvent, objectState: ObjectState, pointID: number }
- canvas.error => { exception: Error }
- canvas.message => { messages: { type: 'text' | 'list'; content: string | string[]; className?: string; icon?: 'info' | 'loading' }[] | null, topic: string }
- canvas.error => { exception: Error, domain?: string }
- canvas.destroy
```

Expand Down Expand Up @@ -232,28 +108,31 @@ canvas.draw({

## API Reaction

| | IDLE | GROUP | SPLIT | DRAW | MERGE | EDIT | DRAG | RESIZE | ZOOM_CANVAS | DRAG_CANVAS | INTERACT |
| ----------------- | ---- | ----- | ----- | ---- | ----- | ---- | ---- | ------ | ----------- | ----------- | -------- |
| setup() | + | + | + | +/- | + | +/- | +/- | +/- | + | + | + |
| activate() | + | - | - | - | - | - | - | - | - | - | - |
| rotate() | + | + | + | + | + | + | + | + | + | + | + |
| focus() | + | + | + | + | + | + | + | + | + | + | + |
| fit() | + | + | + | + | + | + | + | + | + | + | + |
| grid() | + | + | + | + | + | + | + | + | + | + | + |
| draw() | + | - | - | + | - | - | - | - | - | - | - |
| interact() | + | - | - | - | - | - | - | - | - | - | + |
| split() | + | - | + | - | - | - | - | - | - | - | - |
| group() | + | + | - | - | - | - | - | - | - | - | - |
| merge() | + | - | - | - | + | - | - | - | - | - | - |
| fitCanvas() | + | + | + | + | + | + | + | + | + | + | + |
| dragCanvas() | + | - | - | - | - | - | + | - | - | + | - |
| zoomCanvas() | + | - | - | - | - | - | - | + | + | - | - |
| cancel() | - | + | + | + | + | + | + | + | + | + | + |
| configure() | + | + | + | + | + | + | + | + | + | + | + |
| bitmap() | + | + | + | + | + | + | + | + | + | + | + |
| setZLayer() | + | + | + | + | + | + | + | + | + | + | + |
| setupReviewROIs() | + | + | + | + | + | + | + | + | + | + | + |
| destroy() | + | + | + | + | + | + | + | + | + | + | + |
| | IDLE | GROUP | SPLIT | DRAW | MERGE | EDIT | DRAG | RESIZE | ZOOM_CANVAS | DRAG_CANVAS | INTERACT | JOIN | SLICE | SELECT_REGION |
| -------------- | ---- | ----- | ----- | ---- | ----- | ---- | ---- | ------ | ----------- | ----------- | -------- | ---- | ----- | ------------- |
| setup() | + | + | + | +/- | + | +/- | +/- | +/- | + | + | + | + | + | + |
| activate() | + | - | - | - | - | - | - | - | - | - | - | - | - | - |
| rotate() | + | + | + | + | + | + | + | + | + | + | + | + | + | + |
| focus() | + | + | + | + | + | + | + | + | + | + | + | + | + | + |
| fit() | + | + | + | + | + | + | + | + | + | + | + | + | + | + |
| grid() | + | + | + | + | + | + | + | + | + | + | + | + | + | + |
| draw() | + | - | - | + | - | - | - | - | - | - | - | - | - | - |
| interact() | + | - | - | - | - | - | - | - | - | - | + | - | - | - |
| split() | + | - | + | - | - | - | - | - | - | - | - | - | - | - |
| group() | + | + | - | - | - | - | - | - | - | - | - | - | - | - |
| merge() | + | - | - | - | + | - | - | - | - | - | - | - | - | - |
| edit() | + | - | - | - | - | + | - | - | - | - | - | - | - | - |
| join() | + | - | - | - | - | - | - | - | - | - | - | + | - | - |
| slice() | + | - | - | - | - | - | - | - | - | - | - | - | + | - |
| selectRegion() | + | - | - | - | - | - | - | - | - | - | - | - | - | + |
| fitCanvas() | + | + | + | + | + | + | + | + | + | + | + | + | + | + |
| dragCanvas() | + | - | - | - | - | - | + | - | - | + | - | - | - | - |
| zoomCanvas() | + | - | - | - | - | - | - | + | + | - | - | - | - | - |
| cancel() | - | + | + | + | + | + | + | + | + | + | + | + | + | + |
| configure() | + | + | + | + | + | + | + | + | + | + | + | + | + | + |
| bitmap() | + | + | + | + | + | + | + | + | + | + | + | + | + | + |
| setZLayer() | + | + | + | + | + | + | + | + | + | + | + | + | + | + |
| destroy() | + | + | + | + | + | + | + | + | + | + | + | + | + | + |

<!--lint enable maximum-line-length-->

Expand Down
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.18.1",
"version": "2.19.0",
"description": "Part of Computer Vision Annotation Tool which presents its canvas library",
"main": "src/canvas.ts",
"scripts": {
Expand Down
66 changes: 36 additions & 30 deletions cvat-canvas/src/scss/canvas.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
//
// SPDX-License-Identifier: MIT

/* stylelint-disable selector-class-pattern, selector-id-pattern */

.cvat_canvas_hidden {
display: none;
}
Expand Down Expand Up @@ -65,17 +67,23 @@ polyline.cvat_shape_drawing_opacity {
stroke: red;
}

.cvat_canvas_shape_grouping {
.cvat_canvas_shape_selection {
@extend .cvat_shape_action_dasharray;
@extend .cvat_shape_action_opacity;

fill: darkmagenta;
fill: #fcfbfc;
}

image.cvat_canvas_shape_grouping {
image.cvat_canvas_shape_selection {
visibility: hidden;
}

.cvat_canvas_selection_box {
fill: white;
fill-opacity: 0.1;
stroke: white;
}

.cvat_canvas_shape_region_selection {
@extend .cvat_shape_action_dasharray;
@extend .cvat_shape_action_opacity;
Expand All @@ -92,7 +100,7 @@ circle.cvat_canvas_issue_region {
opacity: 1 !important;
}

polyline.cvat_canvas_shape_grouping {
polyline.cvat_canvas_shape_selection {
@extend .cvat_shape_action_dasharray;
@extend .cvat_shape_action_opacity;

Expand Down Expand Up @@ -314,14 +322,10 @@ g.cvat_canvas_shape_occluded {
}

.cvat_canvas_pixelized {
image-rendering: optimizeSpeed; /* Legal fallback */
image-rendering: -moz-crisp-edges; /* Firefox */
image-rendering: -o-crisp-edges; /* Opera */
image-rendering: -webkit-optimize-contrast; /* Safari */
image-rendering: optimize-contrast; /* CSS3 Proposed */
image-rendering: crisp-edges; /* CSS4 Proposed */
image-rendering: pixelated; /* CSS4 Proposed */
-ms-interpolation-mode: nearest-neighbor; /* IE8+ */
image-rendering: optimizeSpeed;
image-rendering: optimize-contrast;
image-rendering: crisp-edges;
image-rendering: pixelated;
}

.cvat_canvas_removed_image {
Expand Down Expand Up @@ -385,7 +389,7 @@ g.cvat_canvas_shape_occluded {
background-repeat: no-repeat;
width: 100%;
height: 100%;
box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, 0.75);
box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, 75%);
}

#cvat_canvas_bitmap {
Expand All @@ -397,7 +401,7 @@ g.cvat_canvas_shape_occluded {
background: black;
width: 100%;
height: 100%;
box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, 0.75);
box-shadow: 2px 2px 5px 0 rgba(0, 0, 0, 75%);
}

#cvat_canvas_grid {
Expand All @@ -414,6 +418,8 @@ g.cvat_canvas_shape_occluded {
}

#cvat_canvas_content {
@extend .cvat_canvas_pixelized;

filter: contrast(120%) saturate(150%);
position: absolute;
z-index: 2;
Expand All @@ -436,24 +442,24 @@ g.cvat_canvas_shape_occluded {
user-select: none;
}

@keyframes loadingAnimation {
0% {
stroke-dashoffset: 1;
stroke: #09c;
}
.cvat_canvas_shape_darken {
fill: #838383;
stroke: #838383;
}

50% {
stroke-dashoffset: 100;
stroke: #f44;
}
.cvat_canvas_sliced_contour {
fill-opacity: 0.01;
}

100% {
stroke-dashoffset: 300;
stroke: #09c;
}
.cvat_canvas_slicing_line {
pointer-events: none;
fill-opacity: 0;
}

.cvat_canvas_shape_darken {
fill: #838383;
stroke: #838383;
.cvat-canvas-notification-list-warning {
color: orange;
}

.cvat-canvas-notification-list-shortcuts {
color: yellow;
}
Loading

0 comments on commit 401989d

Please sign in to comment.