【问题标题】:Remove Background from Image - Python从图像中删除背景 - Python
【发布时间】:2020-12-11 01:29:35
【问题描述】:

我正在尝试使用 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 和轮廓来裁剪/删除背景,但仍然无法弄清楚。非常感谢任何帮助!

【问题讨论】:

  • 您是要裁剪图像还是使黑色背景透明?如果裁剪为矩形,您将切断大量数据,因此不会保留您的图像。请澄清你想要什么。使背景透明,应该没有那么难。阈值,用形态学清理,获取外部轮廓并将其绘制为黑色背景上的填充白色。然后将其放入图像的 alpha 通道中。
  • fmw42 - 我正在尝试完全裁剪/删除黑色背景,而不创建矩形以丢失原始图像中的数据。我希望能够在基本的照片浏览器中打开图像并且看不到黑色背景,因此目标是清晰/不存在的背景。再次感谢你的帮助! :)

标签: python image opencv pixel threshold


【解决方案1】:

这是在 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()

阈值图像:

形态清洁图像:

轮廓图:

面具图片:

透明背景的结果:

【讨论】:

  • fmv42 - 真是太棒了!!感谢您展示获得最终结果的步骤和逻辑。我在我这边运行了你的脚本,它主要在我这边工作,但它仍然从原始图像中删除了一些像素,并用白色像素代替它们。在您的输出图像中,您还可以在图像的右下角看到几个切口(白色像素)。我假设这是由于可以调整的阈值设置,您可以推荐哪些特定参数?再次感谢您的帮助,非常感谢!
  • 是的,预计会有剪裁。不确定你可以在不带一些黑色的情况下对它们做很多事情。但是你可以使用形态接近于一个比切口大的圆形内核。如果您可以将图像中的纯黑色保留到背景区域,并将数据中的任何黑色像素设为灰色 1,那就更好了。这是经过校正的图像还是以任何方式从矩形原始图像处理的?如果是这样,请将原始数据中的黑色替换为1,这样可以在校正后为背景保留纯黑色。
  • fmv42 - 上面的图像是嵌入文档中的点云图像,因此显示的图像是从另一个生成的,因此是经过预处理的。您的解决方案在相应的 EO 图像上完美运行,该图像也是 .png 格式,但即使对于从源文档中保存为 .png 的图像,我仍然会得到一些像素的切口。您之前是否在 OpenCV 中使用过轮廓/抓取工具尝试过类似的技术?该解决方案几乎是万无一失的,但我会继续排除故障,再次感谢!
猜你喜欢
  • 2020-06-03
  • 1970-01-01
  • 2021-04-30
  • 2022-01-14
  • 2010-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多