Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new tools to join masks together and to slice a polygon/mask into two parts #7084

Merged
merged 96 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from 94 commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
c51b03a
Added controls
bsekachev Oct 31, 2023
fb78358
Removed unused field
bsekachev Oct 31, 2023
50dd9ed
Updated canvas
bsekachev Oct 31, 2023
b68330e
Added fake pipeline
bsekachev Oct 31, 2023
1f5768c
Some code refactoring
bsekachev Oct 31, 2023
f3f39f2
A little bit more refactored code
bsekachev Oct 31, 2023
f1042eb
Fixed shortcut
bsekachev Oct 31, 2023
180e51b
Almost done join
bsekachev Oct 31, 2023
b535000
Fixed join algorithm
bsekachev Oct 31, 2023
469ae9b
Minor refactoring
bsekachev Oct 31, 2023
6dc541c
tmp
bsekachev Oct 31, 2023
2794598
..
bsekachev Nov 1, 2023
4784e8a
Written basic slice code in ui & canvas parts
bsekachev Nov 2, 2023
5b960b9
Additional refactoring
bsekachev Nov 2, 2023
2bd5436
tmp
bsekachev Nov 2, 2023
564a3e8
Fixed algorithm
bsekachev Nov 3, 2023
61c7168
Added slice method to core, linked to ui
bsekachev Nov 6, 2023
68c2ed5
tmp
bsekachev Nov 6, 2023
686428c
Documentation retouch: cloud storages and mot data format (#7071)
mdacoca Oct 31, 2023
a3723b4
[Snyk] Security upgrade urllib3 from 1.26.17 to 1.26.18 (#7027)
nmanovic Nov 1, 2023
d0abe15
[AWS S3] Use local session (#7067)
Marishka17 Nov 2, 2023
3700dd6
Compress `changeFrame` events (#7048)
klakhov Nov 2, 2023
04146e1
REST API tests for default bucket prefix (#7079)
Marishka17 Nov 2, 2023
376a5ba
Chunk preparation optimization (#7081)
azhavoro Nov 2, 2023
c299816
Fixed user email auto verification on accepting organization invitati…
klakhov Nov 3, 2023
7287088
Prepare release v2.8.1
cvat-bot[bot] Nov 3, 2023
0f862d4
Update develop after v2.8.1
cvat-bot[bot] Nov 5, 2023
5a6e352
Fixed opencv runtime initialization
bsekachev Nov 6, 2023
8be4c6e
Update changelog.d/20231106_112434_boris_fixed_opencv_runtime_init.md
bsekachev Nov 6, 2023
5056ada
Enhanced fix
bsekachev Nov 6, 2023
7eaae24
Clear memory
bsekachev Nov 6, 2023
628cf87
Correct state update
bsekachev Nov 6, 2023
1e892fc
Implemented convex hull
bsekachev Nov 6, 2023
e22e52f
Slice for masks
bsekachev Nov 6, 2023
75e93c4
Merge branch 'develop' into bs/join_slice
bsekachev Nov 6, 2023
4e27ace
Removed extra code
bsekachev Nov 6, 2023
32a0b1f
Merge branch 'develop' into bs/join_slice
bsekachev Nov 6, 2023
6f3735e
Refactoring & improved UX
bsekachev Nov 6, 2023
b611551
...
bsekachev Nov 6, 2023
708c399
join only for masks
bsekachev Nov 6, 2023
27fdca7
Updated icons
bsekachev Nov 6, 2023
7e2ff34
minor improvements
bsekachev Nov 7, 2023
c74e4e1
Collecting contours from canvas
bsekachev Nov 7, 2023
7689e82
Slice via shortcut
bsekachev Nov 7, 2023
f5c87c4
Added messaging
bsekachev Nov 7, 2023
fe30fdd
Added undo/slice
bsekachev Nov 7, 2023
b039832
Added alt key handling
bsekachev Nov 7, 2023
550e75b
Accelerated join
bsekachev Nov 7, 2023
645a59b
Found & fixed one problem in existing code
bsekachev Nov 7, 2023
f59eb12
Added comment
bsekachev Nov 7, 2023
61e4757
Added events
bsekachev Nov 7, 2023
5ec0fe2
Added some more logs
bsekachev Nov 7, 2023
f663826
Added count field
bsekachev Nov 7, 2023
cb6249f
Initiated code for shape converter
bsekachev Nov 7, 2023
da13691
Conversion feature
bsekachev Nov 7, 2023
5ea4486
Implemented basic conversion logic for masks
bsekachev Nov 7, 2023
c9c9478
Removed converter code for now
bsekachev Nov 8, 2023
071e06f
Changes 1
bsekachev Nov 8, 2023
a1b1f19
Cleared scss file
bsekachev Nov 8, 2023
ddf37e9
Fixed some stylelint problems
bsekachev Nov 8, 2023
43210e4
Updated table
bsekachev Nov 8, 2023
c281390
Removed extra code
bsekachev Nov 8, 2023
ecfcbcf
Slicing handler refactoring
bsekachev Nov 8, 2023
ac9c15d
Code refactoring
bsekachev Nov 8, 2023
73749db
Simplified constructors
bsekachev Nov 8, 2023
110bbc1
Merge branch 'develop' into bs/join_slice
bsekachev Nov 8, 2023
9cbef1e
Refactoring
bsekachev Nov 8, 2023
675fa3b
Refactoring, license headers
bsekachev Nov 8, 2023
43ac50e
Updated versions, added changelog fragment
bsekachev Nov 8, 2023
6fbbe27
Fixed stylelint
bsekachev Nov 8, 2023
6fe9663
Fixed polygon track can be sliced
bsekachev Nov 8, 2023
8af8d0b
Added joining messages, fixed joining for several frames
bsekachev Nov 8, 2023
2be0834
Finish drawing with hold shift
bsekachev Nov 8, 2023
2130c76
Fixed test
bsekachev Nov 8, 2023
1f3cd9e
Fixed tests
bsekachev Nov 8, 2023
fa7a832
Minor improvements
bsekachev Nov 8, 2023
a9cd4dc
More helpful messages
bsekachev Nov 8, 2023
977f883
Added correct tooltip
bsekachev Nov 8, 2023
628e0a1
Fixed some pixel-level problems
bsekachev Nov 8, 2023
b1778b1
Fixed test
bsekachev Nov 8, 2023
b0da963
Fixed kernel size
bsekachev Nov 8, 2023
66ad8c6
Enhanced extra tools popover
bsekachev Nov 8, 2023
9d2db04
Minor UI improvements
bsekachev Nov 8, 2023
6d5da73
Updated icons
bsekachev Nov 9, 2023
4bad79e
Added missed files
bsekachev Nov 9, 2023
f885771
Added shortcut
bsekachev Nov 9, 2023
aebc9cb
Fixed some corner cases
bsekachev Nov 9, 2023
76d0ea6
Added more error handling
bsekachev Nov 9, 2023
a54cd25
Improved hints feature
bsekachev Nov 9, 2023
720354a
Adjusted transition effect
bsekachev Nov 9, 2023
4760e37
Better color for a message
bsekachev Nov 9, 2023
a8f85f0
Applied comments from Maxim
bsekachev Nov 9, 2023
23c89e8
Resolved conflict
bsekachev Nov 9, 2023
f6f4a20
Do not autoselect shape if slice enabled via button
bsekachev Nov 13, 2023
88e2dd4
applied comments
bsekachev Nov 13, 2023
ef80e93
Fix reexport
bsekachev Nov 13, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading