mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-01 13:45:49 +08:00
Changed coding style to be compliant with PEP8
This commit is contained in:
+99
-102
@@ -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
|
||||
-------
|
||||
@@ -214,7 +115,8 @@ def _slic_cython(double[:, :, :, ::1] image_zyx,
|
||||
dist_center += (image_zyx[z, y, x, c - 3]
|
||||
- segments[k, c]) ** 2
|
||||
if distance[z, y, x] > dist_center:
|
||||
nearest_segments[z, y, x] = k
|
||||
# segments start at 1
|
||||
nearest_segments[z, y, x] = k+1
|
||||
distance[z, y, x] = dist_center
|
||||
change = 1
|
||||
|
||||
@@ -230,7 +132,8 @@ def _slic_cython(double[:, :, :, ::1] image_zyx,
|
||||
for z in range(depth):
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
k = nearest_segments[z, y, x]
|
||||
#compensate the label offset 1
|
||||
k = nearest_segments[z, y, x] - 1
|
||||
n_segment_elems[k] += 1
|
||||
segments[k, 0] += z
|
||||
segments[k, 1] += y
|
||||
@@ -244,3 +147,97 @@ 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[:] 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] connected_segments = np.zeros_like(segments)
|
||||
|
||||
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_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
|
||||
|
||||
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 (segments[zz,yy,xx] == label and connected_segments[zz,yy,xx] == 0):
|
||||
connected_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_segments[zz,yy,xx] > 0 and connected_segments[zz,yy,xx] != current_new_label):
|
||||
adjacent = connected_segments[zz,yy,xx]
|
||||
p = p + 1
|
||||
|
||||
|
||||
#change to an adjacent one, like in the original paper
|
||||
if (count < min_size):
|
||||
connected_segments[*coords.T] = adjacent
|
||||
#for i in range(count):
|
||||
# connected_segments[coord_list[i,0],coord_list[i,1],coord_list[i,2]] = adjacent
|
||||
|
||||
return np.asarray(connected_segments)
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user