Added automatic annotation progress to the task view (#2148)

* Added automatic annotation progress to the task view

* Updated changelog & version

Co-authored-by: Nikita Manovich <nikita.manovich@intel.com>
main
Boris Sekachev 6 years ago committed by GitHub
parent 8d3c95a764
commit 38acc99f27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Ability to work with data on the fly (https://github.com/opencv/cvat/pull/2007)
- Annotation in process outline color wheel (<https://github.com/opencv/cvat/pull/2084>)
- On the fly annotation using DL detectors (<https://github.com/opencv/cvat/pull/2102>)
- Displaying automatic annotation progress on a task view (<https://github.com/opencv/cvat/pull/2148>)
- Automatic tracking of bounding boxes using serverless functions (<https://github.com/opencv/cvat/pull/2136>)
- [Datumaro] CLI command for dataset equality comparison (<https://github.com/opencv/cvat/pull/1989>)
- [Datumaro] Merging of datasets with different labels (<https://github.com/opencv/cvat/pull/2098>)

@ -16,6 +16,8 @@ import moment from 'moment';
import getCore from 'cvat-core-wrapper';
import patterns from 'utils/validation-patterns';
import { getReposData, syncRepos } from 'utils/git-utils';
import { ActiveInference } from 'reducers/interfaces';
import AutomaticAnnotationProgress from 'components/tasks-page/automatic-annotation-progress';
import UserSelector from './user-selector';
import LabelsEditorComponent from '../labels-editor/labels-editor';
@ -26,6 +28,8 @@ interface Props {
taskInstance: any;
installedGit: boolean; // change to git repos url
registeredUsers: any[];
activeInference: ActiveInference | null;
cancelAutoAnnotation(): void;
onTaskUpdate: (taskInstance: any) => void;
}
@ -125,10 +129,7 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
private renderTaskName(): JSX.Element {
const { name } = this.state;
const {
taskInstance,
onTaskUpdate,
} = this.props;
const { taskInstance, onTaskUpdate } = this.props;
return (
<Title
@ -161,9 +162,7 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
private renderParameters(): JSX.Element {
const { taskInstance } = this.props;
const { overlap } = taskInstance;
const { segmentSize } = taskInstance;
const { imageQuality } = taskInstance;
const { overlap, segmentSize, imageQuality } = taskInstance;
const zOrder = taskInstance.zOrder.toString();
return (
@ -197,11 +196,7 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
}
private renderUsers(): JSX.Element {
const {
taskInstance,
registeredUsers,
onTaskUpdate,
} = this.props;
const { taskInstance, registeredUsers, onTaskUpdate } = this.props;
const owner = taskInstance.owner ? taskInstance.owner.username : null;
const assignee = taskInstance.assignee ? taskInstance.assignee.username : null;
const created = moment(taskInstance.createdDate).format('MMMM Do YYYY');
@ -246,10 +241,7 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
private renderDatasetRepository(): JSX.Element | boolean {
const { taskInstance } = this.props;
const {
repository,
repositoryStatus,
} = this.state;
const { repository, repositoryStatus } = this.state;
return (
!!repository
@ -321,10 +313,7 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
}
private renderBugTracker(): JSX.Element {
const {
taskInstance,
onTaskUpdate,
} = this.props;
const { taskInstance, onTaskUpdate } = this.props;
const { bugTracker, bugTrackerEditing } = this.state;
let shown = false;
@ -400,10 +389,7 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
}
private renderLabelsEditor(): JSX.Element {
const {
taskInstance,
onTaskUpdate,
} = this.props;
const { taskInstance, onTaskUpdate } = this.props;
return (
<Row>
@ -424,6 +410,7 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
}
public render(): JSX.Element {
const { activeInference, cancelAutoAnnotation } = this.props;
return (
<div className='cvat-task-details'>
<Row type='flex' justify='start' align='middle'>
@ -446,7 +433,17 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
</Col>
<Col md={16} lg={17} xl={17} xxl={18}>
{ this.renderUsers() }
{ this.renderBugTracker() }
<Row type='flex' justify='space-between' align='middle'>
<Col span={12}>
{ this.renderBugTracker() }
</Col>
<Col span={10}>
<AutomaticAnnotationProgress
activeInference={activeInference}
cancelAutoAnnotation={cancelAutoAnnotation}
/>
</Col>
</Row>
{ this.renderDatasetRepository() }
{ this.renderLabelsEditor() }
</Col>

@ -0,0 +1,63 @@
// Copyright (C) 2020 Intel Corporation
//
// SPDX-License-Identifier: MIT
import React from 'react';
import { Row, Col } from 'antd/lib/grid';
import Text from 'antd/lib/typography/Text';
import Progress from 'antd/lib/progress';
import Tooltip from 'antd/lib/tooltip';
import Icon from 'antd/lib/icon';
import Modal from 'antd/lib/modal';
import { ActiveInference } from 'reducers/interfaces';
interface Props {
activeInference: ActiveInference | null;
cancelAutoAnnotation(): void;
}
export default function AutomaticAnnotationProgress(props: Props): JSX.Element | null {
const { activeInference, cancelAutoAnnotation } = props;
if (!activeInference) return null;
return (
<>
<Row>
<Col>
<Text strong>Automatic annotation</Text>
</Col>
</Row>
<Row type='flex' justify='space-between'>
<Col span={22}>
<Progress
percent={Math.floor(activeInference.progress)}
strokeColor={{
from: '#108ee9',
to: '#87d068',
}}
showInfo={false}
strokeWidth={5}
size='small'
/>
</Col>
<Col span={1} className='close-auto-annotation-icon'>
<Tooltip title='Cancel automatic annotation' mouseLeaveDelay={0}>
<Icon
type='close'
onClick={() => {
Modal.confirm({
title: 'You are going to cancel automatic annotation?',
content: 'Reached progress will be lost. Continue?',
okType: 'danger',
onOk() {
cancelAutoAnnotation();
},
});
}}
/>
</Tooltip>
</Col>
</Row>
</>
);
}

@ -10,14 +10,13 @@ import { Row, Col } from 'antd/lib/grid';
import Button from 'antd/lib/button';
import Icon from 'antd/lib/icon';
import Dropdown from 'antd/lib/dropdown';
import Tooltip from 'antd/lib/tooltip';
import Modal from 'antd/lib/modal';
import Progress from 'antd/lib/progress';
import moment from 'moment';
import ActionsMenuContainer from 'containers/actions-menu/actions-menu';
import { ActiveInference } from 'reducers/interfaces';
import { MenuIcon } from 'icons';
import AutomaticAnnotationProgress from './automatic-annotation-progress';
export interface TaskItemProps {
taskInstance: any;
@ -123,47 +122,10 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
/>
</Col>
</Row>
{ activeInference
&& (
<>
<Row>
<Col>
<Text strong>Automatic annotation</Text>
</Col>
</Row>
<Row type='flex' justify='space-between'>
<Col span={22}>
<Progress
percent={Math.floor(activeInference.progress)}
strokeColor={{
from: '#108ee9',
to: '#87d068',
}}
showInfo={false}
strokeWidth={5}
size='small'
/>
</Col>
<Col span={1} className='close-auto-annotation-icon'>
<Tooltip title='Cancel automatic annotation' mouseLeaveDelay={0}>
<Icon
type='close'
onClick={() => {
Modal.confirm({
title: 'You are going to cancel automatic annotation?',
content: 'Reached progress will be lost. Continue?',
okType: 'danger',
onOk() {
cancelAutoAnnotation();
},
});
}}
/>
</Tooltip>
</Col>
</Row>
</>
)}
<AutomaticAnnotationProgress
activeInference={activeInference}
cancelAutoAnnotation={cancelAutoAnnotation}
/>
</Col>
);
}

@ -7,10 +7,8 @@ import { connect } from 'react-redux';
import DetailsComponent from 'components/task-page/details';
import { updateTaskAsync } from 'actions/tasks-actions';
import {
Task,
CombinedState,
} from 'reducers/interfaces';
import { cancelInferenceAsync } from 'actions/models-actions';
import { Task, CombinedState, ActiveInference } from 'reducers/interfaces';
interface OwnProps {
task: Task;
@ -18,26 +16,32 @@ interface OwnProps {
interface StateToProps {
registeredUsers: any[];
activeInference: ActiveInference | null;
installedGit: boolean;
}
interface DispatchToProps {
cancelAutoAnnotation(): void;
onTaskUpdate: (taskInstance: any) => void;
}
function mapStateToProps(state: CombinedState): StateToProps {
function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
const { list } = state.plugins;
return {
registeredUsers: state.users.users,
installedGit: list.GIT_INTEGRATION,
activeInference: state.models.inferences[own.task.instance.id] || null,
};
}
function mapDispatchToProps(dispatch: any): DispatchToProps {
function mapDispatchToProps(dispatch: any, own: OwnProps): DispatchToProps {
return {
onTaskUpdate: (taskInstance: any): void => dispatch(updateTaskAsync(taskInstance)),
cancelAutoAnnotation(): void {
dispatch(cancelInferenceAsync(own.task.instance.id));
},
};
}
@ -46,7 +50,9 @@ function TaskPageContainer(props: StateToProps & DispatchToProps & OwnProps): JS
const {
task,
installedGit,
activeInference,
registeredUsers,
cancelAutoAnnotation,
onTaskUpdate,
} = props;
@ -55,8 +61,10 @@ function TaskPageContainer(props: StateToProps & DispatchToProps & OwnProps): JS
previewImage={task.preview}
taskInstance={task.instance}
installedGit={installedGit}
onTaskUpdate={onTaskUpdate}
registeredUsers={registeredUsers}
activeInference={activeInference}
onTaskUpdate={onTaskUpdate}
cancelAutoAnnotation={cancelAutoAnnotation}
/>
);
}

Loading…
Cancel
Save