How do I remove the background from this kind of image? How do I remove the background from this kind of image? python python

How do I remove the background from this kind of image?


The following code should get you started. You may want to play around with the parameters at the top of the program to fine-tune your extraction:

import cv2import numpy as np#== Parameters =======================================================================BLUR = 21CANNY_THRESH_1 = 10CANNY_THRESH_2 = 200MASK_DILATE_ITER = 10MASK_ERODE_ITER = 10MASK_COLOR = (0.0,0.0,1.0) # In BGR format#== Processing =======================================================================#-- Read image -----------------------------------------------------------------------img = cv2.imread('C:/Temp/person.jpg')gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#-- Edge detection -------------------------------------------------------------------edges = cv2.Canny(gray, CANNY_THRESH_1, CANNY_THRESH_2)edges = cv2.dilate(edges, None)edges = cv2.erode(edges, None)#-- Find contours in edges, sort by area ---------------------------------------------contour_info = []_, contours, _ = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)# Previously, for a previous version of cv2, this line was: #  contours, _ = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)# Thanks to notes from commenters, I've updated the code but left this notefor c in contours:    contour_info.append((        c,        cv2.isContourConvex(c),        cv2.contourArea(c),    ))contour_info = sorted(contour_info, key=lambda c: c[2], reverse=True)max_contour = contour_info[0]#-- Create empty mask, draw filled polygon on it corresponding to largest contour ----# Mask is black, polygon is whitemask = np.zeros(edges.shape)cv2.fillConvexPoly(mask, max_contour[0], (255))#-- Smooth mask, then blur it --------------------------------------------------------mask = cv2.dilate(mask, None, iterations=MASK_DILATE_ITER)mask = cv2.erode(mask, None, iterations=MASK_ERODE_ITER)mask = cv2.GaussianBlur(mask, (BLUR, BLUR), 0)mask_stack = np.dstack([mask]*3)    # Create 3-channel alpha mask#-- Blend masked img into MASK_COLOR background --------------------------------------mask_stack  = mask_stack.astype('float32') / 255.0          # Use float matrices, img         = img.astype('float32') / 255.0                 #  for easy blendingmasked = (mask_stack * img) + ((1-mask_stack) * MASK_COLOR) # Blendmasked = (masked * 255).astype('uint8')                     # Convert back to 8-bit cv2.imshow('img', masked)                                   # Displaycv2.waitKey()#cv2.imwrite('C:/Temp/person-masked.jpg', masked)           # Save

Ouput:enter image description here


If you wish to fill background not with a red color but make it transparent, you may add following lines to solution:

# split image into channelsc_red, c_green, c_blue = cv2.split(img)# merge with mask got on one of a previous stepsimg_a = cv2.merge((c_red, c_green, c_blue, mask.astype('float32') / 255.0))# show on screen (optional in jupiter)%matplotlib inlineplt.imshow(img_a)plt.show()# save to diskcv2.imwrite('girl_1.png', img_a*255)# or the same using pltplt.imsave('girl_2.png', img_a)

If you wish you may tweak some png compression parameters to make file smaller.

Image on a white background below. Or on a black one - http://imgur.com/a/4NwmH

enter image description here


As an alternative, you can use neural networks like this one: CRFRNN.

It gives the result like this:

enter image description here