Home > other >  I am trying to crop an image to remove extra space in python
I am trying to crop an image to remove extra space in python

Time:09-05

This may sound confusing but I will demonstrate what my goal is. I want to crop the extra space around a image using python. You can see in image two the outside border is cropped off until it cuts out the extra space around the colored bars in the center. I am not sure if this is possible. Sorry for the vague question as it is very hard to explain what I am trying to do.

(Before) Image Before Cropping ----------> (After) What I am trying to achieve. You can notice the extra black space around the colored thing in the center is cutout on the after image.

I want to be able to cut the extra space out without me manually typing in where to crop out. How could this be done?

CodePudding user response:

As I understand, your problem is how to identify extra space, rather than which library/framework/tool to use to edit images. If so, then I've solved a similar problem about 4 years ago. I'm sorry, I don't have sample code to show (I left that organisation); but the logic was as follows:

  • Decide a colour for background. Never use this colour in any of the bars in the graph/image.
  • Read image data as RGB matrices (3 x 2D-array).
  • Repeat following on first row, last row, first column, last column:
    • Simultaneously iterate all 3 matrices
    • If all values in the row or column from index=0 to index=len(row or column) are equal to corresponding background colour RGB component, then this is extra space. Remove this row or column from all RGB matrices.
  • Write the remaining RGB matrices as image.

Following are some helpful links in this regard:

CodePudding user response:

Sure!

With a bit of Pillow and Numpy magic, you can do something like this – not sure if this is optimal, since I whipped it up in about 15 minutes and I'm not the Numpyiest of Numpyistas:

from PIL import Image
import numpy as np


def get_first_last(mask, axis: int):
    """ Find the first and last index of non-zero values along an axis in `mask` """
    mask_axis = np.argmax(mask, axis=axis) > 0
    a = np.argmax(mask_axis)
    b = len(mask_axis) - np.argmax(mask_axis[::-1])
    return int(a), int(b)


def crop_borders(img, crop_color):
    np_img = np.array(img)
    mask = (np_img != crop_color)[..., 0]  # compute a mask
    x0, x1 = get_first_last(mask, 0)  # find boundaries along x axis
    y0, y1 = get_first_last(mask, 1)  # find boundaries along y axis
    return img.crop((x0, y0, x1, y1))


def main():
    img = Image.open("0d34A.png").convert("RGB")
    img = crop_borders(img, crop_color=(0, 0, 0))
    img.save("0d34A_cropped.png")


if __name__ == "__main__":
    main()

If you need a different condition (e.g. all pixels dark enough, you can change how mask is defined.

  • Related