I have a numpy binary masked image that looks like the following:

enter image description here

I want to automatically crop this image like the following:

enter image description here

Can I achieve this using some sort of image processing rather than building a bounding box regressor? The method should also work if the image is horizontally flipped.

I am currently using th below crop function to crop the image if any row or column have all 0 pixels:

def crop_image(img,tol=0):
    # img is 2D image data
    # tol  is tolerance
    mask = img>tol
    return img[np.ix_(mask.any(1),mask.any(0))]

This crops out the upper black space from the image but does not work for the lower part for obvious reasons.

My attempt was to try to threshold the image based on pixel counts. Below is the code:

counts = np.sum(image==1,axis=0)

enter image description here

If we can threshold the image as below we might also consider the task partially successful as we would get something like the following:

enter image description here

enter image description here

Thanks alot. Any help will be highly appreciated.


One approach that is always available for binary images are morphological operations.

enter image description here

The critical piece of code is

# from skimage import morphology
# import numpy as np

# filter elements smaller than 1/6-th of the total width
selem = morphology.rectangle(1, img_binary.shape[1] // 6)
img_opened = morphology.opening(img_binary, selem=selem)

hist = np.sum(img_opened, axis=1)
non_zero = np.argwhere(hist > 0)
top_bound = int(np.round(np.min(non_zero) * (1 - 0.05))) # 5% tolerance
bottom_bound = int(np.round(np.max(non_zero) * (1 + 0.05))) # 5% tolerance

Here is the notebook I used to produce the image above: https://gist.github.com/FirefoxMetzger/5d0d5e207bf8182f61374ac9ad80f10f

  • $\begingroup$ Hi FirefoxMetzger. Thanks for your answer. Unfortunately this does not work for me. I get this image when I try to visualize the img_opened. [![enter image description here][1]][1] [1]: i.stack.imgur.com/8PIt5.png . Addiitonally how do you choose the threshold 1/6th, is there a way to dynamically estimate this? $\endgroup$ – Nolan Cardozo Nov 23 '20 at 13:46
  • $\begingroup$ @NolanCardozo Are you opening a binary image or a gray-scale image? Your result may stem from using a gray-scale morphological operation instead of a binary one. Regarding a dynamic threshold, you can choose the structuring element (selem) dynamically. I choose a fixed one, because - given your question - it seemed like the simplest solution. $\endgroup$ – FirefoxMetzger Nov 23 '20 at 19:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.