-
Notifications
You must be signed in to change notification settings - Fork 42
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
[IO-1405][external] YoloV8 Segementation dataset support #643
Conversation
IO-1405 REQUEST: support Segmentation in the YOLO exports
Product Request from: Nathan Ascott Additional information |
@@ -0,0 +1,46 @@ | |||
from pathlib import Path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracted some normal YOLO functions out for common usage by YOLO and YOLO segementation
_save_class_index(class_index, output_dir) | ||
|
||
|
||
def _export_file(annotation_file: dt.AnnotationFile, class_index: ClassIndex, output_dir: Path) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These functions now in the shared helper file
|
||
|
||
def _build_txt(annotation_file: dt.AnnotationFile, class_index: ClassIndex) -> str: | ||
yolo_lines = [] | ||
for annotation in annotation_file.annotations: | ||
annotation_type = annotation.annotation_class.annotation_type | ||
|
||
if isinstance(annotation, dt.VideoAnnotation): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixes type error - possibly YOLO can support Video, but our usage of it in the exporter doesn't and never has.
|
||
logger = getLogger(__name__) | ||
|
||
CLOSE_VERTICES: bool = False # Set true if polygons need to be closed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are relatively confident that we don't need to close vertices on a polygon, but switching this constant to True
will make the exporter close vertices by adding the first coordinate at the end.
POLYGON = auto() | ||
|
||
|
||
def _build_text(annotation_file: AnnotationFile, class_index: ClassIndex) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extensive logging which largely only shows at DEBUG
level, so won't usually show to users, but they could opt to see. Allows for good diagnostics if this turns out not to work as intended.
|
||
try: | ||
# Create 8 coordinates for the x,y pairs of the 4 corners | ||
x1, y1, x2, y2, x3, y3, x4, y4, x5, y5 = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bounding box is just the original coordinate, followed by 3 offset by width, then height, then -width.
if "x" in annotation.data and "y" in annotation.data and "w" in annotation.data and "h" in annotation.data: | ||
annotation_type = YoloSegmentedAnnotationType.BOUNDING_BOX | ||
elif "points" in annotation.data: | ||
if isinstance(annotation.data["points"][0], list): | ||
logger.warn(f"Skipped annotation at index {annotation_index} because it's a complex polygon'") | ||
continue | ||
|
||
annotation_type = YoloSegmentedAnnotationType.POLYGON | ||
else: | ||
annotation_type = YoloSegmentedAnnotationType.UNKNOWN |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be useful to extract to a helper func, improves the readability then we can do something like:
annotation_type = get_annotation_type(annotation.data)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, agreed. In fact I only didn't because of the time frame. The original plan had a helper func for this, and separate predicate functions for handling bounding boxes and polygons
logger.debug(f"Exporting bounding box at index {annotation_index}.") | ||
|
||
try: | ||
# Create 8 coordinates for the x,y pairs of the 4 corners | ||
x1, y1, x2, y2, x3, y3, x4, y4, x5, y5 = ( | ||
data["x"], | ||
data["y"], | ||
(data["x"] + data["w"]), | ||
(data["y"] + data["h"]), | ||
(data["x"] + data["w"]), | ||
data["y"], | ||
data["x"], | ||
(data["y"] + data["h"]), | ||
data["x"], | ||
data["y"], | ||
) | ||
|
||
logger.debug( | ||
"Coordinates for bounding box: " | ||
f"({x1}, {y1}), ({x2}, {y2}), " | ||
f"({x3}, {y3}), ({x4}, {y4}), " | ||
f"({x5}, {y5})" # Unsure if we have to close this. | ||
) | ||
|
||
# Normalize the coordinates to a proportion of the image size | ||
n_x1 = normalise(x1, im_w) | ||
n_y1 = normalise(y1, im_h) | ||
n_x2 = normalise(x2, im_w) | ||
n_y2 = normalise(y2, im_h) | ||
n_x3 = normalise(x3, im_w) | ||
n_y3 = normalise(y3, im_h) | ||
n_x4 = normalise(x4, im_w) | ||
n_y4 = normalise(y4, im_h) | ||
n_x5 = normalise(x5, im_w) | ||
n_y5 = normalise(y5, im_w) | ||
|
||
logger.debug( | ||
"Normalized coordinates for bounding box: " | ||
f"({n_x1}, {n_y1}), ({n_x2}, {n_y2}), " | ||
f"({n_x3}, {n_y3}), ({n_x4}, {n_y4}), " | ||
f"({n_x5}, {n_y5})" | ||
) | ||
|
||
# Add the coordinates to the points list | ||
points.append(Point(x=n_x1, y=n_y1)) | ||
points.append(Point(x=n_x2, y=n_y2)) | ||
points.append(Point(x=n_x3, y=n_y3)) | ||
points.append(Point(x=n_x4, y=n_y4)) | ||
|
||
if CLOSE_VERTICES: | ||
points.append(Point(x=n_x5, y=n_y5)) | ||
|
||
except KeyError as exc: | ||
logger.warn( | ||
f"Skipped annotation at index {annotation_index} because an" | ||
"expected key was not found in the data.", | ||
exc_info=exc, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also would extract to helper to improve readability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, originally I did, but time was against me on this one
Problem
We don't support YoloV8 Segmentation
Solution
Have implemented YoloV8 Segmentation datasets.
Changelog
Added new Yolo segementation exporter
Added Yolo shared helpers
Added social test for the exporter