Example #1
0
 def test_url(self):
     """Test for url templating"""
     imagery = 'https://api.imagery.com/{z}/{x}/{y}.jpg'
     tile = '1-2-3'.split('-')
     filled = 'https://api.imagery.com/3/1/2.jpg'
     self.assertEqual(url(tile, imagery), filled)
Example #2
0
def preview(dest_folder, number, classes, imagery, ml_type, **kwargs):
    """Produce imagery examples for specified classes

    Parameters
    ------------
    dest_folder: str
        Folder to save labels and example tiles into
    number: int
        Number of preview images to download per class
    classes: list
        A list of classes for machine learning training. Each class is defined as a dict
        with two required properties:
          - name: class name
          - filter: A Mapbox GL Filter.
        See the README for more details
    imagery: str
        Imagery template to download satellite images from.
        Ex: http://a.tiles.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}.jpg?access_token=ACCESS_TOKEN
    ml_type: str
        Defines the type of machine learning. One of "classification", "object-detection", or "segmentation"
    **kwargs: dict
        Other properties from CLI config passed as keywords to other utility functions
    """
    # open labels file
    labels_file = op.join(dest_folder, 'labels.npz')
    tiles = np.load(labels_file)

    # create example tiles directory
    examples_dir = op.join(dest_folder, 'examples')
    if not op.isdir(examples_dir):
        makedirs(examples_dir)

    # find examples tiles for each class and download
    print('Writing example images to {}'.format(examples_dir))
    o = urlparse(imagery)
    _, image_format = op.splitext(o.path)
    for i, cl in enumerate(classes):
        # create class directory
        class_dir = op.join(dest_folder, 'examples', cl.get('name'))
        if not op.isdir(class_dir):
            makedirs(class_dir)

        class_tiles = [t for t in tiles.files if class_match(ml_type, tiles[t], i + 1)]
        class_tiles = class_tiles[:number]
        print('Downloading {} tiles for class {}'.format(len(class_tiles), cl.get('name')))
        for tile in class_tiles:
            r = requests.get(url(tile.split('-'), imagery))
            tile_img = op.join(dest_folder, 'examples', cl.get('name'),
                               '{}{}'.format(tile, image_format))
            open(tile_img, 'wb').write(r.content)
            if ml_type == 'object-detection':
                img = Image.open(tile_img)
                draw = ImageDraw.Draw(img)
                for box in tiles[tile]:
                    draw.rectangle(((box[0], box[1]), (box[2], box[3])), outline='red')
                img.save(tile_img)
            elif ml_type == 'segmentation':
                final = Image.new('RGB', (256, 256))
                img = Image.open(tile_img)
                mask = Image.fromarray(tiles[tile] * 255)
                final.paste(img, mask)
                final.save(tile_img)
Example #3
0
def download_images(dest_folder, classes, imagery, ml_type, background_ratio,
                    **kwargs):
    """Download satellite images specified by a URL and a label.npz file
    Parameters
    ------------
    dest_folder: str
        Folder to save labels, tiles, and final numpy arrays into
    classes: list
        A list of classes for machine learning training. Each class is defined as a dict
        with two required properties:
          - name: class name
          - filter: A Mapbox GL Filter.
        See the README for more details
    imagery: str
        Imagery template to download satellite images from.
        Ex: http://a.tiles.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}.jpg?access_token=ACCESS_TOKEN
    ml_type: str
        Defines the type of machine learning. One of "classification", "object-detection", or "segmentation"
    background_ratio: float
        Determines the number of background images to download in single class problems. Ex. A value
        of 1 will download an equal number of background images to class images.
    **kwargs: dict
        Other properties from CLI config passed as keywords to other utility functions
    """
    # open labels file
    labels_file = op.join(dest_folder, 'labels.npz')
    tiles = np.load(labels_file)

    # create tiles directory
    tiles_dir = op.join(dest_folder, 'tiles')
    if not op.isdir(tiles_dir):
        makedirs(tiles_dir)

    # find tiles which have any matching class
    def class_test(value):
        """Determine if a label matches a given class index"""
        if ml_type == 'object-detection':
            return len(value)
        elif ml_type == 'segmentation':
            return np.sum(value) > 0
        elif ml_type == 'classification':
            return value[0] == 0
        return None

    class_tiles = [tile for tile in tiles.files if class_test(tiles[tile])]

    # for classification problems with a single class, we also get background
    # tiles up to len(class_tiles) * config.get('background_ratio')
    background_tiles = []
    limit = len(class_tiles) * background_ratio
    if ml_type == 'classification' and len(classes) == 1:
        background_tiles_full = [
            tile for tile in tiles.files if tile not in class_tiles
        ]
        shuffle(background_tiles_full)
        background_tiles = background_tiles_full[:limit]

    # download tiles
    tiles = class_tiles + background_tiles
    print('Downloading {} tiles to {}'.format(len(tiles),
                                              op.join(dest_folder, 'tiles')))
    o = urlparse(imagery)
    _, image_format = op.splitext(o.path)
    for tile in tiles:
        r = requests.get(url(tile.split('-'), imagery))
        tile_img = op.join(dest_folder, 'tiles',
                           '{}{}'.format(tile, image_format))
        open(tile_img, 'wb').write(r.content)