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

Move annotation formats to dataset manager #1256

Merged
merged 28 commits into from
Mar 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
530ce17
Move formats to dataset manager
zhiltsov-max Mar 12, 2020
38318a4
Unify datataset export and anno export implementations
zhiltsov-max Mar 12, 2020
ce4a8c4
Merge branch 'develop' into zm/merge-anno-and-dm
zhiltsov-max Mar 20, 2020
f459afb
Add track_id to TrackedShape, export tracked shapes
zhiltsov-max Mar 23, 2020
041889e
Replace MOT format
zhiltsov-max Mar 23, 2020
23085bc
Replace LabelMe format
zhiltsov-max Mar 23, 2020
493be2a
Add new formats to dm
zhiltsov-max Mar 23, 2020
867f8b9
Add dm tests
zhiltsov-max Mar 24, 2020
6b40c12
Extend TrackedShape
zhiltsov-max Mar 25, 2020
5ee72e1
Enable dm test in CI
zhiltsov-max Mar 25, 2020
b86386e
Fix tests
zhiltsov-max Mar 25, 2020
04b77d9
Add import
zhiltsov-max Mar 25, 2020
a96b063
Fix tests
zhiltsov-max Mar 25, 2020
93fc0aa
Fix mot track ids
zhiltsov-max Mar 25, 2020
872b25e
Fix mot format
zhiltsov-max Mar 25, 2020
0acfc6c
Update attribute logic in labelme tests
zhiltsov-max Mar 25, 2020
5030c5d
Use common code in yolo
zhiltsov-max Mar 26, 2020
3701187
Put datumaro in path in settings
zhiltsov-max Mar 26, 2020
875c701
Expect labels file in MOT next to annotations file
zhiltsov-max Mar 26, 2020
b316bb0
Add MOT format description
zhiltsov-max Mar 26, 2020
fba95df
Add import
zhiltsov-max Mar 26, 2020
b67f7c4
Add labelme format description
zhiltsov-max Mar 26, 2020
5ab7937
Linter fix
zhiltsov-max Mar 26, 2020
f08652d
Linter fix2
zhiltsov-max Mar 26, 2020
0df9bc4
Compare attributes ordered
zhiltsov-max Mar 26, 2020
f754641
Update docs
zhiltsov-max Mar 27, 2020
216a8db
Merge branch 'develop' into zm/merge-anno-and-dm
zhiltsov-max Mar 30, 2020
9bd00c6
Update tests
zhiltsov-max Mar 30, 2020
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 .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ before_script:

script:
- docker-compose -f docker-compose.yml -f docker-compose.ci.yml run cvat_ci /bin/bash -c 'python3 manage.py test cvat/apps utils/cli'
- docker-compose -f docker-compose.yml -f docker-compose.ci.yml run cvat_ci /bin/bash -c 'python3 manage.py test --pattern="_tests.py" cvat/apps/dataset_manager'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the line above doesn't work to find tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests for the dataset manager app. conflict with tests for the git app., they are meant not to be executed in a single suite. This is done by naming tests for dm in a way that thay are not found automatically in the first line.

- docker-compose -f docker-compose.yml -f docker-compose.ci.yml run cvat_ci /bin/bash -c 'python3 manage.py test datumaro/'
- docker-compose -f docker-compose.yml -f docker-compose.ci.yml run cvat_ci /bin/bash -c 'cd cvat-data && npm install && cd ../cvat-core && npm install && npm run test && npm run coveralls'
71 changes: 66 additions & 5 deletions cvat/apps/annotation/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<!--lint disable list-item-indent-->
<!--lint disable no-duplicate-headings-->
## Description

The purpose of this application is to add support for multiple annotation formats for CVAT.
Expand Down Expand Up @@ -525,10 +527,10 @@ python create_pascal_tf_record.py --data_dir <path to VOCdevkit> --set train --y
│   └── Segmentation/
│   └── default.txt # list of image names without extension
├── SegmentationClass/ # merged class masks
│   ── image1.png
│   ── image1.png
│   └── image2.png
└── SegmentationObject/ # merged instance masks
── image1.png
── image1.png
└── image2.png
```
Mask is a png image with several (RGB) channels where each pixel has own color which corresponds to a label.
Expand Down Expand Up @@ -557,11 +559,70 @@ python create_pascal_tf_record.py --data_dir <path to VOCdevkit> --set train --y
│   └── Segmentation/
│   └── <any_subset_name>.txt
├── SegmentationClass/
│   ── image1.png
│   ── image1.png
│   └── image2.png
└── SegmentationObject/
── image.png
── image1.png
└── image2.png
```
- supported shapes: Polygons
- additional comments: the CVAT task should be created with the full label set that may be in the annotation files
- additional comments: the CVAT task should be created with the full label set that may be in the annotation files

