Esempio n. 1
0
def levelSetMap(image, level = 0, sigma = None):
    siv = hasattr(image, "siv") and image.siv or vigra.SplineImageView3(image)

    zc = findZeroCrossingsOnGrid(siv, level)
    result = geomap.GeoMap(zc, [], image.size())

    msg = progress.StatusMessage("- following level set contours")
    next = progress.ProgressHook(msg).rangeTicker(result.nodeCount)

    for node in result.nodeIter():
        next()
        if node.isIsolated():
            followContour(siv, level, result, node.label(), 0.1)

    maputils.mergeDegree2Nodes(result)
    result = maputils.copyMapContents( # compress labels and simplify polygons
        result, edgeTransform = lambda e: \
        geomap.simplifyPolygon(e, 0.05, 0.2))[0]
    #maputils.connectBorderNodes(result, 0.01)

    result.sortEdgesEventually(0.4, 0.01)
    result.initializeMap()
    return result
Esempio n. 2
0
def levelSetMap(image, level=0, sigma=None):
    siv = hasattr(image, "siv") and image.siv or vigra.SplineImageView3(image)

    zc = findZeroCrossingsOnGrid(siv, level)
    result = geomap.GeoMap(zc, [], image.size())

    msg = progress.StatusMessage("- following level set contours")
    next = progress.ProgressHook(msg).rangeTicker(result.nodeCount)

    for node in result.nodeIter():
        next()
        if node.isIsolated():
            followContour(siv, level, result, node.label(), 0.1)

    maputils.mergeDegree2Nodes(result)
    result = maputils.copyMapContents( # compress labels and simplify polygons
        result, edgeTransform = lambda e: \
        geomap.simplifyPolygon(e, 0.05, 0.2))[0]
    #maputils.connectBorderNodes(result, 0.01)

    result.sortEdgesEventually(0.4, 0.01)
    result.initializeMap()
    return result
