Esempio n. 1
0
def test_composite_subtiles_real(real_tiles_green_mask, real_tiles_red_mask,
                                 color_red, color_green,
                                 real_stitched_with_gamma):
    '''Ensure 1024 x 1024 image matches image rendered without tiling.'''

    expected = real_stitched_with_gamma

    inputs = []

    for y in range(0, 4):
        for x in range(0, 4):
            inputs += [{
                'min': 0.006,
                'max': 0.024,
                'grid': (y, x),
                'image': real_tiles_green_mask[y][x],
                'color': color_green
            }, {
                'min': 0,
                'max': 1,
                'grid': (y, x),
                'image': real_tiles_red_mask[y][x],
                'color': color_red
            }]

    result = composite_subtiles(inputs, (256, 256), (0, 0), (1024, 1024))

    np.testing.assert_allclose(expected, np.uint8(255 * result))
Esempio n. 2
0
def test_composite_subtiles_nonsquare(hd_tiles_green_mask, color_green,
                                      hd_stitched):
    '''Ensure non-square image is stitched correctly with square tiles.'''

    expected = ski.adjust_gamma(hd_stitched, 1 / 2.2)

    inputs = []

    for y in range(0, 2):
        for x in range(0, 2):
            inputs += [{
                'min': 0,
                'max': 1,
                'grid': (y, x),
                'image': hd_tiles_green_mask[y][x],
                'color': color_green
            }]

    result = composite_subtiles(inputs, (1024, 1024), (0, 0), (1080, 1920))

    np.testing.assert_allclose(expected, result)
Esempio n. 3
0
    def render_region(self, event, context):
        from minerva_db.sql.api import Client as db_client
        self._open_session()
        client = db_client(self.session)
        '''Render the specified region with the given settings'''

        uuid = event_path_param(event, 'uuid')
        validate_uuid(uuid)
        self._has_image_permission(self.user_uuid, uuid, 'Read')

        x = int(event_path_param(event, 'x'))
        y = int(event_path_param(event, 'y'))
        width = int(event_path_param(event, 'width'))
        height = int(event_path_param(event, 'height'))
        z = int(event_path_param(event, 'z'))
        t = int(event_path_param(event, 't'))

        # Split the channels path parameters
        channel_path_params = event['pathParameters']['channels'].split('/')

        # Read the path parameter for the channels and convert
        channels = [
            _parse_channel_params(param) for param in channel_path_params
        ]

        # Read the optional query parameters for output shape
        output_width = event['queryStringParameters'].get('output-width')
        output_height = event['queryStringParameters'].get('output-height')
        output_width = int(output_width) if output_width is not None else None
        output_height = (int(output_height)
                         if output_height is not None else None)

        # Set prefer_higher_resolution from query parameter
        prefer_higher_resolution = (
            event['queryStringParameters'].get('prefer-higher-resolution'))
        prefer_higher_resolution = (prefer_higher_resolution.lower() == 'true'
                                    if prefer_higher_resolution is not None
                                    else False)

        # Query the shape of the full image
        image = client.get_image(uuid)
        fileset_uuid = image['data']['fileset_uuid']
        fileset = client.get_fileset(fileset_uuid)

        if fileset['data']['complete'] is not True:
            raise ValueError(
                f'Fileset has not had metadata extracted yet: {fileset_uuid}')

        obj = boto3.resource('s3').Object(
            bucket.split(':')[-1], f'{fileset_uuid}/metadata.xml')
        body = obj.get()['Body']
        data = body.read()
        stream = BytesIO(data)
        import xml.etree.ElementTree as ET
        e_root = ET.fromstring(stream.getvalue().decode('UTF-8'))
        e_image = e_root.find('ome:Image[@ID="Image:{}"]'.format(uuid),
                              {'ome': OME_NS})
        e_pixels = e_image.find('ome:Pixels', {'ome': OME_NS})

        image_shape = (int(e_pixels.attrib['SizeX']),
                       int(e_pixels.attrib['SizeY']))

        # Query the number of levels available
        level_count = image['data']['pyramid_levels']

        # Create shape tuples
        tile_shape = (1024, 1024)
        target_shape = (height, width)

        # Get the optimum level of the pyramid from which to use tiles
        try:
            output_max = max(
                [d for d in (output_height, output_width) if d is not None])
            level = render.get_optimum_pyramid_level(image_shape, level_count,
                                                     output_max,
                                                     prefer_higher_resolution)
        except ValueError:
            level = 0

        # Transform origin and shape of target region into that required for
        # the pyramid level being used
        origin = render.transform_coordinates_to_level((x, y), level)
        shape = render.transform_coordinates_to_level(target_shape, level)

        # Calculate the scaling factor
        if output_width is not None:
            if output_height is not None:
                # Use both supplied scaling factors
                scaling_factor = (output_height / shape[0],
                                  output_width / shape[1])
            else:
                # Calculate scaling factor from output_width only
                scaling_factor = output_width / shape[1]
        else:
            if output_height is not None:
                # Calcuate scaling factor from output_height only
                scaling_factor = output_height / shape[0]
            else:
                # No scaling
                scaling_factor = 1

        args = []
        tiles = []
        for channel in channels:

            color = channel['color']
            _id = channel['index']
            _min = channel['min']
            _max = channel['max']

            for indices in render.select_grids(tile_shape, origin, shape):

                (i, j) = indices

                # Disallow negative tiles
                if i < 0 or j < 0:
                    continue

                # Add to list of tiles to fetch
                args.append((uuid, j, i, z, t, _id, level))

                # Add to list of tiles
                tiles.append({
                    'grid': (i, j),
                    'color': color,
                    'min': _min,
                    'max': _max
                })

        # Fetch raw tiles in parallel
        s3_tile_provider = S3TileProvider(
            bucket.split(':')[-1], missing_tile_callback=handle_missing_tile)
        try:
            pool = ThreadPool(len(args))
            images = pool.starmap(s3_tile_provider.get_tile, args)
        finally:
            pool.close()

        # Update tiles dictionary with image data
        for image_tile, image in zip(tiles, images):
            image_tile['image'] = image

        # Blend the raw tiles
        composite = render.composite_subtiles(tiles, tile_shape, origin, shape)

        #Rescale for desired output size
        if scaling_factor != 1:
            scaled = render.scale_image_nearest_neighbor(
                composite, scaling_factor)
        else:
            scaled = composite

        #  requires 0 - 255 values
        scaled *= 255
        scaled = scaled.astype(np.uint8, copy=False)

        # Encode rendered image as JPG
        img = BytesIO()
        imagecodecs.imwrite(img, scaled, codec="jpg")
        img.seek(0)
        return img.read()