### [MOT sequence](https://arxiv.org/pdf/1906.04567.pdf)
#### Dumper
- downloaded file: a zip archive of the following structure:
```bash
taskname.zip/
├── img1/
| ├── imgage1.jpg
| └── imgage2.jpg
└── gt/
├── labels.txt
└── gt.txt

# labels.txt
cat
dog
person
...

# gt.txt
# frame_id, track_id, x, y, w, h, "not ignored", class_id, visibility, <skipped>
1,1,1363,569,103,241,1,1,0.86014
...

```
- supported annotations: Rectangle shapes and tracks
- supported attributes: `visibility` (number), `ignored` (checkbox)

#### Loader
- uploaded file: a zip archive of the structure above or:
```bash
taskname.zip/
├── labels.txt # optional, mandatory for non-official labels
└── gt.txt
```
- supported annotations: Rectangle tracks

### [LabelMe](http://labelme.csail.mit.edu/Release3.0)
#### Dumper
- downloaded file: a zip archive of the following structure:
```bash
taskname.zip/
├── img1.jpg
└── img1.xml
```
- supported annotations: Rectangles, Polygons (with attributes)

#### Loader
- uploaded file: a zip archive of the following structure:
```bash
taskname.zip/
├── Masks/
| ├── img1_mask1.png
| └── img1_mask2.png
├── img1.xml
├── img2.xml
└── img3.xml
```
- supported annotations: Rectangles, Polygons, Masks (as polygons)
22 changes: 16 additions & 6 deletions cvat/apps/annotation/annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ class Annotation:
Attribute = namedtuple('Attribute', 'name, value')
LabeledShape = namedtuple('LabeledShape', 'type, frame, label, points, occluded, attributes, group, z_order')
LabeledShape.__new__.__defaults__ = (0, 0)
TrackedShape = namedtuple('TrackedShape', 'type, points, occluded, frame, attributes, outside, keyframe, z_order')
TrackedShape.__new__.__defaults__ = (0, )
TrackedShape = namedtuple('TrackedShape', 'type, frame, points, occluded, outside, keyframe, attributes, group, z_order, label, track_id')
TrackedShape.__new__.__defaults__ = (0, 0, None, 0)
Track = namedtuple('Track', 'label, group, shapes')
Tag = namedtuple('Tag', 'frame, label, attributes, group')
Tag.__new__.__defaults__ = (0, )
Expand Down Expand Up @@ -272,11 +272,14 @@ def _export_tracked_shape(self, shape):
return Annotation.TrackedShape(
type=shape["type"],
frame=self._db_task.data.start_frame + shape["frame"] * self._frame_step,
label=self._get_label_name(shape["label_id"]),
points=shape["points"],
occluded=shape["occluded"],
z_order=shape.get("z_order", 0),
group=shape.get("group", 0),
outside=shape.get("outside", False),
keyframe=shape.get("keyframe", True),
z_order=shape["z_order"],
track_id=shape["track_id"],
attributes=self._export_attributes(shape["attributes"]),
)

Expand Down Expand Up @@ -318,7 +321,11 @@ def _get_frame(annotations, shape):
annotations = {}
data_manager = DataManager(self._annotation_ir)
for shape in sorted(data_manager.to_shapes(self._db_task.data.size), key=lambda shape: shape.get("z_order", 0)):
_get_frame(annotations, shape).labeled_shapes.append(self._export_labeled_shape(shape))
if 'track_id' in shape:
exported_shape = self._export_tracked_shape(shape)
else:
exported_shape = self._export_labeled_shape(shape)
_get_frame(annotations, shape).labeled_shapes.append(exported_shape)

for tag in self._annotation_ir.tags:
_get_frame(annotations, tag).tags.append(self._export_tag(tag))
Expand All @@ -332,14 +339,17 @@ def shapes(self):

@property
def tracks(self):
for track in self._annotation_ir.tracks:
for idx, track in enumerate(self._annotation_ir.tracks):
tracked_shapes = TrackManager.get_interpolated_shapes(track, 0, self._db_task.data.size)
for tracked_shape in tracked_shapes:
tracked_shape["attributes"] += track["attributes"]
tracked_shape["track_id"] = idx
tracked_shape["group"] = track["group"]
tracked_shape["label_id"] = track["label_id"]

yield Annotation.Track(
label=self._get_label_name(track["label_id"]),
group=track['group'],
group=track["group"],
shapes=[self._export_tracked_shape(shape) for shape in tracked_shapes],
)

Expand Down
6 changes: 2 additions & 4 deletions cvat/apps/annotation/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,10 @@

def register_format(format_file):
source_code = open(format_file, 'r').read()
global_vars = {
"__builtins__": {},
}
global_vars = {}
exec(source_code, global_vars)
if "format_spec" not in global_vars or not isinstance(global_vars["format_spec"], dict):
raise Exception("Could not find \'format_spec\' definition in format file specification")
raise Exception("Could not find 'format_spec' definition in format file specification")

format_spec = deepcopy(global_vars["format_spec"])
format_spec["handler_file"] = File(open(format_file))
Expand Down
Loading