Remove Background from Image - Python

懵懂的女人 提交于 2021-01-29 09:39:15

问题


I am trying to remove the black background from an image using OpenCV, but I am unable to remove the pixels to capture just the main imagery without the black background. Here is the code I am using, along with the original input image.

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('C:\\Users\\mdl518\\Desktop\\input.png')
mask = np.zeros(img.shape[:2],np.uint8)

bgdModel = np.zeros((1,65),np.float64)
fgdModel = np.zeros((1,65),np.float64)

rect = (0,0,1035,932)  # image width/height re-formatted as (x,y,width,height)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,cv2.GC_INIT_WITH_RECT)

mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
img = img*mask2[:,:,np.newaxis]

plt.imshow(img)
plt.savefig('C:\\Users\\mdl518\\Desktop\\output.png')

I am essentially re-formatting the code outlined here (https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_grabcut/py_grabcut.html) that illustrates forefront extraction using OpenCV. However, I am still unable to crop the surrounding background pixels from the input image while preserving the integrity of the image itself in the output image. Is there an easier way to go about this? I also tried to crop/remove the background using cv2.thresholding and contours but still couldn't figure it out. Any assistance is most appreciated!


回答1:


Here is one approach to make your background transparent in Python/OpenCV.

  • Read the input
  • Convert to gray
  • Threshold
  • Apply morphology to clean extraneous spots
  • Get external contours
  • Find the largest contour
  • Draw the contour as white filled on a black background as a mask
  • Antialias the mask
  • Put that into the alpha channel of the input image
  • Save the result

Input:

import cv2
import numpy as np
import skimage.exposure

# load image
img = cv2.imread('aerial_image.jpg')

# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold
thresh = cv2.threshold(gray, 11, 255, cv2.THRESH_BINARY)[1]

# apply morphology to clean small spots
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, borderType=cv2.BORDER_CONSTANT, borderValue=0)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel, borderType=cv2.BORDER_CONSTANT, borderValue=0)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
morph = cv2.morphologyEx(morph, cv2.MORPH_ERODE, kernel, borderType=cv2.BORDER_CONSTANT, borderValue=0)

# get external contour
contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)

# draw white filled contour on black background as mas
contour = np.zeros_like(gray)
cv2.drawContours(contour, [big_contour], 0, 255, -1)

# blur dilate image
blur = cv2.GaussianBlur(contour, (5,5), sigmaX=0, sigmaY=0, borderType = cv2.BORDER_DEFAULT)

# stretch so that 255 -> 255 and 127.5 -> 0
mask = skimage.exposure.rescale_intensity(blur, in_range=(127.5,255), out_range=(0,255))

# put mask into alpha channel of input
result = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
result[:,:,3] = mask

# save output
cv2.imwrite('aerial_image_thresh.png', thresh)
cv2.imwrite('aerial_image_morph.png', morph)
cv2.imwrite('aerial_image_contour.png', contour)
cv2.imwrite('aerial_image_mask.png', mask)
cv2.imwrite('aerial_image_antialiased.png', result)


# Display various images to see the steps
cv2.imshow('thresh', thresh)
cv2.imshow('morph', morph)
cv2.imshow('contour', contour)
cv2.imshow('mask', mask)
cv2.imshow('result', result)

cv2.waitKey(0)
cv2.destroyAllWindows()

Threshold image:

Morphology cleaned image:

Contour image:

Mask image:

Result with transparent background:



来源:https://stackoverflow.com/questions/63526621/remove-background-from-image-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!