示例#1
0
 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)
示例#2
0
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)))
示例#3
0
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'])))
示例#4
0
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'))
示例#5
0
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'))
示例#6
0
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'])))