Esempio n. 4
0
def test_composite_subtiles_level0(
        level0_tiles_green_mask, level0_tiles_red_mask,
        level0_tiles_magenta_mask, level0_tiles_blue_mask,
        level0_tiles_orange_mask, level0_tiles_cyan_mask, color_red,
        color_green, color_blue, color_magenta, color_cyan, color_orange,
        level0_stitched):
    '''Ensure expected rendering of multi-tile multi-channel image.'''

    expected = ski.adjust_gamma(level0_stitched, 1 / 2.2)

    result = composite_subtiles([{
        'min': 0,
        'max': 1,
        'grid': (0, 0),
        'image': level0_tiles_green_mask[0][0],
        'color': color_green
    }, {
        'min': 0,
        'max': 1,
        'grid': (1, 0),
        'image': level0_tiles_green_mask[1][0],
        'color': color_green
    }, {
        'min': 0,
        'max': 1,
        'grid': (2, 0),
        'image': level0_tiles_green_mask[2][0],
        'color': color_green
    }, {
        'min': 0,
        'max': 1,
        'grid': (0, 0),
        'image': level0_tiles_red_mask[0][0],
        'color': color_red
    }, {
        'min': 0,
        'max': 1,
        'grid': (1, 0),
        'image': level0_tiles_red_mask[1][0],
        'color': color_red
    }, {
        'min': 0,
        'max': 1,
        'grid': (2, 0),
        'image': level0_tiles_red_mask[2][0],
        'color': color_red
    }, {
        'min': 0,
        'max': 1,
        'grid': (0, 1),
        'image': level0_tiles_magenta_mask[0][1],
        'color': color_magenta
    }, {
        'min': 0,
        'max': 1,
        'grid': (1, 1),
        'image': level0_tiles_magenta_mask[1][1],
        'color': color_magenta
    }, {
        'min': 0,
        'max': 1,
        'grid': (2, 1),
        'image': level0_tiles_magenta_mask[2][1],
        'color': color_magenta
    }, {
        'min': 0,
        'max': 1,
        'grid': (0, 1),
        'image': level0_tiles_blue_mask[0][1],
        'color': color_blue
    }, {
        'min': 0,
        'max': 1,
        'grid': (1, 1),
        'image': level0_tiles_blue_mask[1][1],
        'color': color_blue
    }, {
        'min': 0,
        'max': 1,
        'grid': (2, 1),
        'image': level0_tiles_blue_mask[2][1],
        'color': color_blue
    }, {
        'min': 0,
        'max': 1,
        'grid': (0, 2),
        'image': level0_tiles_orange_mask[0][2],
        'color': color_orange
    }, {
        'min': 0,
        'max': 1,
        'grid': (1, 2),
        'image': level0_tiles_orange_mask[1][2],
        'color': color_orange
    }, {
        'min': 0,
        'max': 1,
        'grid': (2, 2),
        'image': level0_tiles_orange_mask[2][2],
        'color': color_orange
    }, {
        'min': 0,
        'max': 1,
        'grid': (0, 2),
        'image': level0_tiles_cyan_mask[0][2],
        'color': color_cyan
    }, {
        'min': 0,
        'max': 1,
        'grid': (1, 2),
        'image': level0_tiles_cyan_mask[1][2],
        'color': color_cyan
    }, {
        'min': 0,
        'max': 1,
        'grid': (2, 2),
        'image': level0_tiles_cyan_mask[2][2],
        'color': color_cyan
    }], (2, 2), (0, 0), (6, 6))

    np.testing.assert_allclose(expected, result)