-1

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?

Jett t
  • 13
  • 2
  • Yes, this is possible. Please see [on topic](https://stackoverflow.com/help/on-topic) and [how to ask](https://stackoverflow.com/help/ask) from the [intro tour](https://stackoverflow.com/tour). "*Show me how to solve this coding problem*" [is off-topic for Stack Overflow](https://meta.stackoverflow.com/q/284236). You have to [make an honest attempt at the solution](https://meta.stackoverflow.com/q/261592), and then ask a specific question about your implementation. – MattDMo Sep 05 '22 at 04:13
  • @MattDMo I am sorry if I didn't make enough of an attempt for you. I have trying to solve this problem for hours and cant find any resources. Would I use a library like Pillow? How could I achieve what you said is possible? – Jett t Sep 05 '22 at 04:32
  • It all depends on what you're trying to do. If you have an image of known size and you want to crop it to another known size, then Pillow will probably work well. However, if you're trying to analyze the picture to determine how wide the widest bar is and crop it to that dimension, that's a lot more complex, and you'll probably want to use something OpenCV. – MattDMo Sep 05 '22 at 04:36
  • @MattDMo I have a image of unknown size and would want to crop it to the the dimension of the widest bar and the height of the top bar and bottom bar. I dont even know how something like that could be done in code. Could I get an example of this could be done? – Jett t Sep 05 '22 at 04:41
  • Well, you're going to have to start reading up on image processing and finding pixels. OpenCV is powerful enough that this should be doable, but it'll probably take more than 4 or 5 lines of code. You need to find the bounding box that contains all the pixels that aren't black (assuming your image isn't anti-aliased), then crop. You can also look *up* the pipeline at how the images are being made, and possibly tweak that process so they're already cropped enough. Check out [this Q&A](https://stackoverflow.com/q/50051916) for a possible starting point. – MattDMo Sep 05 '22 at 04:52

2 Answers2

1

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.

AKX
  • 152,115
  • 15
  • 115
  • 172
0

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:

Azhar Khan
  • 3,829
  • 11
  • 26
  • 32