def _create_pascal_writer(self): """ Create an instance of pascal writer.""" return PascalWriter( path=self._image_path, width=self._image_width, height=self._image_height, database=self._project_name)
def write_label( # pylint: disable-msg=too-many-arguments label_id: str, image_url: str, labels: Dict[str, Any], label_format: str, images_output_dir: str, annotations_output_dir: str): """Writes a single Pascal VOC formatted image and label pair to disk. Args: label_id: ID for the instance to write image_url: URL to download image file from labels: Labelbox formatted labels to use for generating annotation label_format: Format of the labeled data. Valid options are: "WKT" and "XY", default is "XY". annotations_output_dir: File path of directory to write Pascal VOC annotation files. images_output_dir: File path of directory to write images. """ # Download image and save it response = requests.get(image_url, stream=True, timeout=10.0) response.raw.decode_content = True image = Image.open(response.raw) image_fqn = os.path.join( images_output_dir, '{img_id}.{ext}'.format(img_id=label_id, ext=image.format.lower())) image.save(image_fqn, format=image.format) # generate image annotation in Pascal VOC width, height = image.size xml_writer = PascalWriter(image_fqn, width, height) # remove classification labels (Skip, etc...) if not callable(getattr(labels, 'keys', None)): # skip if no categories (e.g. "Skip") return # convert label to Pascal VOC format for category_name, paths in labels.items(): if label_format == 'WKT': xml_writer = _add_pascal_object_from_wkt(xml_writer, wkt_data=paths, label=category_name) elif label_format == 'XY': xml_writer = _add_pascal_object_from_xy(xml_writer, polygons=paths, label=category_name) else: exc = UnknownFormatError(label_format=label_format) logging.exception(exc.message) raise exc # write Pascal VOC xml annotation for image xml_writer.save( os.path.join(annotations_output_dir, '{}.xml'.format(label_id)))
def from_json(labeled_data, ann_output_dir, images_output_dir, label_format='WKT'): """Convert Labelbox JSON export to Pascal VOC format. Args: labeled_data (str): File path to Labelbox JSON export of label data. ann_output_dir (str): File path of directory to write Pascal VOC annotation files. 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: ann_output_dir = os.path.abspath(ann_output_dir) assert os.path.isdir(ann_output_dir) except AssertionError as e: logging.exception('Annotation output directory does not exist') return None # read labelbox JSON output with open(labeled_data, 'r') as f: lines = f.readlines() label_data = json.loads(lines[0]) for data in label_data: # Download image and save it try: response = requests.get(data['Labeled Data'], stream=True) except requests.exceptions.MissingSchema as e: logging.exception(('"Labeled Data" field must be a URL. ' 'Support for local files coming soon')) continue except requests.exceptions.ConnectionError as e: logging.exception('Failed to fetch image from {}'.format( data['Labeled Data'])) continue response.raw.decode_content = True im = Image.open(response.raw) image_name = ('{img_id}.{ext}'.format(img_id=data['ID'], ext=im.format.lower())) image_fqn = os.path.join(images_output_dir, image_name) im.save(image_fqn, format=im.format) # generate image annotation in Pascal VOC width, height = im.size xml_writer = PascalWriter(image_fqn, width, height) # convert WKT multipolygon to Pascal VOC format for cat in data['Label'].keys(): if label_format == 'WKT': xml_writer = add_pascal_object_from_wkt( xml_writer, img_height=height, wkt_data=data['Label'][cat], label=cat) elif label_format == 'XY': xml_writer = add_pascal_object_from_xy(xml_writer, img_height=height, data=data['Label'][cat], label=cat) else: e = UnknownFormatError(label_format=label_format) print(e.message) raise e # write Pascal VOC xml annotation for image xml_writer.save( os.path.join(ann_output_dir, '{}.xml'.format(data['ID'])))
def test_1(results_dir): pascal_writer = PascalWriter('test-image.png', 100, 100) pascal_writer.addObject(name='triangle', xy_coords=[5, 5, 95, 5, 50, 95]) pascal_writer.save( os.path.join(results_dir, 'test-annotation-triangle.xml'))
def test_2(results_dir): pascal_writer = PascalWriter('test-image.png', 100, 100) pascal_writer.addObject(name='bndbox', xy_coords=[5, 5, 95, 5, 95, 95, 5, 95]) pascal_writer.save(os.path.join(results_dir, 'test-annotation-bndbox.xml'))
def from_json(labeled_data, ann_output_dir, images_output_dir): """Convert Labelbox JSON export to Pascal VOC format. Args: labeled_data (str): File path to Labelbox JSON export of label data. ann_output_dir (str): File path of directory to write Pascal VOC annotation files. images_output_dir (str): File path of directory to write images. 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: ann_output_dir = os.path.abspath(ann_output_dir) assert os.path.isdir(ann_output_dir) except AssertionError as e: logging.exception('Annotation output directory does not exist') return None # read labelbox JSON output with open(labeled_data, 'r') as f: lines = f.readlines() label_data = json.loads(lines[0]) for data in label_data: # Download image and save it try: response = requests.get(data['Labeled Data'], stream=True) except requests.exceptions.MissingSchema as e: logging.exception(('"Labeled Data" field must be a URL. ' 'Support for local files coming soon')) continue except requests.exceptions.ConnectionError as e: logging.exception('Failed to fetch image from {}' .format(data['Labeled Data'])) continue response.raw.decode_content = True im = Image.open(response.raw) image_name = ('{img_id}.{ext}' .format(img_id=data['ID'], ext=im.format.lower())) image_fqn = os.path.join(images_output_dir, image_name) im.save(image_fqn, format=im.format) # generate image annotation in Pascal VOC width, height = im.size xml_writer = PascalWriter(image_fqn, width, height) # convert WKT multipolygon to Pascal VOC format for cat in data['Label'].keys(): multipolygon = wkt.loads(data['Label'][cat]) for m in multipolygon: xy_coords = [] for x, y in m.exterior.coords: xy_coords.extend([x, height-y]) # remove last polygon if it is identical to first point if xy_coords[-2:] == xy_coords[:2]: xy_coords = xy_coords[:-2] xml_writer.addObject(name=cat, xy_coords=xy_coords) # write Pascal VOC xml annotation for image xml_writer.save(os.path.join(ann_output_dir, '{}.xml'.format(data['ID'])))