scikit-image
96 строк · 4.2 Кб
1cimport numpy as cnp
2cimport cython
3cnp.import_array()
4
5
6ctypedef fused np_ints:
7cnp.int32_t
8cnp.int64_t
9
10ctypedef fused np_uints:
11cnp.uint32_t
12cnp.uint64_t
13
14
15@cython.boundscheck(False)
16@cython.nonecheck(False)
17@cython.wraparound(False)
18def reconstruction_loop(cnp.ndarray[dtype=np_uints, ndim=1,
19negative_indices=False, mode='c'] aranks,
20cnp.ndarray[dtype=np_ints, ndim=1,
21negative_indices=False, mode='c'] aprev,
22cnp.ndarray[dtype=np_ints, ndim=1,
23negative_indices=False, mode='c'] anext,
24cnp.ndarray[dtype=np_ints, ndim=1,
25negative_indices=False, mode='c'] astrides,
26Py_ssize_t current_idx,
27Py_ssize_t image_stride):
28"""The inner loop for reconstruction.
29
30This algorithm uses the rank-order of pixels. If low intensity pixels have
31a low rank and high intensity pixels have a high rank, then this loop
32performs reconstruction by dilation. If this ranking is reversed, the
33result is reconstruction by erosion.
34
35For each pixel in the seed image, check its neighbors. If its neighbor's
36rank is below that of the current pixel, replace the neighbor's rank with
37the rank of the current pixel. This dilation is limited by the mask, i.e.
38the rank at each pixel cannot exceed the mask as that pixel.
39
40Parameters
41----------
42aranks : array
43The rank order of the flattened seed and mask images.
44aprev, anext: arrays
45Indices of previous and next pixels in rank sorted order.
46astrides : array
47Strides to neighbors of the current pixel.
48current_idx : int
49Index of highest-ranked pixel used as starting point in loop.
50image_stride : int
51Stride between seed image and mask image in `aranks`.
52"""
53cdef unsigned int neighbor_rank, current_rank, mask_rank
54cdef int i, neighbor_idx, current_link, nprev, nnext
55cdef int nstrides = astrides.shape[0]
56cdef np_uints *ranks = <np_uints *>(aranks.data)
57cdef np_ints *prev = <np_ints *>(aprev.data)
58cdef np_ints *next = <np_ints *>(anext.data)
59cdef np_ints *strides = <np_ints *>(astrides.data)
60
61with nogil:
62while current_idx != -1:
63if current_idx < image_stride:
64current_rank = ranks[current_idx]
65if current_rank == 0:
66break
67for i in range(nstrides):
68neighbor_idx = current_idx + strides[i]
69neighbor_rank = ranks[neighbor_idx]
70# Only propagate neighbors ranked below the current rank
71if neighbor_rank < current_rank:
72mask_rank = ranks[neighbor_idx + image_stride]
73# Only propagate neighbors ranked below the mask rank
74if neighbor_rank < mask_rank:
75# Raise the neighbor to the mask rank if
76# the mask ranked below the current rank
77if mask_rank < current_rank:
78current_link = neighbor_idx + image_stride
79ranks[neighbor_idx] = mask_rank
80else:
81current_link = current_idx
82ranks[neighbor_idx] = current_rank
83# unlink the neighbor
84nprev = prev[neighbor_idx]
85nnext = next[neighbor_idx]
86next[nprev] = nnext
87if nnext != -1:
88prev[nnext] = nprev
89# link to the neighbor after the current link
90nnext = next[current_link]
91next[neighbor_idx] = nnext
92prev[neighbor_idx] = current_link
93if nnext >= 0:
94prev[nnext] = neighbor_idx
95next[current_link] = neighbor_idx
96current_idx = next[current_idx]
97