How to crop or remove white background from an image

Tuhin Sah picture Tuhin Sah · Jan 23, 2018 · Viewed 18k times · Source

I am trying to compare images using OpenCV and Python.

Consider these images:


Image  900 x 726


Image 900 x 675


Both feature an identical pair of shoes, set to a white background. The only difference being that the first has a taller background than the second.

I want to know how to programmatically crop the white backgrounds of both so that I'm left with only the pair of shoes.

I must add that it won't be possible for me to manually crop the backgrounds.

Answer

Kinght 金 picture Kinght 金 · Jan 23, 2018

You requirement in the comment: The shoes are on a white background. I would like to completely get rid of the border; as in be left with a rectangular box with either a white or a transparent background, having the length and width of the shoes in the picture.

Then my steps to crop the target regions:

  1. Convert to gray, and threshold
  2. Morph-op to remove noise
  3. Find the max-area contour
  4. Crop and save it
#!/usr/bin/python3
# Created by Silencer @ Stackoverflow 
# 2018.01.23 14:41:42 CST
# 2018.01.23 18:17:42 CST
import cv2
import numpy as np

## (1) Convert to gray, and threshold
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
th, threshed = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV)

## (2) Morph-op to remove noise
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (11,11))
morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)

## (3) Find the max-area contour
cnts = cv2.findContours(morphed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
cnt = sorted(cnts, key=cv2.contourArea)[-1]

## (4) Crop and save it
x,y,w,h = cv2.boundingRect(cnt)
dst = img[y:y+h, x:x+w]
cv2.imwrite("001.png", dst)

Result: