Skimage: group labels with distance condition on outline
<p>I have used <em>skimage.measure.label</em> to get labels of my image but i was wondering if there was a function or a best way to group the labels with a distance condition on their outline.</p>

<p>Currently i use <em>skimage.measure.regionprops</em> to analyse each label then <em>skimage.segmentation.find_boundaries</em> to get the outline of each label then i get the coordinates, i check the distance between each points, i update the label if the distance match the condition and then i reuse <em>regionprops</em> to get right labels after grouping (i will post my code soon).</p>

<p>Currently work with this code:</p>

<pre><code>import math
import matplotlib.pyplot as plt
import numpy as np

from skimage.draw import ellipse
from skimage.measure import label, regionprops
from skimage.transform import rotate


image = np.zeros((600, 600))

rr, cc = ellipse(300, 350, 100, 220)
rr2, cc2 = ellipse(100, 100, 20, 50)
image[rr, cc] = 1
image[rr2, cc2] = 1

image = rotate(image, angle=15, order=0)

label_img = label(image)
regions = regionprops(label_img)

fig, ax = plt.subplots()
ax.imshow(image, cmap=plt.cm.gray)

for props in regions:
    y0, x0 = props.centroid
    orientation = props.orientation
    x1 = x0 + math.cos(orientation) * 0.5 * props.major_axis_length
    y1 = y0 - math.sin(orientation) * 0.5 * props.major_axis_length
    x2 = x0 - math.sin(orientation) * 0.5 * props.minor_axis_length
    y2 = y0 - math.cos(orientation) * 0.5 * props.minor_axis_length

    ax.plot((x0, x1), (y0, y1), '-r', linewidth=2.5)
    ax.plot((x0, x2), (y0, y2), '-r', linewidth=2.5)
    ax.plot(x0, y0, '.g', markersize=15)

    minr, minc, maxr, maxc = props.bbox
    bx = (minc, maxc, maxc, minc, minc)
    by = (minr, minr, maxr, maxr, minr)
    ax.plot(bx, by, '-b', linewidth=2.5)

ax.axis((0, 600, 600, 0))
plt.show()
</code></pre>

<p>This code work for grouping and display the result (blue is before, cyan is after):</p>

<p><a href="http://i.stack.imgur.com/j32Bp.png" rel="nofollow"><img src="http://i.stack.imgur.com/j32Bp.png" alt="label grouping"></a></p>

<pre><code>import math
import matplotlib.pyplot as plt
import numpy as np

from skimage.draw import ellipse
from skimage.measure import label, regionprops
from skimage.transform import rotate
from skimage.segmentation import find_boundaries

image = np.zeros((600, 600))

rr, cc = ellipse(300, 350, 100, 220)
rr2, cc2 = ellipse(100, 100, 20, 50)
rr3, cc3 = ellipse(200, 50, 20, 50)
image[rr, cc] = 1
image[rr2, cc2] = 1
image[rr3, cc3] = 1

image = rotate(image, angle=15, order=0)

pixel_distance = 100

# Labeling image
label_img = label(image)

# Applying regionprops
regions = regionprops(label_img)

# First draw before regroup with blue rectangles
fig, ax = plt.subplots()
ax.imshow(image, interpolation="none")

for props in regions:
    y0, x0 = props.centroid
    orientation = props.orientation
    x1 = x0 + math.cos(orientation) * 0.5 * props.major_axis_length
    y1 = y0 - math.sin(orientation) * 0.5 * props.major_axis_length
    x2 = x0 - math.sin(orientation) * 0.5 * props.minor_axis_length
    y2 = y0 - math.cos(orientation) * 0.5 * props.minor_axis_length

    ax.plot((x0, x1), (y0, y1), '-r', linewidth=2.5)
    ax.plot((x0, x2), (y0, y2), '-r', linewidth=2.5)
    ax.plot(x0, y0, '.g', markersize=15)

    minr, minc, maxr, maxc = props.bbox
    bx = (minc, maxc, maxc, minc, minc)
    by = (minr, minr, maxr, maxr, minr)
    ax.plot(bx, by, '-b', linewidth=2.5)

# Check distances for each label
for props in regions:

    # Get boundaries coordinates for that label
    label_boundaries = find_boundaries(label_img == props.label)
    bound_cord = np.column_stack(np.where(label_boundaries))

    # DEBUG: Draw boundaries
    # for cord in bound_cord:
    #     ax.plot(cord[1], cord[0], '.b', markersize=5)

    # We will compare each boundaries coordinates with the coordinates of all other label boundaries
    for j_props in regions:
        if j_props.label &gt; props.label:
            regrouped = False
            print "LABEL :", props.label, "VS :", j_props.label
            # Get boundaries coordinates for that label
            j_label_boundaries = find_boundaries(label_img == j_props.label)
            j_bound_cord = np.column_stack(np.where(j_label_boundaries))

            # Coordinates comparisons
            i = 0
            while not regrouped and i &lt; len(bound_cord):
                j = 0
                while not regrouped and j &lt; len(j_bound_cord):
                    # Apply distance condition
                    if math.hypot(j_bound_cord[j][1] - bound_cord[i][1], j_bound_cord[j][0] - bound_cord[i][0]) &lt;= pixel_distance:
                        # Assign the less label value
                        label_img[label_img == j_props.label] = min(props.label, j_props.label)
                        j_props.label = min(props.label, j_props.label)
                        regrouped = True
                    j += 1
                i += 1

# Second time we use regionprobs to get new labels informations
regions_2 = regionprops(label_img)

# Redraw after grouping with cyan rectangles
for props in regions_2:
    y0, x0 = props.centroid
    orientation = props.orientation
    x1 = x0 + math.cos(orientation) * 0.5 * props.major_axis_length
    y1 = y0 - math.sin(orientation) * 0.5 * props.major_axis_length
    x2 = x0 - math.sin(orientation) * 0.5 * props.minor_axis_length
    y2 = y0 - math.cos(orientation) * 0.5 * props.minor_axis_length

    ax.plot((x0, x1), (y0, y1), '-y', linewidth=2.5)
    ax.plot((x0, x2), (y0, y2), '-y', linewidth=2.5)
    ax.plot(x0, y0, '.c', markersize=15)

    minr, minc, maxr, maxc = props.bbox
    bx = (minc, maxc, maxc, minc, minc)
    by = (minr, minr, maxr, maxr, minr)
    ax.plot(bx, by, '-c', linewidth=2.5)

ax.axis((0, 600, 600, 0))
plt.show()
</code></pre>

python image-processing scikit-image skimage