Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion labelbox/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"The Labelbox python package."

__version__ = '0.0.6'
__version__ = '0.0.7'
15 changes: 10 additions & 5 deletions labelbox/exporters/coco_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
from labelbox.exceptions import UnknownFormatError


LOGGER = logging.getLogger(__name__)


def from_json(labeled_data, coco_output, label_format='WKT'):
"Writes labelbox JSON export into MS COCO format."
# read labelbox JSON output
Expand All @@ -29,10 +32,10 @@ def from_json(labeled_data, coco_output, label_format='WKT'):
try:
add_label(coco, data['ID'], data['Labeled Data'], data['Label'], label_format)
except requests.exceptions.MissingSchema as exc:
logging.exception(exc)
LOGGER.warning(exc)
continue
except requests.exceptions.ConnectionError:
logging.exception('Failed to fetch image from %s', data['Labeled Data'])
LOGGER.warning('Failed to fetch image from %s, skipping', data['Labeled Data'])
continue

with open(coco_output, 'w+') as file_handle:
Expand Down Expand Up @@ -155,18 +158,20 @@ def _get_polygons(label_format, label_data):
xy_list = xy_list['geometry']

# V2 and V3
assert isinstance(xy_list, list), \
'Expected list in "geometry" key but got {}'.format(xy_list)
if not isinstance(xy_list, list):
LOGGER.warning('Could not get an point list to construct polygon, skipping')
continue
else: # V2, or non-list
if not isinstance(xy_list, list) or not xy_list or 'x' not in xy_list[0]:
# skip non xy lists
LOGGER.warning('Could not get an point list to construct polygon, skipping')
continue

if len(xy_list) > 2: # need at least 3 points to make a polygon
polygons.append(Polygon(map(lambda p: (p['x'], p['y']), xy_list)))
else:
exc = UnknownFormatError(label_format=label_format)
logging.exception(exc.message)
LOGGER.exception(exc.message)
raise exc

return polygons
18 changes: 9 additions & 9 deletions labelbox/exporters/voc_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
from labelbox.exporters.pascal_voc_writer import Writer as PascalWriter


LOGGER = logging.getLogger(__name__)


def from_json(labeled_data, annotations_output_dir, images_output_dir,
label_format='WKT'):
"""Convert Labelbox JSON export to Pascal VOC format.
Expand All @@ -26,18 +29,15 @@ def from_json(labeled_data, annotations_output_dir, images_output_dir,
images_output_dir (str): File path of directory to write images.
label_format (str): Format of the labeled data.
Valid options are: "WKT" and "XY", default is "WKT".

Todo:
* Add functionality to allow use of local copy of an image instead of
downloading it each time.
"""

# make sure annotation output directory is valid
try:
annotations_output_dir = os.path.abspath(annotations_output_dir)
assert os.path.isdir(annotations_output_dir)
except AssertionError:
logging.exception('Annotation output directory does not exist')
except AssertionError as exc:
LOGGER.exception('Annotation output directory does not exist, please create it first.')
raise exc

# read labelbox JSON output
with open(labeled_data, 'r') as file_handle:
Expand All @@ -55,10 +55,10 @@ def from_json(labeled_data, annotations_output_dir, images_output_dir,
annotations_output_dir)

except requests.exceptions.MissingSchema as exc:
logging.exception(exc)
LOGGER.warning(exc)
continue
except requests.exceptions.ConnectionError:
logging.exception('Failed to fetch image from %s', data['Labeled Data'])
LOGGER.warning('Failed to fetch image from %s, skipping', data['Labeled Data'])
continue


Expand Down Expand Up @@ -141,7 +141,7 @@ def _add_pascal_object_from_xy(xml_writer, img_height, polygons, label):
polygon = polygon['geometry']
if not isinstance(polygon, list) \
or not all(map(lambda p: 'x' in p and 'y' in p, polygon)):
# couldn't make a list of points, give up
LOGGER.warning('Could not get an point list to construct polygon, skipping')
return xml_writer

xy_coords = []
Expand Down
6 changes: 4 additions & 2 deletions labelbox/lbx.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import numpy as np
from PIL import Image

LOGGER = logging.getLogger(__name__)

# NOTE: image-segmentation front-end requires background pixels to be white to
# render them transparent
BACKGROUND_RGBA = np.array([255, 255, 255, 255], dtype=np.uint8)
Expand Down Expand Up @@ -92,9 +94,9 @@ def _color_to_key(color):
offset += 4
count = 0
except KeyError as exc:
logging.error('Could not find color %s in colormap', pixel_words[i])
LOGGER.error('Could not find color %s in colormap', pixel_words[i])
if np.all(pixel_words[i] == np.array([0, 0, 0, 0])):
logging.error('Did you remember to set background pixels to `BACKGROUND_RGBA`?')
LOGGER.error('Did you remember to set background pixels to `BACKGROUND_RGBA`?')
raise exc

# write header
Expand Down
8 changes: 8 additions & 0 deletions tests/test_exporters.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ def test_empty_skipped(self, tmpfile, datadir):
labeled_data = datadir.join('empty_skipped.json')
lb2co.from_json(labeled_data=labeled_data, coco_output=tmpfile)

def test_non_polygons(self, tmpfile, datadir):
labeled_data = datadir.join('non_polygon.json')
lb2co.from_json(labeled_data=labeled_data, coco_output=tmpfile, label_format='XY')


class TestVocExporter(object):
def test_wkt_1(self, tmpdir, datadir):
Expand Down Expand Up @@ -85,3 +89,7 @@ def test_bad_label_format(self, tmpdir, datadir):
labeled_data = datadir.join('labelbox_xy_1.json')
with pytest.raises(lb2pa.UnknownFormatError):
lb2pa.from_json(labeled_data, tmpdir, tmpdir, label_format='INVALID')

def test_non_polygons(self, tmpdir, datadir):
labeled_data = datadir.join('non_polygon.json')
lb2pa.from_json(labeled_data, tmpdir, tmpdir, label_format='XY')
1 change: 1 addition & 0 deletions tests/test_exporters/non_polygon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"ID":"cjlmqp9dnw28w0771zeasfqie","Labeled Data":"https://storage.googleapis.com/labelbox-example-datasets/tesla/2018-Tesla-Model-3-front-three-quarter-in-motion.jpg","Label":{"box":[{"geometry":{"x":1259,"y":1411}}],"select_the_cup_models":["model_3"]},"Created By":"feynman@labelbox.com","Project Name":"seg tesla v3","Created At":"2018-09-03T20:30:51.000Z","Seconds to Label":3.111,"External ID":null,"Agreement":null,"Dataset Name":"Example Tesla Dataset","Reviews":[],"View Label":"https://image-segmentation-v3.labelbox.com?project=cjl8ss8h83bep0715vux0nugp&label=cjlmqp9dnw28w0771zeasfqie"}]