2013-10-03 60 views
0

我需要查找图像中的所有封闭形状并获取其坐标。我需要Python中的这个,但是解释如何做到这一点也是足够的。如果你愿意,可以随意用Python代码回答。我已经搜索在谷歌很多,发现这两个东西:查找图像中的封闭形状

在第一个链接的答案描绘了给我的所有领域,而不是封闭的区域坐标。我不明白第二个链接中的第一个答案,有些评论说它不起作用。在第二环节的第二个答案不适用于相似图片的工作:

some image

我试图让自己的代码太多,但它比第二个需要较长的时间来计算,它有要快很多(并非真的很快,但至少快于1/10秒)。

我如何找到这些区域?

PS:图像中有一些线条不是封闭形状的一部分。

+0

对图像内容有任何假设吗?如果不是,您如何准确定义封闭区域? – BartoszKP

+0

您的图像是自然图像还是由合成物体组成,如您提到的示例。 你的坐标是什么意思?在示例图像的情况下,您需要黑色区域或白色区域的坐标吗? –

+0

BartoszKP,内容是用pygame(曲线和直线)绘制的一些黑线。 Koustav Ghosal,它可以是用一些线条绘制的所有东西,坐标我指的是一个封闭区域中的一个点,封闭区域是白色区域。 – user2746752

回答

2

这里有一个函数find_groups,它将图像中的每个像素分为三类:自由,封闭和边框,以及一个函数print_groups以可读的方式进行测试。

from collections import namedtuple 
from copy import deepcopy 

def find_groups(inpixels): 
    """ 
    Group the pixels in the image into three categories: free, closed, and 
    border. 
     free: A white pixel with a path to outside the image. 
     closed: A white pixels with no path to outside the image. 
     border: A black pixel. 

    Params: 
     pixels: A collection of columns of rows of pixels. 0 is black 1 is 
       white. 

    Return: 
     PixelGroups with attributes free, closed and border. 
     Each is a list of tuples (y, x). 
    """ 

    # Pad the entire image with white pixels. 
    width = len(inpixels[0]) + 2 
    height = len(inpixels) + 2 
    pixels = deepcopy(inpixels) 
    for y in pixels: 
     y.insert(0, 1) 
     y.append(1) 
    pixels.insert(0, [1 for x in range(width)]) 
    pixels.append([1 for x in range(width)]) 

    # The free pixels are found through a breadth first traversal. 
    queue = [(0,0)] 
    visited = [(0,0)] 
    while queue: 
     y, x = queue.pop(0) 

     adjacent = ((y+1, x), (y-1, x), (y, x+1), (y, x-1)) 
     for n in adjacent: 
      if (-1 < n[0] < height and -1 < n[1] < width and 
             not n in visited and 
            pixels[n[0]][n[1]] == 1): 
       queue.append(n) 
       visited.append(n) 

    # Remove the padding and make the categories. 
    freecoords = [(y-1, x-1) for (y, x) in visited if 
       (0 < y < height-1 and 0 < x < width-1)] 
    allcoords = [(y, x) for y in range(height-2) for x in range(width-2)] 
    complement = [i for i in allcoords if not i in freecoords] 
    bordercoords = [(y, x) for (y, x) in complement if inpixels[y][x] == 0] 
    closedcoords = [(y, x) for (y, x) in complement if inpixels[y][x] == 1] 

    PixelGroups = namedtuple('PixelGroups', ['free', 'closed', 'border']) 
    return PixelGroups(freecoords, closedcoords, bordercoords) 

def print_groups(ysize, xsize, pixelgroups): 
    ys= [] 
    for y in range(ysize): 
     xs = [] 
     for x in range(xsize): 
      if (y, x) in pixelgroups.free: 
       xs.append('.') 
      elif (y, x) in pixelgroups.closed: 
       xs.append('X') 
      elif (y, x) in pixelgroups.border: 
       xs.append('#') 
     ys.append(xs) 
    print('\n'.join([' '.join(k) for k in ys])) 

我们使用它:

pixels = [[0, 1, 0, 0, 1, 1], 
      [1, 0, 1, 1, 0, 1], 
      [1, 0, 1, 1, 0, 1], 
      [1, 0 ,1 ,1 ,0, 1], 
      [1, 0, 1 ,0 ,1, 1], 
      [1, 0, 0, 1, 1, 1], 
      [1, 1, 1, 1, 1, 1]] 
pixelgroups = find_groups(pixels) 
print_groups(7, 6, pixelgroups) 
print("closed: " + str(pixelgroups.closed)) 

输出:

# . # # . . 
. # X X # . 
. # X X # . 
. # X X # . 
. # X # . . 
. # # . . . 
. . . . . . 

closed: [(1, 2), (1, 3), (2, 2), (2, 3), (3, 2), (3, 3), (4, 2)] 

你会发现随机点和条纹被归类为边界。但是你总是可以区分真实的边界和条纹如下。

# pseudo code 
realborders = [i for i in pixelgroups.border if i has an adjacent closed pixel] 
streaks = [otherwise] 
+0

在你的例子中有一些代码遗漏了,“不是在访问和”后面有什么? – user2746752

+0

而且我认为如果一条不在封闭形状的线条碰到图像边框,它就不起作用。 – user2746752

+0

@ user2746752好点。我得到了一切工作并更新了这篇文章。为了解决边界问题,该函数现在用白色像素填充图像,以便它可以绕过任何东西。 –