fixing tests

This commit is contained in:
Guillem Palou Visa
2013-12-24 16:18:57 +01:00
parent e68ab76b24
commit 64d945da71
3 changed files with 145 additions and 121 deletions
+101 -100
View File
@@ -9,107 +9,10 @@ cimport numpy as cnp
from skimage.util import regular_grid
def _enforce_label_connectivity_cython(Py_ssize_t[:, :, ::1] nearest_segments,
Py_ssize_t n_segments,
int min_size,
int max_size):
""" Helper function to remove small disconnected regions from the labels
Parameters
----------
nearest_segments : 3D array of int, shape (Z, Y, X)
The label field/superpixels found by SLIC.
n_segments: int
number of specified segments
min_size: int
minimum size of the segment
max_size: int
maximum size of the segment. This is done for performance reasons,
to pre-allocate a sufficiently large array for the breadth first search
Returns
-------
connected_nearest_segments : 3D array of int, shape (Z, Y, X)
A label field with connected labels starting at label=1
"""
#get image dimensions
cdef Py_ssize_t depth, height, width
depth = nearest_segments.shape[0]
height = nearest_segments.shape[1]
width = nearest_segments.shape[2]
#neighborhood arrays
cdef Py_ssize_t[:] ddx = np.array((1,-1,0,0,0,0))
cdef Py_ssize_t[:] ddy = np.array((0,0,1,-1,0,0))
cdef Py_ssize_t[:] ddz = np.array((0,0,0,0,1,-1))
#new object with connected segments
cdef Py_ssize_t[:, :, ::1] new_nearest_segments \
= np.zeros((depth, height, width), dtype=np.intp)
cdef Py_ssize_t current_new_label = 0
cdef Py_ssize_t label = 0
#variables for the breadth first search
cdef Py_ssize_t count = 1
cdef Py_ssize_t p = 0
cdef Py_ssize_t adjacent
cdef Py_ssize_t zz,yy,xx
cdef Py_ssize_t[:, :] coord_list \
= np.zeros((max_size,3), dtype=np.intp)
#loop through all image
for z in range(depth):
for y in range(height):
for x in range(width):
if (new_nearest_segments[z,y,x] > 0):
continue
#find the component size
adjacent = 0
label = nearest_segments[z,y,x]
current_new_label = current_new_label+1
new_nearest_segments[z,y,x] = current_new_label
count = 1
p = 0
coord_list[p,0] = z
coord_list[p,1] = y
coord_list[p,2] = x
#perform a breadth first search to find the size of the connected component
while (p != count):
for i in range(6):
zz = coord_list[p,0] + ddz[i]
yy = coord_list[p,1] + ddy[i]
xx = coord_list[p,2] + ddx[i]
if (xx >= 0 and xx < width and yy >= 0 and yy < height and zz >= 0 and zz < depth):
if (nearest_segments[zz,yy,xx] == label and new_nearest_segments[zz,yy,xx] == 0):
new_nearest_segments[zz,yy,xx] = current_new_label
coord_list[count,0] = zz
coord_list[count,1] = yy
coord_list[count,2] = xx
count = count + 1
elif (new_nearest_segments[zz,yy,xx] > 0 and new_nearest_segments[zz,yy,xx] != current_new_label):
adjacent = new_nearest_segments[zz,yy,xx]
p = p + 1
#change to an adjacent one, like in the original paper
if (count < min_size):
#print("Changing segment {0} label {1} ".format(current_new_label, label))
for i in range(count):
new_nearest_segments[coord_list[i,0],coord_list[i,1],coord_list[i,2]] = adjacent
return np.asarray(new_nearest_segments)
def _slic_cython(double[:, :, :, ::1] image_zyx,
double[:, ::1] segments,
Py_ssize_t max_iter,
double[::1] spacing,
int enforce_connectivity,
Py_ssize_t min_size = True):
double[::1] spacing):
"""Helper function for SLIC segmentation.
Parameters
@@ -124,8 +27,6 @@ def _slic_cython(double[:, :, :, ::1] image_zyx,
The voxel spacing along each image dimension. This parameter
controls the weights of the distances along z, y, and x during
k-means clustering.
enforce_connectivity: int indicating whether the returned label
field must have connected labels
Returns
-------
@@ -244,3 +145,103 @@ def _slic_cython(double[:, :, :, ::1] image_zyx,
segments[k, c] /= n_segment_elems[k]
return np.asarray(nearest_segments)
def _enforce_label_connectivity_cython(Py_ssize_t[:, :, ::1] segments,
Py_ssize_t n_segments,
int min_size,
int max_size):
""" Helper function to remove small disconnected regions from the labels
Parameters
----------
segments : 3D array of int, shape (Z, Y, X)
The label field/superpixels found by SLIC.
n_segments: int
number of specified segments
min_size: int
minimum size of the segment
max_size: int
maximum size of the segment. This is done for performance reasons,
to pre-allocate a sufficiently large array for the breadth first search
Returns
-------
connected_segments : 3D array of int, shape (Z, Y, X)
A label field with connected labels starting at label=1
"""
#get image dimensions
cdef Py_ssize_t depth, height, width
depth = segments.shape[0]
height = segments.shape[1]
width = segments.shape[2]
#neighborhood arrays
cdef Py_ssize_t[::1] ddx = np.array((1, -1, 0, 0, 0, 0))
cdef Py_ssize_t[::1] ddy = np.array((0, 0, 1, -1, 0, 0))
cdef Py_ssize_t[::1] ddz = np.array((0, 0, 0, 0, 1, -1))
#new object with connected segments
cdef Py_ssize_t[:, :, ::1] connected_segments \
= np.zeros_like(segments, dtype=np.intp)
cdef Py_ssize_t current_new_label = 0
cdef Py_ssize_t label = 0
#variables for the breadth first search
cdef Py_ssize_t current_segment_size = 1
cdef Py_ssize_t bfs_visited = 0
cdef Py_ssize_t adjacent
cdef Py_ssize_t zz, yy, xx
cdef Py_ssize_t[:, ::1] coord_list = np.zeros((max_size, 3), dtype=np.intp)
#loop through all image
for z in range(depth):
for y in range(height):
for x in range(width):
if connected_segments[z, y, x] > 0:
continue
#find the component size
adjacent = 0
label = segments[z, y, x]
current_new_label += 1
connected_segments[z, y, x] = current_new_label
current_segment_size = 1
bfs_visited = 0
coord_list[bfs_visited, 0] = z
coord_list[bfs_visited, 1] = y
coord_list[bfs_visited, 2] = x
#perform a breadth first search to find
# the size of the connected component
while bfs_visited != current_segment_size:
for i in range(6):
zz = coord_list[bfs_visited, 0] + ddz[i]
yy = coord_list[bfs_visited, 1] + ddy[i]
xx = coord_list[bfs_visited, 2] + ddx[i]
if (xx >= 0 and xx < width and
yy >= 0 and yy < height and
zz >= 0 and zz < depth):
if (segments[zz, yy, xx] == label and
connected_segments[zz, yy, xx] == 0):
connected_segments[zz, yy, xx] = \
current_new_label
coord_list[current_segment_size, 0] = zz
coord_list[current_segment_size, 1] = yy
coord_list[current_segment_size, 2] = xx
current_segment_size += 1
elif (connected_segments[zz, yy, xx] > 0 and
connected_segments[zz, yy, xx] != current_new_label):
adjacent = connected_segments[zz, yy, xx]
bfs_visited += 1
#change to an adjacent one, like in the original paper
if current_segment_size < min_size:
for i in range(current_segment_size):
connected_segments[coord_list[i, 0],
coord_list[i, 1],
coord_list[i, 2]] = adjacent
return np.asarray(connected_segments)
+6 -6
View File
@@ -50,10 +50,10 @@ def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=None,
Synonym for `compactness`. This keyword is deprecated.
enforce_connectivity: bool, optional
Whether the generated segments are connected or not
min_size_factor: float
min_size_factor: float, optional
proportion of the minimum segment size to be removed with respect
to the supposed segment size (depth*width*height/n_segments)
max_size_factor: float
max_size_factor: float, optional
proportion of the maximum connected segment size. A value of 3 works
in most of the cases.
Returns
@@ -169,14 +169,14 @@ def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=None,
ratio = float(max((step_z, step_y, step_x))) / compactness
image = np.ascontiguousarray(image * ratio)
labels = _slic_cython(image, segments, max_iter, spacing, enforce_connectivity)
labels = _slic_cython(image, segments, max_iter, spacing)
if (enforce_connectivity):
segment_size = depth*height*width/n_segments
segment_size = depth * height * width / n_segments
labels = _enforce_label_connectivity_cython(labels,
n_segments,
min_size_factor*segment_size,
max_size_factor*segment_size)
min_size_factor * segment_size,
max_size_factor * segment_size)
if is_2d:
labels = labels[0]
+38 -15
View File
@@ -21,10 +21,10 @@ def test_color_2d():
# we expect 4 segments
assert_equal(len(np.unique(seg)), 4)
assert_equal(seg.shape, img.shape[:-1])
assert_equal(seg[:10, :10], 0)
assert_equal(seg[10:, :10], 2)
assert_equal(seg[:10, 10:], 1)
assert_equal(seg[10:, 10:], 3)
assert_equal(seg[:10, :10], 1)
assert_equal(seg[10:, :10], 3)
assert_equal(seg[:10, 10:], 2)
assert_equal(seg[10:, 10:], 4)
def test_gray_2d():
@@ -41,10 +41,10 @@ def test_gray_2d():
assert_equal(len(np.unique(seg)), 4)
assert_equal(seg.shape, img.shape)
assert_equal(seg[:10, :10], 0)
assert_equal(seg[10:, :10], 2)
assert_equal(seg[:10, 10:], 1)
assert_equal(seg[10:, 10:], 3)
assert_equal(seg[:10, :10], 1)
assert_equal(seg[10:, :10], 3)
assert_equal(seg[:10, 10:], 2)
assert_equal(seg[10:, 10:], 4)
def test_color_3d():
@@ -65,7 +65,7 @@ def test_color_3d():
assert_equal(len(np.unique(seg)), 8)
for s, c in zip(slices, range(8)):
assert_equal(seg[s], c)
assert_equal(seg[s], c + 1)
def test_gray_3d():
@@ -76,7 +76,7 @@ def test_gray_3d():
midpoint = dim_size // 2
slices.append((slice(None, midpoint), slice(midpoint, None)))
slices = list(it.product(*slices))
shades = np.arange(0, 1.000001, 1.0/7)
shades = np.arange(0, 1.000001, 1.0 / 7)
for s, sh in zip(slices, shades):
img[s] = sh
img += 0.001 * rnd.normal(size=img.shape)
@@ -87,7 +87,7 @@ def test_gray_3d():
assert_equal(len(np.unique(seg)), 8)
for s, c in zip(slices, range(8)):
assert_equal(seg[s], c)
assert_equal(seg[s], c + 1)
def test_list_sigma():
@@ -96,7 +96,7 @@ def test_list_sigma():
[0, 0, 0, 1, 1, 1]], np.float)
img += 0.1 * rnd.normal(size=img.shape)
result_sigma = np.array([[0, 0, 0, 1, 1, 1],
[0, 0, 0, 1, 1, 1]], np.int)
[0, 0, 0, 1, 1, 1]], np.int) + 1
seg_sigma = slic(img, n_segments=2, sigma=[1, 50, 1], multichannel=False)
assert_equal(seg_sigma, result_sigma)
@@ -106,9 +106,9 @@ def test_spacing():
img = np.array([[1, 1, 1, 0, 0],
[1, 1, 0, 0, 0]], np.float)
result_non_spaced = np.array([[0, 0, 0, 1, 1],
[0, 0, 1, 1, 1]], np.int)
[0, 0, 1, 1, 1]], np.int) + 1
result_spaced = np.array([[0, 0, 0, 0, 0],
[1, 1, 1, 1, 1]], np.int)
[1, 1, 1, 1, 1]], np.int) + 1
img += 0.1 * rnd.normal(size=img.shape)
seg_non_spaced = slic(img, n_segments=2, sigma=0, multichannel=False,
compactness=1.0)
@@ -120,11 +120,34 @@ def test_spacing():
def test_invalid_lab_conversion():
img = np.array([[1, 1, 1, 0, 0],
[1, 1, 0, 0, 0]], np.float)
[1, 1, 0, 0, 0]], np.float) + 1
assert_raises(ValueError, slic, img, multichannel=True, convert2lab=True)
def test_enforce_connectivity():
img = np.array([[0, 0, 0, 1, 1, 1],
[1, 0, 0, 1, 1, 0],
[0, 0, 0, 1, 1, 0]], np.float)
segments_connected = slic(img, 2, compactness=0.0001,
enforce_connectivity=True,
convert2lab=False)
segments_disconnected = slic(img, 2, compactness=0.0001,
enforce_connectivity=False,
convert2lab=False)
result_connected = np.array([[1, 1, 1, 2, 2, 2],
[1, 1, 1, 2, 2, 2],
[1, 1, 1, 2, 2, 2]], np.float)
result_disconnected = np.array([[1, 1, 1, 2, 2, 2],
[2, 1, 1, 2, 2, 1],
[1, 1, 1, 2, 2, 1]], np.float)
assert_equal(segments_connected, result_connected)
assert_equal(segments_disconnected, result_disconnected)
if __name__ == '__main__':
from numpy import testing
testing.run_module_suite()