Skip to content

Instantly share code, notes, and snippets.

@soraxas
Last active September 7, 2023 03:06
Show Gist options
  • Save soraxas/c9cdb7cca0e85e42a76028a76cfd8dbb to your computer and use it in GitHub Desktop.
Save soraxas/c9cdb7cca0e85e42a76028a76cfd8dbb to your computer and use it in GitHub Desktop.
Using this script on an image will crop all sub-regions that are surrounded by white pixels boarder as new images. Useful to extract all sub images, say, in a screenshot.
#!/usr/bin/env python3
from pathlib import Path
import argparse
from PIL import Image
import numpy as np
from scipy.ndimage.measurements import label
parser = argparse.ArgumentParser(
"Crop all sub-regions that are surrounded by white pixels"
)
parser.add_argument("image_file")
parser.add_argument("--order-by-y-axis", default=False, action="store_true")
parser.add_argument("--no-region-as-suffix", default=False, action="store_true")
parser.add_argument("--target-pixel-value", default=255)
args = parser.parse_args()
def find_squares(array: np.ndarray, area_range=[-np.inf, np.inf]):
assert len(array.shape) == 2
assert array.dtype == bool
labeled, num_features = label(array, np.ones((3, 3), dtype=int))
for i in range(1, num_features + 1):
pixels = np.where(labeled == i)
# print(pixels)
x1 = pixels[1].min()
x2 = pixels[1].max()
y1 = pixels[0].min()
y2 = pixels[0].max()
area = (x2 - x1) * (y2 - y1)
# print(area)
print(f"{i} | slice: array[{y1}:{y2}, {x1}:{x2}] (area={area})")
if area_range[0] <= area <= area_range[1]:
yield (x1, y1, x2, y2)
def main(args):
image_fname = Path(args.image_file)
if not image_fname.exists():
print(f"Given filename '{image_fname}' does not exists!")
exit(1)
image = Image.open(image_fname)
image_pixels = np.asarray(image)[:, :, :3]
is_white = (image_pixels == args.target_pixel_value).all(axis=2)
regions = list(find_squares(~is_white))
# sort by top-left corners (i.e., [x1, y1])
# order_by = "order-by-x-axis"
order_functor = lambda x: (x[0], x[1])
if args.order_by_y_axis:
order_functor = lambda x: (x[1], x[0])
regions = sorted(regions, key=order_functor)
for i, region in enumerate(regions):
suffix = ""
if not args.no_region_as_suffix:
suffix = f"-[x={region[0]}-{region[2]},y={region[1]}-{region[3]}]"
target_filename = f"{image_fname.stem}_{i}{suffix}.png"
image.crop(region).save(target_filename)
if __name__ == "__main__":
main(args)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment