I have a lot of pictures that I have to perform some data analysis on. Currently all of the pictures look like the one below:
Before the images can be processed I must remove the vertical black border on the left and right side of the image. So far I've been able to achieve this in Python by converting the image to grayscale and then an array so that darker pixels are closer to 0. Then I can select the region where the entire column is above a threshold value:
import numpy as np
from PIL import Image
file = "file_name.png"
img = Image.open(file).convert('L')
img.show()
array = np.array(img)
print(array.shape)
array_crop = array[:, np.all(array > 10, axis=0)]
im = Image.fromarray(array_crop, mode='L')
im.show()
print(array_crop.shape)
the cropped image then looks like this:
where the initial shape is (240, 320) and the cropped shape is (240, 250) which is exactly what I want. The problem is that with this same code, the resulting cropped shape is not always perfect for every image (for example (240, 251)) because the black border is not perfectly black and has a slight gradient. Is there a way in Python to determine the slice index that corresponds to the np.all condition result so that I can apply it to all of my images consistently?
So far the only way I have thought to achieve this is through trial and error. Then as a test I could subtract the two cropped arrays from eachother to make sure all resulting values are 0, but I'd rather not have to do it this way.
CodePudding user response:
You can work out the boundaries of the image like this:
w = np.argwhere(array > 10)
amin = w[:, 0].min()
amax = w[:, 0].max()
bmin = w[:, 1].min()
bmax = w[:, 1].max()
array_crop = array[amin:amax 1, bmin:bmax 1]
which should always crop it to a rectangle.