Skip to content

Cuboid annotation #678

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

Merged
merged 75 commits into from
Feb 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
330ee98
Cuboid feature
Aug 29, 2019
f2c376b
migration files
Aug 29, 2019
6981253
Refactored cuboidShape
Aug 30, 2019
be25775
Removed math.js dependency
Aug 30, 2019
bf61c7c
new cvat formatting with labelled points
HollowTube Sep 15, 2019
a3b867a
Added MIT License to js files that were missing it
HollowTube Sep 15, 2019
b727e03
Added simple constraints to the cuboids
HollowTube Sep 11, 2019
bfd2cf4
reverted commit for settings for vscode to hide local path
HollowTube Sep 15, 2019
6bc62df
fixed locking for cuboids
HollowTube Sep 15, 2019
8a4e336
fixed cuboid View when locked
HollowTube Sep 15, 2019
b929653
fixed occlusion view for cuboids
HollowTube Sep 15, 2019
2144724
Allow cuboid points to be outside the frame dimensions.
timbowl Aug 30, 2019
3f6c1d3
Added stricter constraints on cuboid edges.
HollowTube Sep 29, 2019
c1fb2d0
Slightly stricter restrictions for edge case
HollowTube Sep 30, 2019
357395c
Cleaned up unused imports
HollowTube Sep 30, 2019
559d265
removed dashed lines on cuboids
HollowTube Oct 4, 2019
936b956
Moved projection lines to settings tab
HollowTube Oct 13, 2019
a7da467
Fixed Cuboid shape buffer \
HollowTube Oct 16, 2019
219b265
Merge remote-tracking branch 'origin/develop' into cuboid-annotation
Oct 28, 2019
19574a4
Fix migrations (two 022 migrations after merge with the develop branch).
Oct 28, 2019
db81a22
Fix compatibility issues with auto segmentation.
Oct 28, 2019
454247d
Merge branch 'develop' into cuboid-annotation
nmanovic Nov 18, 2019
646f94c
Grab points and update control scheme
HollowTube Nov 24, 2019
ba82c0d
Merge branch 'cuboid-annotation' of github.com:algolux/cvat into grab…
HollowTube Nov 24, 2019
e40d7be
Greatly improved control scheme, fixed shape merging
HollowTube Nov 24, 2019
4ce6cda
Fixed slight visual bug when dragging faces
HollowTube Nov 28, 2019
7561218
Some optimizations
HollowTube Nov 28, 2019
2aa1aa0
Hiding the grab point on creation
HollowTube Nov 28, 2019
0d58a43
Fixed some cases where cuboid breaks
HollowTube Nov 28, 2019
af7deb1
Fixed upload for videos
HollowTube Nov 29, 2019
408d95b
Removed perspective effects
HollowTube Dec 12, 2019
56f3eb1
Made left back edge editable
HollowTube Dec 12, 2019
a0bae63
left back edge resizable
HollowTube Dec 15, 2019
a25c5b7
fix statistics bug
HollowTube Dec 15, 2019
c1be4f4
added toggles for the back edges
HollowTube Dec 15, 2019
4527701
Constraints for the back edges
HollowTube Dec 16, 2019
5f21bbe
Fix creation bug
HollowTube Dec 16, 2019
d441e20
Merge branch 'develop' into cuboid-annotation
HollowTube Dec 16, 2019
293ff5e
Tightened creation constraints
HollowTube Dec 16, 2019
2061c48
Fixing the code style
HollowTube Dec 19, 2019
f2b6ed1
updated message for invalid cuboids
HollowTube Dec 19, 2019
e29bdd3
Code style
HollowTube Dec 20, 2019
b46fd7e
More style fixes
HollowTube Dec 20, 2019
76c6f0a
Codacy fixes
Dec 23, 2019
81ba771
added shift control for edges
HollowTube Dec 26, 2019
7911a64
Merge remote-tracking branch 'origin/cuboid-annotation' into cuboid-a…
HollowTube Jan 2, 2020
e4a1127
Merge branch 'cvat/develop' into cuboid-annotation
HollowTube Jan 7, 2020
49076ae
More Codacy fixes
HollowTube Jan 9, 2020
7c4968e
More Codacy fixes
HollowTube Jan 15, 2020
4c1a4d6
Double arrows for cursor
HollowTube Jan 15, 2020
9c773e7
Merge branch 'cvat/develop' into cuboid-annotation
HollowTube Jan 15, 2020
f3a3c58
Fix Drag bug
HollowTube Jan 15, 2020
8b58f43
More Codacy fixes
HollowTube Jan 16, 2020
dbf0135
Fix double quotes
HollowTube Jan 16, 2020
89db2cd
Fix camel case
HollowTube Jan 16, 2020
2cba519
More camelcase fixes
HollowTube Jan 16, 2020
8131a12
Generic object sink fixes
HollowTube Jan 16, 2020
6af98d7
Various codacy fixes
HollowTube Jan 16, 2020
4bc949f
Codacy
HollowTube Jan 16, 2020
2aa6c2d
Double quotes
HollowTube Jan 16, 2020
02c400a
Fix migrations
HollowTube Jan 16, 2020
5872c72
Updated shape creation
HollowTube Jan 23, 2020
07ff78a
merged dev into cuboid + fix conflicts
HollowTube Jan 23, 2020
16fc5d8
Adjusted constraints
HollowTube Jan 23, 2020
826f5dc
Codacy fixes
HollowTube Jan 23, 2020
aea1664
Codacy fixes again
HollowTube Jan 23, 2020
e6d8176
Drawing cuboids from the top and bottom
HollowTube Jan 30, 2020
88c0d38
Codacy
HollowTube Jan 30, 2020
183e71d
Resetting perspective on cuboids
HollowTube Feb 10, 2020
fe3bd3b
Choosing orientation of cuboids.
HollowTube Feb 13, 2020
b6df5d1
Codacy fix
HollowTube Feb 14, 2020
0ca28a3
Merge branch 'cvat/develop' into cuboid-annotation
HollowTube Feb 14, 2020
104efd4
Merge cleanup
HollowTube Feb 14, 2020
9726165
revert vs-code settings
HollowTube Feb 20, 2020
15e59a1
Update settings.json
nmanovic Feb 20, 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
77 changes: 76 additions & 1 deletion cvat/apps/annotation/cvat.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ def open_points(self, points):
self.xmlgen.startElement("points", points)
self._level += 1

