I'm trying to crop some binary images. The images have a black background and white silhouette. I want to crop all of my images, removing any excess background. I've tried doing this using the function below, however, the output images tend to also crop the edges of the silhouette, whilst I would like to keep these. I haven't been successful in finding a way to do this. Any ideas on how this could be done?
example images
def crop_image(img,tol):
mask = img > tol
return img[np.ix_(mask.any(1),mask.any(0))]
CodePudding user response:
You can get the coordinates from cv2.findNonZero()
function, and cv2.boundingRect()
import matplotlib.pyplot as plt
import numpy as np
import cv2
def downloadImage(URL):
"""Downloads the image on the URL, and convers to cv2 RGB format"""
from io import BytesIO
from PIL import Image as PIL_Image
import requests
response = requests.get(URL)
image = PIL_Image.open(BytesIO(response.content))
return cv2.cvtColor(np.array(image), cv2.COLOR_BGR2RGB)
URL = "https://i.stack.imgur.com/WgnXW.jpg"
# Read image
img = downloadImage(URL)
# crop blank frame
initialImage = img[11:2330, 11:2208]
fig, ax = plt.subplots(1, 3)
ax[0].imshow(initialImage)
ax[0].set_title('Initial Image')
# crop the empty space
coords = cv2.findNonZero(cv2.cvtColor(initialImage, cv2.COLOR_BGR2GRAY))
x, y, w, h = cv2.boundingRect(coords)
cropedIMag = initialImage[y:y h, x:x w]
ax[1].imshow(cropedIMag)
ax[1].set_title('Cropped Image')
# Add an empty frame to the image
extraPixels = 100
paddedImag = np.pad(cropedIMag, ((extraPixels, extraPixels),(extraPixels, extraPixels),(0,0)), 'constant')
ax[2].imshow(paddedImag)
ax[2].set_title('Cropped \nand padded Image')
plt.show()