Image foreground extraction techniques using Python

1.8k Views Asked by At

I've prepared a piece of code in python using OpenCV that extracts the foreground in the image. My program is getting a stream of images and I need to extract the object from those images.

The images include products like shoes, bags or clothing. Most of the images have white background but sometimes I get a grey gradient background as well. I've used thresholding to separate the foreground from the background and extract the object.

But the problem is that even if I assume that the background will be white and set a fixed upper and lower thresholding values, I sometimes get whites in the object and thresholding doesn't render the correct output.

I wanted to know what might be some good approaches in Computer Vision that I can utilize to get the best results here?

enter image description here

1

There are 1 best solutions below

1
On

You can get this result:

enter image description here

using the canny edge detector, dilation and erosion:

import cv2
import numpy as np

def process(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_canny = cv2.Canny(img_gray, 12, 54)
    kernel = np.ones((3, 3))
    img_dilate = cv2.dilate(img_canny, kernel, iterations=10)
    img_erode = cv2.erode(img_dilate, kernel, iterations=8)
    return img_erode

img = cv2.imread("robe.jpg")
contours, _ = cv2.findContours(process(img), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cv2.drawContours(img, contours, -1, (0, 255, 0), 2)
cv2.imshow("Image", img)
cv2.waitKey(0)

Explanation of the process function:

  1. First, convert the image to grayscale in order to use the canny edge detector on it. Then, detect its edges using the canny edge detector:
def process(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_canny = cv2.Canny(img_gray, 12, 54)
  1. Define a kernel to use to dilate and erode the image:
    kernel = np.ones((3, 3))
  1. Finally, dilate the image several iterations to fill in gaps, remove noise and smooth out bumps in the edges. of course, dilation makes edges thicker, so after that, erode the image to shrink them back down. But as there was a lot of gaps in the edges before dilation, erode the image by less iterations. Return the eroded image:
    img_dilate = cv2.dilate(img_canny, kernel, iterations=10)
    img_erode = cv2.erode(img_dilate, kernel, iterations=8)
    return img_erode