def open_cuboid(self, cuboid):
self._indent()
self.xmlgen.startElement("cuboid", cuboid)
self._level += 1

def add_attribute(self, attribute):
self._indent()
self.xmlgen.startElement("attribute", {"name": attribute["name"]})
Expand All @@ -145,6 +150,11 @@ def close_points(self):
self._indent()
self.xmlgen.endElement("points")

def close_cuboid(self):
self._level -= 1
self._indent()
self.xmlgen.endElement("cuboid")

def close_image(self):
self._level -= 1
self._indent()
Expand Down Expand Up @@ -191,6 +201,25 @@ def dump_as_cvat_annotation(file_object, annotations):
("xbr", "{:.2f}".format(shape.points[2])),
("ybr", "{:.2f}".format(shape.points[3]))
]))
elif shape.type == "cuboid":
dump_data.update(OrderedDict([
("xtl1", "{:.2f}".format(shape.points[0])),
("ytl1", "{:.2f}".format(shape.points[1])),
("xbl1", "{:.2f}".format(shape.points[2])),
("ybl1", "{:.2f}".format(shape.points[3])),
("xtr1", "{:.2f}".format(shape.points[4])),
("ytr1", "{:.2f}".format(shape.points[5])),
("xbr1", "{:.2f}".format(shape.points[6])),
("ybr1", "{:.2f}".format(shape.points[7])),
("xtl2", "{:.2f}".format(shape.points[8])),
("ytl2", "{:.2f}".format(shape.points[9])),
("xbl2", "{:.2f}".format(shape.points[10])),
("ybl2", "{:.2f}".format(shape.points[11])),
("xtr2", "{:.2f}".format(shape.points[12])),
("ytr2", "{:.2f}".format(shape.points[13])),
("xbr2", "{:.2f}".format(shape.points[14])),
("ybr2", "{:.2f}".format(shape.points[15]))
]))
else:
dump_data.update(OrderedDict([
("points", ';'.join((
Expand All @@ -206,6 +235,7 @@ def dump_as_cvat_annotation(file_object, annotations):
if shape.group:
dump_data['group_id'] = str(shape.group)


if shape.type == "rectangle":
dumper.open_box(dump_data)
elif shape.type == "polygon":
Expand All @@ -214,6 +244,8 @@ def dump_as_cvat_annotation(file_object, annotations):
dumper.open_polyline(dump_data)
elif shape.type == "points":
dumper.open_points(dump_data)
elif shape.type == "cuboid":
dumper.open_cuboid(dump_data)
else:
raise NotImplementedError("unknown shape type")

Expand All @@ -231,6 +263,8 @@ def dump_as_cvat_annotation(file_object, annotations):
dumper.close_polyline()
elif shape.type == "points":
dumper.close_points()
elif shape.type == "cuboid":
dumper.close_cuboid()
else:
raise NotImplementedError("unknown shape type")

Expand Down Expand Up @@ -268,6 +302,25 @@ def dump_track(idx, track):
("xbr", "{:.2f}".format(shape.points[2])),
("ybr", "{:.2f}".format(shape.points[3])),
]))
elif shape.type == "cuboid":
dump_data.update(OrderedDict([
("xtl1", "{:.2f}".format(shape.points[0])),
("ytl1", "{:.2f}".format(shape.points[1])),
("xbl1", "{:.2f}".format(shape.points[2])),
("ybl1", "{:.2f}".format(shape.points[3])),
("xtr1", "{:.2f}".format(shape.points[4])),
("ytr1", "{:.2f}".format(shape.points[5])),
("xbr1", "{:.2f}".format(shape.points[6])),
("ybr1", "{:.2f}".format(shape.points[7])),
("xtl2", "{:.2f}".format(shape.points[8])),
("ytl2", "{:.2f}".format(shape.points[9])),
("xbl2", "{:.2f}".format(shape.points[10])),
("ybl2", "{:.2f}".format(shape.points[11])),
("xtr2", "{:.2f}".format(shape.points[12])),
("ytr2", "{:.2f}".format(shape.points[13])),
("xbr2", "{:.2f}".format(shape.points[14])),
("ybr2", "{:.2f}".format(shape.points[15]))
]))
else:
dump_data.update(OrderedDict([
("points", ';'.join(['{:.2f},{:.2f}'.format(x, y)
Expand All @@ -285,6 +338,8 @@ def dump_track(idx, track):
dumper.open_polyline(dump_data)
elif shape.type == "points":
dumper.open_points(dump_data)
elif shape.type == "cuboid":
dumper.open_cuboid(dump_data)
else:
raise NotImplementedError("unknown shape type")

Expand All @@ -302,6 +357,8 @@ def dump_track(idx, track):
dumper.close_polyline()
elif shape.type == "points":
dumper.close_points()
elif shape.type == "cuboid":
dumper.close_cuboid()
else:
raise NotImplementedError("unknown shape type")
dumper.close_track()
Expand Down Expand Up @@ -347,7 +404,7 @@ def load(file_object, annotations):
context = iter(context)
ev, _ = next(context)

supported_shapes = ('box', 'polygon', 'polyline', 'points')
supported_shapes = ('box', 'polygon', 'polyline', 'points', 'cuboid')

track = None
shape = None
Expand Down Expand Up @@ -393,6 +450,24 @@ def load(file_object, annotations):
shape['points'].append(el.attrib['ytl'])
shape['points'].append(el.attrib['xbr'])
shape['points'].append(el.attrib['ybr'])
elif el.tag == 'cuboid':
shape['points'].append(el.attrib['xtl1'])
shape['points'].append(el.attrib['ytl1'])
shape['points'].append(el.attrib['xbl1'])
shape['points'].append(el.attrib['ybl1'])
shape['points'].append(el.attrib['xtr1'])
shape['points'].append(el.attrib['ytr1'])
shape['points'].append(el.attrib['xbr1'])
shape['points'].append(el.attrib['ybr1'])

shape['points'].append(el.attrib['xtl2'])
shape['points'].append(el.attrib['ytl2'])
shape['points'].append(el.attrib['xbl2'])
shape['points'].append(el.attrib['ybl2'])
shape['points'].append(el.attrib['xtr2'])
shape['points'].append(el.attrib['ytr2'])
shape['points'].append(el.attrib['xbr2'])
shape['points'].append(el.attrib['ybr2'])
else:
for pair in el.attrib['points'].split(';'):
shape['points'].extend(map(float, pair.split(',')))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ window.addEventListener('DOMContentLoaded', () => {
get: () => instance._defaultType,
set: (type) => {
if (!['box', 'box_by_4_points', 'points', 'polygon',
'polyline', 'auto_segmentation'].includes(type)) {
'polyline', 'auto_segmentation', 'cuboid'].includes(type)) {
throw Error(`Unknown shape type found ${type}`);
}
instance._defaultType = type;
Expand Down
1 change: 1 addition & 0 deletions cvat/apps/engine/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ class ShapeType(str, Enum):
POLYGON = 'polygon' # (x0, y0, ..., xn, yn)
POLYLINE = 'polyline' # (x0, y0, ..., xn, yn)
POINTS = 'points' # (x0, y0, ..., xn, yn)
CUBOID = 'cuboid'

@classmethod
def choices(self):
Expand Down
2 changes: 1 addition & 1 deletion cvat/apps/engine/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ class ShapeSerializer(serializers.Serializer):
occluded = serializers.BooleanField()
z_order = serializers.IntegerField(default=0)
points = serializers.ListField(
child=serializers.FloatField(min_value=0),
child=serializers.FloatField(),
allow_empty=False,
)

Expand Down
27 changes: 23 additions & 4 deletions cvat/apps/engine/static/engine/js/annotationParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ class AnnotationParser {
const imWidth = this._im_meta[frame].width;
const imHeight = this._im_meta[frame].height;

let xtl = +box.getAttribute('xtl');
let ytl = +box.getAttribute('ytl');
let xbr = +box.getAttribute('xbr');
let ybr = +box.getAttribute('ybr');
const xtl = +box.getAttribute("xtl");
const ytl = +box.getAttribute("ytl");
const xbr = +box.getAttribute("xbr");
const ybr = +box.getAttribute("ybr");

if (xtl < 0 || ytl < 0 || xbr < 0 || ybr < 0
|| xtl > imWidth || ytl > imHeight || xbr > imWidth || ybr > imHeight) {
Expand Down Expand Up @@ -155,6 +155,7 @@ class AnnotationParser {
polygons: [],
polylines: [],
points: [],
cuboids: [],
};

const tracks = xml.getElementsByTagName('track');
Expand All @@ -163,12 +164,14 @@ class AnnotationParser {
polygon: this._getShapeFromPath('polygon', tracks),
polyline: this._getShapeFromPath('polyline', tracks),
points: this._getShapeFromPath('points', tracks),
cuboid: this._getShapeFromPath('cuboid', tracks),
};
const shapeTarget = {
box: 'boxes',
polygon: 'polygons',
polyline: 'polylines',
points: 'points',
cuboid: 'cuboids',
};

const images = xml.getElementsByTagName('image');
Expand All @@ -194,6 +197,10 @@ class AnnotationParser {
points.setAttribute('frame', frame);
parsed.points.push(points);
}
for (const cuboid of image.getElementsByTagName('cuboid')) {
cuboid.setAttribute('frame', frame);
parsed.cuboid.push(cuboid);
}
}

for (const shapeType in parsed) {
Expand Down Expand Up @@ -224,6 +231,18 @@ class AnnotationParser {
occluded,
points,
});
} else if (shapeType === 'cuboid') {
const [points, occluded, zOrder] = this._getPolyPosition(shape, frame);
data[shapeTarget[shapeType]].push({
label_id: labelId,
group: +group,
attributes: attributeList,
type: 'cuboid',
z_order: zOrder,
frame,
occluded,
points,
});
} else {
const [points, occluded, zOrder] = this._getPolyPosition(shape, frame);
data[shapeTarget[shapeType]].push({
Expand Down
6 changes: 6 additions & 0 deletions cvat/apps/engine/static/engine/js/annotationSaver.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/*
* Copyright (C) 2018 Intel Corporation
*
* SPDX-License-Identifier: MIT
*/

/* exported buildAnnotationSaver */

/* global
Expand Down
8 changes: 7 additions & 1 deletion cvat/apps/engine/static/engine/js/annotationUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@ function setupMenu(job, task, shapeCollectionModel,
<td> ${byLabelsStat[labelId].polylines.interpolation} </td>
<td> ${byLabelsStat[labelId].points.annotation} </td>
<td> ${byLabelsStat[labelId].points.interpolation} </td>
<td> ${byLabelsStat[labelId].cuboids.annotation} </td>
<td> ${byLabelsStat[labelId].cuboids.interpolation} </td>
<td> ${byLabelsStat[labelId].manually} </td>
<td> ${byLabelsStat[labelId].interpolated} </td>
<td class="semiBold"> ${byLabelsStat[labelId].total} </td>
Expand All @@ -312,6 +314,8 @@ function setupMenu(job, task, shapeCollectionModel,
<td> ${totalStat.polylines.interpolation} </td>
<td> ${totalStat.points.annotation} </td>
<td> ${totalStat.points.interpolation} </td>
<td> ${totalStat.cuboids.annotation} </td>
<td> ${totalStat.cuboids.interpolation} </td>
<td> ${totalStat.manually} </td>
<td> ${totalStat.interpolated} </td>
<td> ${totalStat.total} </td>
Expand Down Expand Up @@ -670,13 +674,15 @@ function buildAnnotationUI(jobData, taskData, imageMetaData, annotationData, ann
'track count': totalStat.boxes.annotation + totalStat.boxes.interpolation
+ totalStat.polygons.annotation + totalStat.polygons.interpolation
+ totalStat.polylines.annotation + totalStat.polylines.interpolation
+ totalStat.points.annotation + totalStat.points.interpolation,
+ totalStat.points.annotation + totalStat.points.interpolation
+ totalStat.cuboids.annotation + totalStat.cuboids.interpolation,
'frame count': window.cvat.player.frames.stop - window.cvat.player.frames.start + 1,
'object count': totalStat.total,
'box count': totalStat.boxes.annotation + totalStat.boxes.interpolation,
'polygon count': totalStat.polygons.annotation + totalStat.polygons.interpolation,
'polyline count': totalStat.polylines.annotation + totalStat.polylines.interpolation,
'points count': totalStat.points.annotation + totalStat.points.interpolation,
'cuboid count': totalStat.cuboids.annotation + totalStat.cuboids.interpolation,
});
loadJobEvent.close();

Expand Down
Loading