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

Supported type for all labels #5273

Merged
merged 10 commits into from
Nov 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ non-ascii paths while adding files from "Connected file share" (issue #4428)
- Create manifest with cvat/server docker container command (<https://github.com/opencv/cvat/pull/5172>)
- Cannot assign a resource to a user who has an organization (<https://github.com/opencv/cvat/pull/5218>)
- Logs and annotations are not saved when logout from a job page (<https://github.com/opencv/cvat/pull/5266>)
- Added "type" field for all the labels, allows to reduce number of controls on annotation view (<https://github.com/opencv/cvat/pull/5273>)
- Occluded not applied on canvas instantly for a skeleton elements (<https://github.com/opencv/cvat/pull/5259>)
- Oriented bounding boxes broken with COCO format ss(<https://github.com/opencv/cvat/pull/5219>)
- Fixed upload resumption in production environments
Expand Down
13 changes: 13 additions & 0 deletions cvat-core/src/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,3 +481,16 @@ export enum WebhookSourceType {
export enum WebhookContentType {
JSON = 'application/json',
}

export enum LabelType {
ANY = 'any',
RECTANGLE = 'rectangle',
POLYGON = 'polygon',
POLYLINE = 'polyline',
POINTS = 'points',
ELLIPSE = 'ellipse',
CUBOID = 'cuboid',
SKELETON = 'skeleton',
MASK = 'mask',
TAG = 'tag',
}
2 changes: 1 addition & 1 deletion cvat-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-ui",
"version": "1.43.2",
"version": "1.44.0",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons';
import { SelectValue } from 'antd/lib/select';
import Layout, { SiderProps } from 'antd/lib/layout';
import Text from 'antd/lib/typography/Text';

import { filterApplicableLabels } from 'utils/filter-applicable-labels';
import { Label } from 'cvat-core-wrapper';
import { Canvas } from 'cvat-canvas-wrapper';
import { Canvas3d } from 'cvat-canvas3d-wrapper';
import { LogType } from 'cvat-logger';
Expand Down Expand Up @@ -147,6 +149,7 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
activatedStateID === null || activatedIndex === -1 ? null : filteredStates[activatedIndex];

const activeAttribute = activeObjectState ? labelAttrMap[activeObjectState.label.id] : null;
const applicableLabels = activeObjectState ? filterApplicableLabels(activeObjectState, labels) : [];

if (canvasIsReady) {
if (activeObjectState) {
Expand Down Expand Up @@ -308,12 +311,10 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
nextObject={nextObject}
/>
<ObjectBasicsEditor
currentLabel={activeObjectState.label.name}
labels={labels}
changeLabel={(value: SelectValue): void => {
const labelName = value as string;
const [newLabel] = labels.filter((_label): boolean => _label.name === labelName);
activeObjectState.label = newLabel;
currentLabel={activeObjectState.label.id}
labels={applicableLabels}
changeLabel={(value: Label): void => {
activeObjectState.label = value;
updateAnnotations([activeObjectState]);
}}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import React from 'react';
import Select, { SelectValue } from 'antd/lib/select';
import { Label } from 'cvat-core-wrapper';
import LabelSelector from 'components/label-selector/label-selector';

interface Props {
currentLabel: string;
labels: any[];
changeLabel(value: SelectValue): void;
currentLabel: number;
labels: Label[];
changeLabel(value: Label): void;
}

function ObjectBasicsEditor(props: Props): JSX.Element {
const { currentLabel, labels, changeLabel } = props;

return (
<div className='cvat-attribute-annotation-sidebar-basics-editor'>
<Select value={currentLabel} onChange={changeLabel} style={{ width: '50%' }}>
{labels.map(
(label: any): JSX.Element => (
<Select.Option value={label.name} key={label.name}>
{label.name}
</Select.Option>
),
)}
</Select>
<LabelSelector
style={{ width: '50%' }}
labels={labels}
value={currentLabel}
onChange={changeLabel}
/>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand All @@ -10,7 +11,7 @@

.attribute-annotation-sidebar:not(.ant-layout-sider-collapsed) {
background: $background-color-2;
padding: 5px;
padding: $grid-unit-size;

> .ant-layout-sider-children {
display: flex;
Expand All @@ -24,7 +25,7 @@
align-items: center;
justify-content: space-between;
font-size: 18px;
margin-top: 10px;
margin-top: $grid-unit-size;

> span {
max-width: 60%;
Expand All @@ -40,13 +41,13 @@
.cvat-attribute-annotation-sidebar-basics-editor {
display: flex;
align-items: center;
justify-content: space-between;
justify-content: center;
font-size: 18px;
margin: 10px 0;
margin: $grid-unit-size 0;
}

.attribute-annotations-sidebar-not-found-wrapper {
margin-top: 20px;
margin-top: $grid-unit-size * 3;
text-align: center;
flex-grow: 10;
}
Expand All @@ -56,7 +57,7 @@
}

.attribute-annotation-sidebar-attr-list-wrapper {
margin: 10px 0 10px 10px;
margin: $grid-unit-size 0 $grid-unit-size $grid-unit-size;
}

.attribute-annotation-sidebar-attr-elem-wrapper {
Expand All @@ -75,5 +76,5 @@
}

.cvat-sidebar-collapse-button-spacer {
height: 32px;
height: $grid-unit-size * 4;
}
12 changes: 9 additions & 3 deletions cvat-ui/src/components/annotation-page/canvas/brush-tools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import Icon, { VerticalAlignBottomOutlined } from '@ant-design/icons';
import InputNumber from 'antd/lib/input-number';
import Select from 'antd/lib/select';

import { getCore } from 'cvat-core-wrapper';
import { filterApplicableForType } from 'utils/filter-applicable-labels';
import { getCore, Label, LabelType } from 'cvat-core-wrapper';
import { Canvas, CanvasMode } from 'cvat-canvas-wrapper';
import {
BrushIcon, EraserIcon, PolygonMinusIcon, PolygonPlusIcon,
Expand Down Expand Up @@ -44,6 +45,7 @@ function BrushTools(): React.ReactPortal | null {
const [brushForm, setBrushForm] = useState<'circle' | 'square'>('circle');
const [[top, left], setTopLeft] = useState([0, 0]);
const [brushSize, setBrushSize] = useState(10);
const [applicableLabels, setApplicableLabels] = useState<Label[]>([]);

const [removeUnderlyingPixels, setRemoveUnderlyingPixels] = useState(false);
const dragBar = useDraggable(
Expand Down Expand Up @@ -99,6 +101,10 @@ function BrushTools(): React.ReactPortal | null {
}
}, [currentTool, brushSize, brushForm, visible, defaultLabelID, editableState]);

useEffect(() => {
setApplicableLabels(filterApplicableForType(LabelType.MASK, labels));
}, [labels]);

useEffect(() => {
const canvasContainer = window.document.getElementsByClassName('cvat-canvas-container')[0];
if (canvasContainer) {
Expand Down Expand Up @@ -254,9 +260,9 @@ function BrushTools(): React.ReactPortal | null {
icon={<VerticalAlignBottomOutlined />}
onClick={() => setRemoveUnderlyingPixels(!removeUnderlyingPixels)}
/>
{ !editableState && (
{ !editableState && !!applicableLabels.length && (
<LabelSelector
labels={labels}
labels={applicableLabels}
value={defaultLabelID}
onChange={({ id: labelID }: { id: number }) => {
if (Number.isInteger(labelID)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import React, { useCallback, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import message from 'antd/lib/message';

import { CombinedState } from 'reducers';
import { LabelType } from 'cvat-core-wrapper';
import { CombinedState, ObjectType } from 'reducers';
import { rememberObject, updateAnnotationsAsync } from 'actions/annotation-actions';
import LabelItemContainer from 'containers/annotation-page/standard-workspace/objects-side-bar/label-item';
import GlobalHotKeys from 'utils/mousetrap-react';
Expand All @@ -15,6 +17,8 @@ function LabelsListComponent(): JSX.Element {
const dispatch = useDispatch();
const labels = useSelector((state: CombinedState) => state.annotation.job.labels);
const activatedStateID = useSelector((state: CombinedState) => state.annotation.annotations.activatedStateID);
const activeShapeType = useSelector((state: CombinedState) => state.annotation.drawing.activeShapeType);
const activeObjectType = useSelector((state: CombinedState) => state.annotation.drawing.activeObjectType);
const states = useSelector((state: CombinedState) => state.annotation.annotations.states);
const keyMap = useSelector((state: CombinedState) => state.shortcuts.keyMap);

Expand Down Expand Up @@ -72,14 +76,22 @@ function LabelsListComponent(): JSX.Element {
if (Number.isInteger(labelID) && label) {
if (Number.isInteger(activatedStateID)) {
const activatedState = states.filter((state: any) => state.clientID === activatedStateID)[0];
if (activatedState) {
const bothAreTags = activatedState.objectType === ObjectType.TAG && label.type === ObjectType.TAG;
const labelIsApplicable = label.type === LabelType.ANY ||
activatedState.shapeType === label.type || bothAreTags;
if (activatedState && labelIsApplicable) {
activatedState.label = label;
dispatch(updateAnnotationsAsync([activatedState]));
}
} else {
dispatch(rememberObject({ activeLabelID: labelID }));
message.destroy();
message.success(`Default label was changed to "${label.name}"`);
const bothAreTags = activeObjectType === ObjectType.TAG && label.type === ObjectType.TAG;
const labelIsApplicable = label.type === LabelType.ANY ||
activeShapeType === label.type || bothAreTags;
if (labelIsApplicable) {
dispatch(rememberObject({ activeLabelID: labelID }));
message.destroy();
message.success(`Default label has been changed to "${label.name}"`);
}
}
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import React from 'react';
import Layout from 'antd/lib/layout';
import { ActiveControl } from 'reducers';
import { Label, LabelType } from 'cvat-core-wrapper';
import { Canvas3d as Canvas } from 'cvat-canvas3d-wrapper';
import MoveControl, {
Props as MoveControlProps,
Expand All @@ -20,13 +22,14 @@ import GroupControl, {
} from 'components/annotation-page/standard-workspace/controls-side-bar/group-control';
import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import ControlVisibilityObserver from 'components/annotation-page/standard-workspace/controls-side-bar/control-visibility-observer';
import { filterApplicableForType } from 'utils/filter-applicable-labels';

interface Props {
keyMap: KeyMap;
canvasInstance: Canvas;
activeControl: ActiveControl;
normalizedKeyMap: Record<string, string>;
labels: any[];
labels: Label[];
jobInstance: any;
repeatDrawShape(): void;
redrawShape(): void;
Expand Down Expand Up @@ -55,6 +58,7 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
jobInstance,
} = props;

const applicableLabels = filterApplicableForType(LabelType.CUBOID, labels);
const preventDefault = (event: KeyboardEvent | undefined): void => {
if (event) {
event.preventDefault();
Expand All @@ -74,7 +78,7 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
},
};

if (labels.length) {
if (applicableLabels.length) {
handlers = {
...handlers,
PASTE_SHAPE: (event: KeyboardEvent | undefined) => {
Expand Down Expand Up @@ -138,15 +142,15 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
<ObservedDrawCuboidControl
canvasInstance={canvasInstance}
isDrawing={activeControl === ActiveControl.DRAW_CUBOID}
disabled={!labels.length}
disabled={!applicableLabels.length}
/>
<ObservedGroupControl
switchGroupShortcut={normalizedKeyMap.SWITCH_GROUP_MODE}
resetGroupShortcut={normalizedKeyMap.RESET_GROUP}
canvasInstance={canvasInstance}
activeControl={activeControl}
groupObjects={groupObjects}
disabled={!labels.length}
disabled={!applicableLabels.length}
jobInstance={jobInstance}
/>
</Layout.Sider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import React, { useState, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { Row, Col } from 'antd/lib/grid';
import Text from 'antd/lib/typography/Text';
import Select from 'antd/lib/select';

import { CombinedState, DimensionType } from 'reducers';
import { DimensionType } from 'reducers';
import { Label } from 'cvat-core-wrapper';
import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import { shift } from 'utils/math';

Expand All @@ -18,6 +19,7 @@ interface ShortcutLabelMap {

type Props = {
onShortcutPress(event: KeyboardEvent | undefined, labelID: number): void;
labels: Label[];
};

const defaultShortcutLabelMap = {
Expand All @@ -34,8 +36,7 @@ const defaultShortcutLabelMap = {
} as ShortcutLabelMap;

const ShortcutsSelect = (props: Props): JSX.Element => {
const { onShortcutPress } = props;
const { labels } = useSelector((state: CombinedState) => state.annotation.job);
const { labels, onShortcutPress } = props;
const [shortcutLabelMap, setShortcutLabelMap] = useState(defaultShortcutLabelMap);

const keyMap: KeyMap = {};
Expand Down Expand Up @@ -69,7 +70,7 @@ const ShortcutsSelect = (props: Props): JSX.Element => {
if (event) {
event.preventDefault();
}
onShortcutPress(event, label.id);
onShortcutPress(event, label.id as number);
};
});

Expand Down
Loading