Esempio n. 3
0
def marchingSquares(image, level = 0, variant = True, border = True,
                    initialize = True, markOuter = 1):
    """Return a new GeoMap with sub-pixel level contours extracted by
    the marching squares method.  (Pixels with values < level are
    separated from pixels >= level.)

    If the image does not have an attribute 'siv', standard linear
    interpolation is used.  If image.siv exists, it should be a
    SplineImageView that is used for the Newton-Raphson method to
    perform another subsequent sub-pixel correction.

    The optional parameter `variant` determines the handling of the
    ambiguous diagonal configuration:

    `variant` = True (default)
      always let the two sampling points above `level` be connected

    `variant` = False
      always let the two opposite sampling points < `level` be connected

    `variant` = SplineImageView(...)
      for each ambiguous configuration, check the midpoint of the
      square; then handle as if variant = (midpoint >= level)

    If `initialize` is a true value (default), the map will be
    initialized.

    If markOuter is != 0, the faces above(outer == 1) / below(outer == -1)
    the threshold are marked with the OUTER_FACE flag (this only works
    if the map is initialized)."""

    connections1 = ((1, 0), (0, 2), (1, 2), (3, 1), (3, 0), (0, 2), (3, 1), (3, 2), (2, 3), (1, 0), (2, 3), (0, 3), (1, 3), (2, 1), (2, 0), (0, 1))
    connections2 = ((1, 0), (0, 2), (1, 2), (3, 1), (3, 0), (0, 1), (3, 2), (3, 2), (2, 3), (1, 3), (2, 0), (0, 3), (1, 3), (2, 1), (2, 0), (0, 1))
    configurations = (0, 0, 1, 2, 3, 4, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 16)

    result = geomap.GeoMap(image.shape)

    def addNodeDirectX(x, y, ofs):
        pos = Vector2(x+ofs, y)
        # out of three successive pixels, the middle one may be the
        # threshold, then we would get duplicate points already in the
        # horizontal pass:
        node = result.nearestNode(pos, 1e-8)
        return node or result.addNode(pos)

    def addNodeDirectY(x, y, ofs):
        pos = Vector2(x, y+ofs)
        node = result.nearestNode(pos, 1e-8) # already exists? (e.g. hNodes?)
        return node or result.addNode(pos)

    def addNodeNewtonRefinementX(x, y, ofs):
        for i in range(100):
            o = -(image.siv(x+ofs, y)-level) / image.siv.dx(x+ofs, y)
            if abs(o) > 0.5:
                o = vigra.sign(o)*0.05
            ofs += o
            if ofs <= 0 or ofs >= 1:
                ofs -= o
                break
            if abs(o) < 1e-4:
                break
        return addNodeDirectX(x, y, ofs)

    def addNodeNewtonRefinementY(x, y, ofs):
        for i in range(100):
            o = -(image.siv(x, y+ofs)-level) / image.siv.dy(x, y+ofs)
            if abs(o) > 0.5:
                o = vigra.sign(o)*0.05
            ofs += o
            if ofs <= 0 or ofs >= 1:
                ofs -= o
                break
            if abs(o) < 1e-4:
                break
        return addNodeDirectY(y, y, ofs)

    if hasattr(image, "siv"):
        addNodeX = addNodeNewtonRefinementX
        addNodeY = addNodeNewtonRefinementY
    else:
        addNodeX = addNodeDirectX
        addNodeY = addNodeDirectY

    hNodes = vigra.Image(image.shape, numpy.uint32)
    v1 = image[:-1]
    v2 = image[1:]
    ofs = (level - v1)/(v2 - v1)
    for x, y in numpy.transpose(numpy.nonzero((v1 < level) != (v2 < level))):
        hNodes[x, y] = addNodeX(x, y, ofs).label()

    vNodes = vigra.Image(image.shape, numpy.uint32)
    v1 = image[:,:-1]
    v2 = image[:,1:]
    ofs = (level - v1)/(v2 - v1)
    for x, y in numpy.transpose(numpy.nonzero((v1 < level) != (v2 < level))):
        vNodes[x, y] = addNodeY(x, y, ofs).label()

    nodes = (hNodes, vNodes, vNodes, hNodes)
    offsets = numpy.array(((0, 0), (0, 0), (1, 0), (0, 1)))

    defaultConnections = connections1
    if variant == False:
        defaultConnections = connections2
    if isinstance(variant, bool):
        variant = None

    configurations = ((image[:-1,:-1] < level) +
                      (image[ 1:,:-1] < level)*2 +
                      (image[:-1, 1:] < level)*4 +
                      (image[ 1:, 1:] < level)*8)
    for x, y in numpy.transpose(numpy.nonzero(configurations)):
        config = configurations[x,y]

        connections = connections1
        if variant is not None and config in (6, 9):
            if variant(x + 0.5, y + 0.5) < level:
                connections = connections2

        for s, e in connections[
            configurations[config]:configurations[config+1]]:
            startNode = result.node(int(nodes[s][tuple(offsets[s] + (x, y))]))
            endNode   = result.node(int(nodes[e][tuple(offsets[e] + (x, y))]))
            if startNode != endNode:
                result.addEdge(startNode, endNode,
                               [startNode.position(), endNode.position()])

    maputils.mergeDegree2Nodes(result) # node suppression
    result = maputils.copyMapContents(result)[0] # compress edge labels

    if border:
        maputils.connectBorderNodes(result, 0.5)
        result.sortEdgesEventually(0.4, 0.01)

    if not initialize:
        return result

    result.initializeMap()
    if markOuter:
        markOuter = markOuter > 0
        it = result.faceIter()
        if border:
            it.next().setFlag(flag_constants.OUTER_FACE)
        for face in it:
            face.setFlag(flag_constants.OUTER_FACE,
                         (face.contours().next().label() < 0) == markOuter)

    return result
