【问题标题】:Removing Background Around Contour去除轮廓周围的背景
【发布时间】:2020-10-10 15:38:48
【问题描述】:

我只有几周的时间来学习使用 Python 和 OpenCV 编码,但 StackOverflow 已经帮助了我无数次。但是我似乎无法解决这个问题,所以决定问我的第一个问题。

  • 我正在尝试拍照
  • 按面积查找最大轮廓
  • 去除轮廓外的背景
  • 有效地从最大的“对象”中删除背景 图片。

我在最后一部分苦苦挣扎。我知道我需要以某种方式创建一个蒙版,然后将蒙版放在原始图像上。

如何创建正确类型的掩码?以及如何将蒙版放置在原始图像之上?

这是我的代码:

import cv2
import numpy as np

# Load image
image = cv2.imread('Resources/X.png')

# Grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Find Canny edges
edged = cv2.Canny(gray, 30, 200)

# Finding Contours
contours, hierarchy = cv2.findContours(edged,
                                       cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

cv2.imshow('Canny Edges After Contouring', edged)
print("Number of Contours found = " + str(len(contours)))
cv2.waitKey(0)

# Largest contour
c = max(contours, key=cv2.contourArea)


# Not sure what to do from here. Attempt below:
mask = np.zeros(image.shape, np.uint8)                  # What is this actually doing? what does np.unit8 mean?
cv2.drawContours(mask, c, -1, (255, 255, 255), 1)       # I am drawing the correct outline/contour

cv2.imshow('Mask', mask)
cv2.waitKey(0)

任何帮助将不胜感激。

谢谢 克里斯

编辑:

我设法做到了,但不确定我在做什么 :-( 我将如何获得不同的颜色背景?我想我必须用另一种颜色填充空白掩码? 也不确定按位函数实际上在做什么。

blank_mask = np.zeros(image.shape, dtype=np.uint8)
cv2.fillPoly(blank_mask, [c], (255,255,255))
blank_mask = cv2.cvtColor(blank_mask, cv2.COLOR_BGR2GRAY)
result = cv2.bitwise_and(original,original,mask=blank_mask)
cv2.imshow('Result', result)

【问题讨论】:

  • 将您的输入图像发布到一些免费的托管服务,并将 URL 放在这里
  • 嗨 fmw42。我用图片链接编辑了我的原始帖子。我实际上设法弄清楚并得到了结果。但是我不能说我真的知道发生了什么。我在函数上添加了一些问题。

标签: python opencv mask contour


【解决方案1】:

这是使用 Python/OpenCV 更改图像背景的一种方法。

  • 读取输入并获取其尺寸
  • 黑色阈值并反转以获得黑色背景上的白色
  • 从倒置阈值图像中获取最大轮廓
  • 将最大轮廓绘制为黑色背景上填充的白色作为蒙版
  • 创建倒置蒙版
  • 创建新的彩色背景图片
  • 将蒙版应用到图像
  • 将反转蒙版应用于背景色图像
  • 添加两张图片
  • 保存结果

import cv2
import numpy as np

# Read image
img = cv2.imread('shapes.png')
hh, ww = img.shape[:2]

# threshold on black
# Define lower and uppper limits of what we call "white-ish"
lower = np.array([0, 0, 0])
upper = np.array([0, 0, 0])

# Create mask to only select black
thresh = cv2.inRange(img, lower, upper)

# invert mask so shapes are white on black background
thresh_inv = 255 - thresh

# get the largest contour
contours = cv2.findContours(thresh_inv, 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 contour on black background as mask
mask = np.zeros((hh,ww), dtype=np.uint8)
cv2.drawContours(mask, [big_contour], 0, (255,255,255), cv2.FILLED)

# invert mask so shapes are white on black background
mask_inv = 255 - mask

# create new (blue) background
bckgnd = np.full_like(img, (255,0,0))

# apply mask to image
image_masked = cv2.bitwise_and(img, img, mask=mask)

# apply inverse mask to background
bckgnd_masked = cv2.bitwise_and(bckgnd, bckgnd, mask=mask_inv)

# add together
result = cv2.add(image_masked, bckgnd_masked)

# save results
cv2.imwrite('shapes_inverted_mask.jpg', mask_inv)
cv2.imwrite('shapes_masked.jpg', image_masked)
cv2.imwrite('shapes_bckgrnd_masked.jpg', bckgnd_masked )
cv2.imwrite('shapes_result.jpg', result)

cv2.imshow('mask', mask)
cv2.imshow('image_masked', image_masked)
cv2.imshow('bckgrnd_masked', bckgnd_masked)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

从最大轮廓屏蔽图像:

图像蒙版:

背景蒙版:

结果:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    • 2019-06-18
    • 2012-02-11
    • 1970-01-01
    • 2018-05-12
    • 2020-12-25
    • 2019-02-09
    相关资源
    最近更新 更多