【问题标题】:Concave hull with missing edges缺少边缘的凹形船体
【发布时间】:2014-09-08 23:56:47
【问题描述】:

我有一个二进制掩码,我想从中提取轮廓。二进制掩码的所有“外部”边缘都是“真实边缘”,概率非常高。保持这些边缘固定,我现在的目标是插入“缺失”边缘(示例图像和下面的所需结果)。我曾尝试使用 Delaunay 三角测量,但没有取得多大成功(参见下面的代码)。但是,我什至不确定这是最好的方法,因为在此过程中我会从“真实边缘”中丢失一些细节。

Delaunay 三角测量在这里合适吗?如果是这样,下面的代码有什么问题?有没有更好的算法来解决这类问题?这如何在 Python 中实现?

当前代码(不起作用)

import numpy as np
from scipy.spatial import Delaunay
from descartes import PolygonPatch
from shapely.geometry import MultiLineString
from shapely.ops import cascaded_union, polygonize
from skimage.draw import polygon
from skimage import segmentation, morphology

def triangulate(mask, alpha=1000):

  contours = measure.find_contours(mask, 0.8)

  points = []

  for n, contour in enumerate(contours):

    for m in xrange(0, len(contour[:, 0])):
      y = contour[:, 0][m]
      x = contour[:, 1][m]
      points.append([y, x])

  points = np.asarray(points)

  tri = Delaunay(points)
  edges = set()
  edge_points = []

  def add_edge(i, j):
    if (i, j) in edges or (j, i) in edges: return
    edges.add( (i, j) )
    edge_points.append(points[ [i, j] ])

  for ia, ib, ic in tri.vertices:
    pa = points[ia]
    pb = points[ib]
    pc = points[ic]

    # Lengths of sides of triangle
    a = math.sqrt((pa[0]-pb[0])**2 + (pa[1]-pb[1])**2)
    b = math.sqrt((pb[0]-pc[0])**2 + (pb[1]-pc[1])**2)
    c = math.sqrt((pc[0]-pa[0])**2 + (pc[1]-pa[1])**2)

    # Semiperimeter of triangle
    s = (a + b + c)/2.0

    # Area of triangle by Heron's formula
    try:
      area = math.sqrt(s*(s-a)*(s-b)*(s-c))
      circum_r = a*b*c/(4.0*area)

      # Here's the radius filter.
      #if circum_r < 1.0/alpha:
      if circum_r < alpha:
          add_edge(ia, ib)
          add_edge(ib, ic)
          add_edge(ic, ia)
    except:
      print('Triangulation error')

  m = MultiLineString(edge_points)
  triangles = list(polygonize(m))

  poly = PolygonPatch(cascaded_union(triangles), alpha=0.5)

  vertices = poly.get_path().vertices

  rr, cc = polygon(vertices[:,0], vertices[:,1])

  img = np.zeros(im.shape)
  img[rr, cc] = 1

  return img

【问题讨论】:

  • 你研究过 OpenCV 吗?对于这类东西,它有很多非常有用的功能。 (我认为拉普拉斯算子在这里可能有用)。
  • 我认为您正在寻找的是所谓的活动轮廓,尤其是。测地线活动轮廓。一个快速的谷歌搜索发现了这个 python 实现:github.com/pmneila/morphsnakes。我没有尝试过,但示例图像看起来与您的问题非常相似。
  • 所以你在电脑上做罗夏? ;-)
  • 看看 Alpha 形状。

标签: python image-processing interpolation triangulation delaunay


【解决方案1】:

正如 nikie 指出的那样,如果性能不是要求,morphological snakes 将解决您的问题。

当您增加迭代次数时,蛇往往会完美地掩盖形状,但这不是您想要的,因此您需要找出有效的参数组合。

我玩了一下,找到了一个很好的近似值:

对于这个形状,我使用了以下代码:

def test_concave():
    # Load the image.
    imgcolor = imread("testimages/concave_hull.jpg")/255.0
    img = rgb2gray(imgcolor)

    # g(I)
    gI = morphsnakes.gborders(img, alpha=1000, sigma=7)

    # Morphological GAC. Initialization of the level-set.
    mgac = morphsnakes.MorphGAC(gI, smoothing=3, threshold=0.55, balloon=-1)
    mgac.levelset = circle_levelset(img.shape, (50, 199), 200)

    # Visual evolution.
    ppl.figure()
    morphsnakes.evolve_visual(mgac, num_iters=62, background=imgcolor)


if __name__ == '__main__':
    print """"""
    test_concave()
    ppl.show()

【讨论】:

  • 我想接受这个答案,但我不确定普遍性。对于不一定了解不同参数背后的数学原理的人,您能否添加一些关于如何找到合适(和可概括)参数的指导?
【解决方案2】:

凸包得到外边界,然后凸缺陷看最近的真实边缘离包有多远。

如果距离很小,则使用该轮廓作为真正的外部,否则如果缺陷很大,则它是真正的间隙,并使用相邻点之间的凸边界

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-28
    • 2011-04-22
    • 2015-07-13
    • 1970-01-01
    • 2016-09-05
    • 1970-01-01
    • 2013-02-24
    • 2010-10-16
    相关资源
    最近更新 更多