Pas*_*day 3 python image-processing
我有数百个PNG图像,我必须生成相应的黑白图像,显示对象的外部轮廓.源PNG图像具有alpha通道,因此图像的"无对象"部分是100%透明的.
棘手的部分是,如果物体上有洞,则不应在轮廓中看到那些洞.因此,如果源图像是例如甜甜圈,则相应的轮廓图像将是锯齿状的圆形线,中间没有同心的较小线.
这是一个示例图像,源及其轮廓: 
是否有可以执行此操作的库或命令行工具?理想情况下,可以从Python中使用的东西.
ray*_*ica 14
我同意amgaera.如果您想要查找轮廓,Python中的OpenCV是您可以使用的最佳工具之一.与他/她的帖子一样,使用该findContours方法并使用该RETR_EXTERNAL标志来获得形状的最外部轮廓.这里有一些可重现的代码供您说明这一点.您首先需要安装OpenCV并NumPy实现此目的.
我不确定你使用的是什么平台,但是:
apt-geton libopencv-dev和python-numpy(即sudo apt-get install libopencv-dev python-numpy). brew install opencv然后brew install numpy. http://www.lfd.uci.edu/~gohlke/pythonlibs/- 检查OpenCV软件包并安装它要求的所有依赖项,包括NumPy您可以在此页面上找到的依赖项.无论如何,我拍了你的甜甜圈图像,我用甜甜圈提取了图像.换句话说,我创建了这个图像:

至于你的图像是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()
Run Code Online (Sandbox Code Playgroud)
我们慢慢来看看代码吧.首先,我们导入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)
Run Code Online (Sandbox Code Playgroud)
然后,您将此轮廓图像保存到已命名的文件中contour.png.
这应该足以让你入门.
祝好运!
我会推荐 ImageMagick,它可以从这里免费获得。无论如何,它包含在许多 Linux 发行版中。它也有可用的 Python、Perl、PHP、C/C++ 绑定。
我只是从下面的命令行中使用它。
convert donut.png -channel A -morphology EdgeOut Diamond +channel -fx 'a' -negate output.jpg
Run Code Online (Sandbox Code Playgroud)
基本上,-channel A选择 alpha(透明度)并应用形态来提取不透明区域的轮廓。然后+channel告诉 ImageMagick 我现在再次访问所有频道。这-fx是一个自定义函数(运算符),我将输出图像的每个像素设置为a- 修改后的 alpha 通道中的 alpha 值。
已编辑
以下可能比使用上述fx运算符更快:
convert donut.png -channel RGBA -separate -delete 0-2 -morphology EdgeOut Diamond -negate output.png
Run Code Online (Sandbox Code Playgroud)
结果:

如果您有数百(或数千)张图像要勾勒轮廓,我会推荐 GNU Parallel,可从此处获得。然后它将使用您所有的 CPU 内核来快速完成工作。你的命令看起来像这样 - 但请先备份并处理副本,直到你掌握它的窍门!
parallel convert {} -channel A -morphology EdgeOut Diamond +channel -fx 'a' -negate {.}.jpg ::: *.png
Run Code Online (Sandbox Code Playgroud)
这表示将之后:::的所有内容用作要处理的文件。然后并行地,使用所有可用的内核,转换每个 PNG 文件并将其名称更改为相应的 JPEG 文件作为输出文件名。
| 归档时间: |
|
| 查看次数: |
8562 次 |
| 最近记录: |