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.