我同意 amgaera。如果要查找轮廓,Python 中的 OpenCV 是可以使用的最佳工具之一。与他/她的帖子一样,使用findContours 方法并使用RETR_EXTERNAL 标志来获取形状的最外层轮廓。这里有一些可重现的代码来说明这一点。您首先需要安装 OpenCV 和 NumPy 才能进行此操作。
我不确定您使用的是什么平台,但是:
- 如果您使用的是 Linux,只需在
libopencv-dev 和 python-numpy 上执行 apt-get(即 sudo apt-get install libopencv-dev python-numpy)。
- 如果您使用的是 Mac OS,请安装 Homebrew,然后通过
brew install opencv 安装,然后通过 brew install numpy 安装。
- 如果您使用的是 Windows,最好的方法是通过 Christoph Gohlke 的 Windows 非官方 Python 包:
http://www.lfd.uci.edu/~gohlke/pythonlibs/ - 检查 OpenCV 包并安装它要求的所有依赖项,包括 @987654339 @ 您可以在此页面上找到。
无论如何,我拍了你的甜甜圈图像,然后只提取了带有甜甜圈的图像。换句话说,我创建了这个图像:
至于您的图像是 PNG 并具有 alpha 通道,这实际上并不重要。只要您在此图像中只包含一个对象,我们实际上根本不需要访问 Alpha 通道。下载此图像后,将其保存为 donut.png,然后继续运行此代码:
import cv2 # Import OpenCV
import numpy as np # Import NumPy
# Read in the image as grayscale - Note the 0 flag
im = cv2.imread('donut.png', 0)
# Run findContours - Note the RETR_EXTERNAL flag
# Also, we want to find the best contour possible with CHAIN_APPROX_NONE
contours, hierarchy = cv2.findContours(im.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# Create an output of all zeroes that has the same shape as the input
# image
out = np.zeros_like(im)
# On this output, draw all of the contours that we have detected
# in white, and set the thickness to be 3 pixels
cv2.drawContours(out, contours, -1, 255, 3)
# Spawn new windows that shows us the donut
# (in grayscale) and the detected contour
cv2.imshow('Donut', im)
cv2.imshow('Output Contour', out)
# Wait indefinitely until you push a key. Once you do, close the windows
cv2.waitKey(0)
cv2.destroyAllWindows()
让我们慢慢看代码。首先我们导入 OpenCV 和 NumPy 包。我将 NumPy 导入为 np,如果您到处查看 numpy 文档和教程,他们这样做是为了尽量减少打字。 OpenCV 和 NumPy 相互配合,这就是为什么你需要同时安装这两个包的原因。然后我们使用imread 读取图像。我将标志设置为0 以使图像灰度化以使事情变得简单。一旦我加载了图像,我就运行findContours,这个函数的输出输出了一个包含两个东西的元组:
-
contours - 这是一个数组结构,可为您提供图像中检测到的每个轮廓的 (x,y) 坐标。
-
hierarchy - 这包含有关您检测到的轮廓的其他信息,例如拓扑,但为了这篇文章,我们跳过它。
请注意,我指定了RETR_EXTERNAL 来检测对象的最外层轮廓。我还指定了CHAIN_APPROX_NONE 标志,以确保我们获得完整的轮廓而没有任何近似值。一旦我们检测到轮廓,我们就会创建一个全黑的新输出图像。这将包含我们检测到的甜甜圈外轮廓。创建此图像后,我们运行drawContours 方法。您指定要在其中显示轮廓的图像、之前创建的轮廓结构,并且 -1 标志表示要绘制图像中的所有轮廓。如果一切顺利,您应该只检测到一个轮廓。然后,您指定您希望轮廓看起来像什么颜色。在我们的例子中,我们希望它是白色的。之后,您指定要绘制轮廓的厚度。我选择了 3 像素的厚度。
我们要做的最后一件事是显示结果的样子。我调用imshow 来显示原始甜甜圈图像的外观(灰度)以及输出轮廓的外观。 imshow 不是故事的结局。在调用cv2.waitKey(0) 之前,您不会看到任何输出。现在的意思是你可以无限期地显示图像,直到你按下一个键。按下某个键后,cv2.destroyAllWindows() 调用将关闭所有生成的窗口。
这就是我得到的(一旦你重新排列窗口,使它们并排):
另外,如果您想保存图像,只需运行imwrite 即可保存图像。您指定要写入的图像的名称以及要访问的变量。因此,您可以执行以下操作:
cv2.imwrite('contour.png', out)
然后您将此轮廓图像保存到名为 contour.png 的文件中。
这应该足以让您入门。
祝你好运!