Skip to content

Instantly share code, notes, and snippets.

@VieVie31
Last active April 29, 2020 19:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save VieVie31/9adbff1e84e37fba877457b1fa4d28a6 to your computer and use it in GitHub Desktop.
Save VieVie31/9adbff1e84e37fba877457b1fa4d28a6 to your computer and use it in GitHub Desktop.
Crop black borders in image with python (robust to watermark putted in)…
import numpy as np
import matplotlib.pyplot as plt
from skimage.io import imread
from skimage.filters import sobel
from skimage.transform import resize
from skimage.morphology import binary_erosion
from scipy.ndimage.filters import maximum_filter1d
def crop_black_border(img: np.ndarray) -> np.ndarray:
"""Crop black edges even if some watermark is putted in.
@author: VieVie31 (http://github.com/VieVie31)
The intuition behind my algorithm is that the sobel response
should be the greatest on the edges of the black borders…
My algorithm follow the next steps :
1. resize the image to a smaller version (for faster computation)
2. make a binary mask from the eroded version of the binarized resized image
3. compute sobel edge detection on the binary mask
4. sum by row/column and apply non local non maximum filtering
5. if there are only 2 peaks behind a given threshold keep the index
6. crop on the index previously found
:param img: the image to process
:return: the copped version of the image
"""
im = img[:, :, :3].mean(-1) if len(img.shape) == 3 else img
im = im / 255. if (im > 1).sum() else im
h, w = im.shape
im = resize(im, (128, 128))
black = im < .06
black = binary_erosion(~black, selem=np.ones((8, 8)))
contours = sobel(black)
horiz = contours.sum(1)
verti = contours.sum(0)
# break consecutive maximum
horiz = horiz + (1e-8 * np.random.rand(128))
verti = verti + (1e-8 * np.random.rand(128))
verti = (verti > 50) * (maximum_filter1d(verti, 5) == verti)
horiz = (horiz > 50) * (maximum_filter1d(horiz, 5) == horiz)
if horiz.sum() == 2:
i, j = horiz.argsort()[-2:]
i, j = min(i, j), max(i, j)
img = img[int(i * h / 128):int(j * h / 128)]
if verti.sum() == 2:
i, j = verti.argsort()[-2:]
i, j = min(i, j), max(i, j)
img = img[:, int(i * w / 128):int(j * w / 128)]
return img
if __name__ == "__main__":
for i in range(1, 4):
plt.imshow(crop_black_border(imread(f"im{i}.jpg")))
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment