Skip to content

Commit

Permalink
Merge branch 'develop' into bs/couple_of_fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
nmanovic committed May 22, 2020
2 parents e8c937d + 27efa89 commit dacef18
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 82 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Removed
- `annotation` application is replaced with `dataset_manager` (https://github.com/opencv/cvat/pull/1352)
- `_DATUMARO_INIT_LOGLEVEL` env. variable is removed in favor of regular `--loglevel` cli parameter (https://github.com/opencv/cvat/pull/1583)

### Fixed
- Categories for empty projects with no sources are taken from own dataset (https://github.com/opencv/cvat/pull/1352)
Expand All @@ -49,6 +50,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `tf.placeholder() is not compatible with eager execution` exception for auto_segmentation (<https://github.com/opencv/cvat/pull/1562>)
- Canvas cannot be moved with move functionality on left mouse key (<https://github.com/opencv/cvat/pull/1573>)
- Deep extreme cut request is sent when draw any shape with Make AI polygon option enabled (<https://github.com/opencv/cvat/pull/1573>)
- Fixed an error when exporting a task with cuboids to any format except CVAT (<https://github.com/opencv/cvat/pull/1577>)
- Synchronization with remote git repo (<https://github.com/opencv/cvat/pull/1582>)
- A problem with mask to polygons conversion when polygons are too small (<https://github.com/opencv/cvat/pull/1581>)

### Security
-
Expand Down
3 changes: 2 additions & 1 deletion cvat-ui/src/components/create-task-page/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
text-align: center;
padding-top: 40px;
overflow-y: auto;
height: 90%;
height: 100%;
padding-bottom: 40px;

> div > span {
font-size: 36px;
Expand Down
15 changes: 11 additions & 4 deletions cvat-ui/src/components/register-page/register-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Checkbox from 'antd/lib/checkbox';
import patterns from 'utils/validation-patterns';

import { UserAgreement } from 'reducers/interfaces'
import { Row, Col } from 'antd/lib/grid';

export interface UserConfirmation {
name: string;
Expand Down Expand Up @@ -107,9 +108,9 @@ class RegisterFormComponent extends React.PureComponent<RegisterFormProps> {
form.validateFields((error, values): void => {
if (!error) {
values.confirmations = []

for (const userAgreement of userAgreements) {

values.confirmations.push({
name: userAgreement.name,
value: values[userAgreement.name]
Expand Down Expand Up @@ -289,8 +290,14 @@ class RegisterFormComponent extends React.PureComponent<RegisterFormProps> {

return (
<Form onSubmit={this.handleSubmit} className='login-form'>
{this.renderFirstNameField()}
{this.renderLastNameField()}
<Row gutter={8}>
<Col span={12}>
{this.renderFirstNameField()}
</Col>
<Col span={12}>
{this.renderLastNameField()}
</Col>
</Row>
{this.renderUsernameField()}
{this.renderEmailField()}
{this.renderPasswordField()}
Expand Down
5 changes: 3 additions & 2 deletions cvat-ui/src/components/register-page/register-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: MIT

import './styles.scss';
import React from 'react';
import { RouteComponentProps } from 'react-router';
import { Link, withRouter } from 'react-router-dom';
Expand Down Expand Up @@ -29,8 +30,8 @@ function RegisterPageComponent(
xs: { span: 14 },
sm: { span: 14 },
md: { span: 10 },
lg: { span: 4 },
xl: { span: 4 },
lg: { span: 6 },
xl: { span: 5 },
};

const {
Expand Down
7 changes: 7 additions & 0 deletions cvat-ui/src/components/register-page/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright (C) 2020 Intel Corporation
//
// SPDX-License-Identifier: MIT

.ant-form-item {
margin-bottom: 12px;
}
3 changes: 2 additions & 1 deletion cvat-ui/src/components/settings-page/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
@import '../../base.scss';

.cvat-settings-page {
height: 90%;
height: 100%;
overflow-y: auto;
padding-bottom: 15px;

> div:nth-child(1) {
margin-top: 30px;
Expand Down
1 change: 1 addition & 0 deletions cvat-ui/src/components/tasks-page/top-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ function TopBarComponent(props: VisibleTopBarProps & RouteComponentProps): JSX.E
onClick={
(): void => history.push('/tasks/create')
}
icon='plus'
>
Create new task
</Button>
Expand Down
2 changes: 2 additions & 0 deletions cvat/apps/dataset_manager/bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,8 @@ def convert_attrs(label, cvat_attrs):
x0, y0, x1, y1 = anno_points
anno = datumaro.Bbox(x0, y0, x1 - x0, y1 - y0,
label=anno_label, attributes=anno_attr, group=anno_group)
elif shape_obj.type == ShapeType.CUBOID:
continue # Datumaro does not support cuboids
else:
raise Exception("Unknown shape type '%s'" % shape_obj.type)

Expand Down
17 changes: 8 additions & 9 deletions cvat/apps/git/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@
import shutil
import subprocess
from glob import glob
from tempfile import TemporaryDirectory
import zipfile

import django_rq
import git
from django.db import transaction
from django.utils import timezone
from pyunpack import Archive

from cvat.apps.dataset_manager.task import export_task
from cvat.apps.engine.log import slogger
Expand Down Expand Up @@ -284,16 +283,16 @@ def push(self, user, scheme, host, db_task, last_save):
if ext == '.zip':
shutil.move(dump_name, self._annotation_file)
elif ext == '.xml':
with TemporaryDirectory() as tmp_dir:
# TODO: remove extra packing-unpacking
Archive(src_path).extractall(tmp_dir)
anno_paths = glob(osp.join(tmp_dir, '**', '*.xml'),
recursive=True)
shutil.move(anno_paths[0], self._annotation_file)
with zipfile.ZipFile(dump_name) as archive:
for f in archive.namelist():
if f.endswith('.xml'):
with open(self._annotation_file, 'wb') as output:
output.write(archive.read(f))
break
os.remove(dump_name)
else:
raise Exception("Got unknown annotation file type")

os.remove(dump_name)
self._rep.git.add(self._annotation_file)

# Merge diffs
Expand Down
85 changes: 21 additions & 64 deletions datumaro/datumaro/cli/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

import argparse
import logging as log
import logging.handlers
import os
import sys

from . import contexts, commands
Expand All @@ -25,6 +23,25 @@
def loglevel(name):
return _log_levels[name]

class _LogManager:
@classmethod
def init_logger(cls, args=None):
# Define minimalistic parser only to obtain loglevel
parser = argparse.ArgumentParser(add_help=False)
cls._define_loglevel_option(parser)
args, _ = parser.parse_known_args(args)

log.basicConfig(format='%(asctime)s %(levelname)s: %(message)s',
level=args.loglevel)

@staticmethod
def _define_loglevel_option(parser):
parser.add_argument('--loglevel', type=loglevel, default='info',
help="Logging level (options: %s; default: %s)" % \
(', '.join(_log_levels.keys()), "%(default)s"))
return parser


def _make_subcommands_help(commands, help_line_start=0):
desc = ""
for command_name, _, command_help in commands:
Expand All @@ -38,9 +55,7 @@ def make_parser():
formatter_class=argparse.RawDescriptionHelpFormatter)

parser.add_argument('--version', action='version', version=VERSION)
parser.add_argument('--loglevel', type=loglevel, default='info',
help="Logging level (options: %s; default: %s)" % \
(', '.join(_log_levels.keys()), "%(default)s"))
_LogManager._define_loglevel_option(parser)

known_contexts = [
('project', contexts.project, "Actions on projects (datasets)"),
Expand Down Expand Up @@ -83,71 +98,13 @@ def make_parser():

return parser

class _LogManager:
_LOGLEVEL_ENV_NAME = '_DATUMARO_INIT_LOGLEVEL'
_BUFFER_SIZE = 1000
_root = None
_init_handler = None
_default_handler = None

@classmethod
def init_basic_logger(cls):
base_loglevel = os.getenv(cls._LOGLEVEL_ENV_NAME, 'info')
base_loglevel = loglevel(base_loglevel)
root = log.getLogger()
root.setLevel(base_loglevel)

# NOTE: defer use of this handler until the logger
# is properly initialized, but keep logging enabled before this.
# Store messages obtained during initialization and print them after
# if necessary.
default_handler = log.StreamHandler()
default_handler.setFormatter(
log.Formatter('%(asctime)s %(levelname)s: %(message)s'))

init_handler = logging.handlers.MemoryHandler(cls._BUFFER_SIZE,
target=default_handler)
root.addHandler(init_handler)

cls._root = root
cls._init_handler = init_handler
cls._default_handler = default_handler

@classmethod
def set_up_logger(cls, level):
log.getLogger().setLevel(level)

if cls._init_handler:
# NOTE: Handlers are not capable of filtering with loglevel
# despite a level can be set for a handler. The level is checked
# by Logger. However, handler filters are checked at handler level.
class LevelFilter:
def __init__(self, level):
super().__init__()
self.level = level

def filter(self, record):
return record.levelno >= self.level
filt = LevelFilter(level)
cls._default_handler.addFilter(filt)

cls._root.removeHandler(cls._init_handler)
cls._init_handler.close()
del cls._init_handler
cls._init_handler = None

cls._default_handler.removeFilter(filt)

cls._root.addHandler(cls._default_handler)

def main(args=None):
_LogManager.init_basic_logger()
_LogManager.init_logger(args)

parser = make_parser()
args = parser.parse_args(args)

_LogManager.set_up_logger(args.loglevel)

if 'command' not in args:
parser.print_help()
return 1
Expand Down
2 changes: 1 addition & 1 deletion datumaro/datumaro/plugins/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ def transform_item(self, item):
log.debug("[%s]: item %s: "
"Mask conversion to polygons resulted in too "
"small polygons, which were discarded" % \
(self.NAME, item.id))
(self._get_name(__class__), item.id))
annotations.extend(polygons)
else:
annotations.append(ann)
Expand Down
28 changes: 28 additions & 0 deletions datumaro/tests/test_transforms.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging as log
import numpy as np

from unittest import TestCase
Expand Down Expand Up @@ -65,6 +66,33 @@ def __iter__(self):
actual = transforms.MasksToPolygons(SrcExtractor())
compare_datasets(self, DstExtractor(), actual)

def test_mask_to_polygons_small_polygons_message(self):
class SrcExtractor(Extractor):
def __iter__(self):
items = [
DatasetItem(id=1, image=np.zeros((5, 10, 3)),
annotations=[
Mask(np.array([
[0, 0, 0],
[0, 1, 0],
[0, 0, 0],
]),
),
]
),
]
return iter(items)

class DstExtractor(Extractor):
def __iter__(self):
return iter([ DatasetItem(id=1, image=np.zeros((5, 10, 3))), ])

with self.assertLogs(level=log.DEBUG) as logs:
actual = transforms.MasksToPolygons(SrcExtractor())

compare_datasets(self, DstExtractor(), actual)
self.assertRegex('\n'.join(logs.output), 'too small polygons')

def test_polygons_to_masks(self):
class SrcExtractor(Extractor):
def __iter__(self):
Expand Down

0 comments on commit dacef18

Please sign in to comment.