From 8431778d8dc8d88180e1aaa7fc0439b892fe2101 Mon Sep 17 00:00:00 2001 From: Alan O'Callaghan Date: Mon, 4 Nov 2024 15:39:09 +0000 Subject: [PATCH] LabeledImageServer coordinate bug (#26) Adjust LabeledImageServer rendering of features when a region request is supplied. --- qubalab/images/labeled_server.py | 4 +-- tests/images/test_labeled_server.py | 52 ++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/qubalab/images/labeled_server.py b/qubalab/images/labeled_server.py index a4f9f8a..48f2602 100644 --- a/qubalab/images/labeled_server.py +++ b/qubalab/images/labeled_server.py @@ -106,7 +106,7 @@ def _read_block(self, level: int, region: Region2D) -> np.ndarray: draw_geometry( image.size, drawing_context, - self._geometries[i], + shapely.affinity.translate(self._geometries[i], -region.x, -region.y), 1 ) full_image[label, :, :] = np.asarray(image, dtype=self.metadata.dtype) @@ -119,7 +119,7 @@ def _read_block(self, level: int, region: Region2D) -> np.ndarray: draw_geometry( image.size, drawing_context, - self._geometries[i], + shapely.affinity.translate(self._geometries[i], -region.x, -region.y), self._feature_index_to_label[i] ) return np.expand_dims(np.asarray(image, dtype=self.metadata.dtype), axis=0) diff --git a/tests/images/test_labeled_server.py b/tests/images/test_labeled_server.py index 5846462..fbefd42 100644 --- a/tests/images/test_labeled_server.py +++ b/tests/images/test_labeled_server.py @@ -24,7 +24,7 @@ large_metadata = ImageMetadata( "/path/to/img.tiff", "Image name", - (ImageShape(1000, 500),), + (ImageShape(500, 250),), PixelCalibration( PixelLength.create_microns(2.5), PixelLength.create_microns(2.5) @@ -70,7 +70,7 @@ def test_image_width_with_no_downsample(): labeled_server.close() -def test_image_width_with_no_downsample(): +def test_image_height_with_no_downsample(): expected_height = sample_metadata.shape.y labeled_server = LabeledImageServer(sample_metadata, []) @@ -397,16 +397,19 @@ def test_read_polygon_in_single_channel_image_without_label_map_with_downsample( def test_label_can_hold_many_values(): downsample = 1 - max_objects = 500 - random.seed(42) + max_objects = 1000 + random.seed(1) def rands(): + x = random.randint(0, int(large_metadata.shape.x / downsample)) + y = random.randint(0, int(large_metadata.shape.x / downsample)) return ( - random.randint(0, int(sample_metadata.shape.x / downsample)), - random.randint(0, int(sample_metadata.shape.y / downsample)) + (x, y), + (x + 1, y), + (x + 1, y + 1), + (x, y + 1) ) - coords = [(rands(), rands(), rands(), rands()) for i in range(max_objects)] - coords = list(set(coords)) + coords = [rands() for i in range(max_objects)] n_objects = len(coords) features = [ImageFeature(geojson.Polygon([coords[i]]), Classification("Some classification")) for i in range(n_objects)] @@ -414,4 +417,35 @@ def rands(): image = labeled_server.read_region(1, Region2D(0, 0, labeled_server.metadata.width, labeled_server.metadata.height)) - assert np.max(image) > 255 + assert np.max(image) == max_objects + + +def test_single_channel_labeled_image_with_region_request(): + downsample = 1 + features = [ImageFeature(geojson.LineString([(7, 5), (9, 5)]))] + expected_image = np.array( + [[[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 1, 1, 1]]] + ) + labeled_server = LabeledImageServer(sample_metadata, features, multichannel=False, downsample=downsample) + region = Region2D(5, 3, labeled_server.metadata.width-5, labeled_server.metadata.height-3) + image = labeled_server.read_region(1, region) + + np.testing.assert_array_equal(image, expected_image) + +def test_multi_channel_labeled_image_with_region_request(): + downsample = 1 + features = [ImageFeature(geojson.LineString([(7, 5), (9, 5)]))] + expected_image = np.array( + [[[False, False, False, False, False], + [False, False, False, False, False], + [False, False, False, False, False]], + [[False, False, False, False, False], + [False, False, False, False, False], + [False, False, True, True, True]]] + ) + labeled_server = LabeledImageServer(sample_metadata, features, multichannel=True, downsample=downsample) + region = Region2D(5, 3, labeled_server.metadata.width-5, labeled_server.metadata.height-3) + image = labeled_server.read_region(1, region) + np.testing.assert_array_equal(image, expected_image)