从图像中删除背景 - Python

Remove Background from Image - Python

我正在尝试使用 OpenCV 从图像中删除黑色背景,但我无法删除像素以仅捕获没有黑色背景的主要图像。这是我使用的代码以及原始输入图像。

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')

我实际上是在重新格式化此处概述的代码 (https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_grabcut/py_grabcut.html),该代码演示了使用 OpenCV 进行的最前沿提取。但是,我仍然无法从输入图像中裁剪周围的背景像素,同时在输出图像中保留图像本身的完整性。有没有更简单的方法来解决这个问题?我还尝试使用 cv2.thresholding 和轮廓 crop/remove 背景,但仍然无法弄清楚。非常感谢任何帮助!

这是在 Python/OpenCV 中使背景透明的一种方法。

  • 读取输入
  • 转换为灰色
  • 阈值
  • 应用形态学来清除多余的斑点
  • 获取外部轮廓
  • 找到最大的轮廓
  • 将轮廓绘制为黑色背景上的白色填充作为遮罩
  • 抗锯齿蒙版
  • 将其放入输入图像的 alpha 通道
  • 保存结果

输入:

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()

阈值图像:

形态学清理图像:

轮廓图:

蒙版图片:

透明背景的结果: