Skip to content

Commit

Permalink
Merge pull request #540 from mradamcox/509_ignore_blank_patches
Browse files Browse the repository at this point in the history
509 ignore blank patches
  • Loading branch information
rwood-97 authored Dec 19, 2024
2 parents 9fcc4a3 + ee8940d commit ae10e4b
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ The following table shows which versions of MapReader are compatible with which

_Add new changes here_

### Added

- Added `skip_blank_patches` argument to `MapImages.patchify_all()` ([#540](https://github.com/maps-as-data/MapReader/pull/540))

## [v1.6.1](https://github.com/Living-with-machines/MapReader/releases/tag/v1.6.1) (2024-11-18)

### Added
Expand Down
1 change: 1 addition & 0 deletions docs/source/using-mapreader/step-by-step-guide/2-load.rst
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ This will create 1024 x 1024 pixel patches with 10% overlap between each patch.
- ``square_cuts`` - This is a deprecated method and no longer recommended for use. By default, this is set to ``False`` and padding is added to patches at the edges of the parent image to ensure square patches. If you set ``square_cuts=True``, instead of padding, there will be some overlap between edge patches.
- ``add_to_parent`` - By default, this is set to ``True`` so that each time you run ``patchify_all`` your patches are added to your ``MapImages`` object. Setting it to ``False`` (by specifying ``add_to_parent=False``) will mean your patches are created, but not added to your ``MapImages`` object. This can be useful for testing out different patch sizes.
- ``rewrite`` - By default, this is set to ``False`` so that if your patches already exist they are not overwritten. Setting it to ``True`` (by specifying ``rewrite=True``) will mean already existing patches are recreated and overwritten.
- ``skip_blank_patches`` - By default, this is set to ``False``. Setting to ``True`` will omit any patches that only contain ``0`` values, which can speed up processing on irregularly shaped map images that have empty regions. The `Image.getbbox() <https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.getbbox>`_ method is used to determine if a patch is blank.

If you would like to save your patches as geo-referenced tiffs (i.e. geotiffs), use:

Expand Down
18 changes: 17 additions & 1 deletion mapreader/load/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,7 @@ def patchify_all(
patch_size: int | None = 100,
tree_level: str | None = "parent",
path_save: str | None = None,
skip_blank_patches: bool = False,
add_to_parents: bool | None = True,
square_cuts: bool | None = False,
resize_factor: bool | None = False,
Expand All @@ -1234,6 +1235,8 @@ def patchify_all(
Directory to save the patches.
If None, will be set as f"patches_{patch_size}_{method}" (e.g. "patches_100_pixel").
By default None.
skip_blank_patches : bool
If True, any patch that only contains 0 values will be skipped, by default ``False``. Uses PIL.Image().get_bbox().
add_to_parents : bool, optional
If True, patches will be added to the MapImages instance's
``images`` dictionary, by default ``True``.
Expand Down Expand Up @@ -1313,6 +1316,7 @@ def patchify_all(
add_to_parents=add_to_parents,
resize_factor=resize_factor,
output_format=output_format,
skip_blank_patches=skip_blank_patches,
rewrite=rewrite,
verbose=verbose,
overlap=overlap,
Expand All @@ -1326,6 +1330,7 @@ def _patchify_by_pixel(
add_to_parents: bool | None = True,
resize_factor: bool | None = False,
output_format: str | None = "png",
skip_blank_patches: bool = False,
rewrite: bool | None = False,
verbose: bool | None = False,
overlap: int | None = 0,
Expand All @@ -1347,6 +1352,8 @@ def _patchify_by_pixel(
If True, resize the images before patchifying, by default ``False``.
output_format : str, optional
Format to use when writing image files, by default ``"png"``.
skip_blank_patches : bool
If True, any patch that only contains 0 values will be skipped, by default ``False``. Uses PIL.Image().get_bbox().
rewrite : bool, optional
If True, existing patches will be rewritten, by default ``False``.
verbose : bool, optional
Expand All @@ -1370,6 +1377,7 @@ def _patchify_by_pixel(
)

height, width = img.height, img.width
overlap_pixels = int(patch_size * overlap)

x = 0
while x < width:
Expand All @@ -1389,6 +1397,15 @@ def _patchify_by_pixel(

else:
patch = img.crop((x, y, max_x, max_y))

# skip if blank and don't add to parents
if skip_blank_patches and patch.getbbox() is None:
self._print_if_verbose(
f"[INFO] Skipping empty patch: {patch_id}.", verbose
)
y = y + patch_size - overlap_pixels
continue

if max_x == width:
patch = ImageOps.pad(
patch, (patch_size, patch.height), centering=(0, 0)
Expand Down Expand Up @@ -1416,7 +1433,6 @@ def _patchify_by_pixel(
self._add_patch_coords_id(patch_id)
self._add_patch_polygons_id(patch_id)

overlap_pixels = int(patch_size * overlap)
y = y + patch_size - overlap_pixels
x = x + patch_size - overlap_pixels

Expand Down
Binary file added tests/sample_files/cropped_blank_corners_rgb.tif
Binary file not shown.
Binary file added tests/sample_files/cropped_blank_corners_rgba.tif
Binary file not shown.
20 changes: 20 additions & 0 deletions tests/test_load/test_images.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,26 @@ def test_patchify_pixels(sample_dir, image_id, tmp_path):
assert os.path.isfile(f"{tmp_path}/patch-0-0-3-3-#{image_id}#.png")


def test_patchify_pixels_skip_blank_rgb(sample_dir, tmp_path):
maps = MapImages(f"{sample_dir}/cropped_blank_corners_rgb.tif")
maps.patchify_all(patch_size=3, path_save=tmp_path, skip_blank_patches=True)
parent_list = maps.list_parents()
patch_list = maps.list_patches()
assert len(parent_list) == 1
assert len(patch_list) == 5
assert os.path.isfile(f"{tmp_path}/patch-0-3-3-6-#cropped_blank_corners_rgb.tif#.png")


def test_patchify_pixels_skip_blank_rgba(sample_dir, tmp_path):
maps = MapImages(f"{sample_dir}/cropped_blank_corners_rgba.tif")
maps.patchify_all(patch_size=3, path_save=tmp_path, skip_blank_patches=True)
parent_list = maps.list_parents()
patch_list = maps.list_patches()
assert len(parent_list) == 1
assert len(patch_list) == 5
assert os.path.isfile(f"{tmp_path}/patch-0-3-3-6-#cropped_blank_corners_rgba.tif#.png")


def test_patchify_pixels_square(sample_dir, image_id, tmp_path):
maps = MapImages(f"{sample_dir}/{image_id}")
maps.patchify_all(patch_size=5, path_save=f"{tmp_path}_square", square_cuts=True)
Expand Down

0 comments on commit ae10e4b

Please sign in to comment.