Esempio n. 4
0
def marchingSquares(image,
                    level=0,
                    variant=True,
                    border=True,
                    initialize=True,
                    markOuter=1):
    """Return a new GeoMap with sub-pixel level contours extracted by
    the marching squares method.  (Pixels with values < level are
    separated from pixels >= level.)

    If the image does not have an attribute 'siv', standard linear
    interpolation is used.  If image.siv exists, it should be a
    SplineImageView that is used for the Newton-Raphson method to
    perform another subsequent sub-pixel correction.

    The optional parameter `variant` determines the handling of the
    ambiguous diagonal configuration:

    `variant` = True (default)
      always let the two sampling points above `level` be connected

    `variant` = False
      always let the two opposite sampling points < `level` be connected

    `variant` = SplineImageView(...)
      for each ambiguous configuration, check the midpoint of the
      square; then handle as if variant = (midpoint >= level)

    If `initialize` is a true value (default), the map will be
    initialized.

    If markOuter is != 0, the faces above(outer == 1) / below(outer == -1)
    the threshold are marked with the OUTER_FACE flag (this only works
    if the map is initialized)."""

    connections1 = ((1, 0), (0, 2), (1, 2), (3, 1), (3, 0), (0, 2), (3, 1),
                    (3, 2), (2, 3), (1, 0), (2, 3), (0, 3), (1, 3), (2, 1),
                    (2, 0), (0, 1))
    connections2 = ((1, 0), (0, 2), (1, 2), (3, 1), (3, 0), (0, 1), (3, 2),
                    (3, 2), (2, 3), (1, 3), (2, 0), (0, 3), (1, 3), (2, 1),
                    (2, 0), (0, 1))
    configurations = (0, 0, 1, 2, 3, 4, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 16)

    result = geomap.GeoMap(image.shape)

    def addNodeDirectX(x, y, ofs):
        pos = Vector2(x + ofs, y)
        # out of three successive pixels, the middle one may be the
        # threshold, then we would get duplicate points already in the
        # horizontal pass:
        node = result.nearestNode(pos, 1e-8)
        return node or result.addNode(pos)

    def addNodeDirectY(x, y, ofs):
        pos = Vector2(x, y + ofs)
        node = result.nearestNode(pos, 1e-8)  # already exists? (e.g. hNodes?)
        return node or result.addNode(pos)

    def addNodeNewtonRefinementX(x, y, ofs):
        for i in range(100):
            o = -(image.siv(x + ofs, y) - level) / image.siv.dx(x + ofs, y)
            if abs(o) > 0.5:
                o = vigra.sign(o) * 0.05
            ofs += o
            if ofs <= 0 or ofs >= 1:
                ofs -= o
                break
            if abs(o) < 1e-4:
                break
        return addNodeDirectX(x, y, ofs)

    def addNodeNewtonRefinementY(x, y, ofs):
        for i in range(100):
            o = -(image.siv(x, y + ofs) - level) / image.siv.dy(x, y + ofs)
            if abs(o) > 0.5:
                o = vigra.sign(o) * 0.05
            ofs += o
            if ofs <= 0 or ofs >= 1:
                ofs -= o
                break
            if abs(o) < 1e-4:
                break
        return addNodeDirectY(y, y, ofs)

    if hasattr(image, "siv"):
        addNodeX = addNodeNewtonRefinementX
        addNodeY = addNodeNewtonRefinementY
    else:
        addNodeX = addNodeDirectX
        addNodeY = addNodeDirectY

    hNodes = vigra.Image(image.shape, numpy.uint32)
    v1 = image[:-1]
    v2 = image[1:]
    ofs = (level - v1) / (v2 - v1)
    for x, y in numpy.transpose(numpy.nonzero((v1 < level) != (v2 < level))):
        hNodes[x, y] = addNodeX(x, y, ofs).label()

    vNodes = vigra.Image(image.shape, numpy.uint32)
    v1 = image[:, :-1]
    v2 = image[:, 1:]
    ofs = (level - v1) / (v2 - v1)
    for x, y in numpy.transpose(numpy.nonzero((v1 < level) != (v2 < level))):
        vNodes[x, y] = addNodeY(x, y, ofs).label()

    nodes = (hNodes, vNodes, vNodes, hNodes)
    offsets = numpy.array(((0, 0), (0, 0), (1, 0), (0, 1)))

    defaultConnections = connections1
    if variant == False:
        defaultConnections = connections2
    if isinstance(variant, bool):
        variant = None

    configurations = ((image[:-1, :-1] < level) +
                      (image[1:, :-1] < level) * 2 +
                      (image[:-1, 1:] < level) * 4 +
                      (image[1:, 1:] < level) * 8)
    for x, y in numpy.transpose(numpy.nonzero(configurations)):
        config = configurations[x, y]

        connections = connections1
        if variant is not None and config in (6, 9):
            if variant(x + 0.5, y + 0.5) < level:
                connections = connections2

        for s, e in connections[configurations[config]:configurations[config +
                                                                      1]]:
            startNode = result.node(int(nodes[s][tuple(offsets[s] + (x, y))]))
            endNode = result.node(int(nodes[e][tuple(offsets[e] + (x, y))]))
            if startNode != endNode:
                result.addEdge(startNode, endNode,
                               [startNode.position(),
                                endNode.position()])

    maputils.mergeDegree2Nodes(result)  # node suppression
    result = maputils.copyMapContents(result)[0]  # compress edge labels

    if border:
        maputils.connectBorderNodes(result, 0.5)
        result.sortEdgesEventually(0.4, 0.01)

    if not initialize:
        return result

    result.initializeMap()
    if markOuter:
        markOuter = markOuter > 0
        it = result.faceIter()
        if border:
            it.next().setFlag(flag_constants.OUTER_FACE)
        for face in it:
            face.setFlag(flag_constants.OUTER_FACE,
                         (face.contours().next().label() < 0) == markOuter)

    return result