mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-08 05:38:46 +08:00
86 lines
2.5 KiB
Cython
86 lines
2.5 KiB
Cython
# -*- python -*-
|
|
|
|
import numpy as np
|
|
cimport numpy as np
|
|
|
|
cdef extern from "math.h":
|
|
double fabs(double f)
|
|
|
|
cpdef shortest_path(np.ndarray arr, int reach=1):
|
|
"""Find the shortest left-to-right path through an array.
|
|
|
|
Parameters
|
|
----------
|
|
arr : (M, N) ndarray of float64
|
|
reach : int, optional
|
|
By default (``reach = 1``), the shortest path can only move
|
|
one row up or down for every column it moves forward (i.e.,
|
|
the path gradient is limited to 1). `reach` defines the
|
|
number of rows that can be skipped at each step.
|
|
|
|
Returns
|
|
-------
|
|
p : ndarray of int
|
|
For each column, give the row-coordinate of the
|
|
shortest path.
|
|
cost : float
|
|
Cost of path. This is the absolute sum of all the
|
|
differences along the path.
|
|
|
|
"""
|
|
if arr.ndim != 2:
|
|
raise ValueError("Expected 2-D array as input")
|
|
|
|
cdef np.ndarray[np.double_t, ndim=2] data = \
|
|
np.ascontiguousarray(arr, dtype=np.double)
|
|
|
|
cdef int M = arr.shape[0]
|
|
cdef int N = arr.shape[1]
|
|
|
|
cdef np.ndarray[np.int_t, ndim=2] node = \
|
|
np.empty((M, N), dtype=int)
|
|
|
|
cdef np.ndarray[np.double_t, ndim=2] cost = \
|
|
np.empty((M, N), dtype=np.double)
|
|
|
|
cdef np.ndarray[np.int_t] out = np.empty((N,), dtype=int)
|
|
|
|
cdef int c, r, rb, r_min_node
|
|
cdef int r_bracket_min = 0, r_bracket_max = 0
|
|
cdef double delta0 = 0, delta1 = 0
|
|
|
|
cost[:, 0] = 0
|
|
|
|
for c in range(1, N):
|
|
for r in range(M):
|
|
r_bracket_min = r - reach
|
|
r_bracket_max = r + reach
|
|
|
|
if r_bracket_min < 0:
|
|
r_bracket_min = 0
|
|
if r_bracket_max > M - 1:
|
|
r_bracket_max = M - 1
|
|
|
|
node[r, c] = r_bracket_min
|
|
for rb in range(r_bracket_min, r_bracket_max + 1):
|
|
delta0 = fabs(data[r, c] - data[rb, c - 1])
|
|
delta1 = fabs(data[r, c] - data[node[r, c], c - 1])
|
|
if delta0 < delta1:
|
|
node[r, c] = rb
|
|
|
|
cost[r, c] = cost[node[r, c], c - 1] + \
|
|
fabs(data[r, c] - data[node[r, c], c - 1])
|
|
|
|
# Find minimum cost path
|
|
print arr
|
|
print cost
|
|
print node
|
|
r_min_node = cost[:,-1].argmin()
|
|
|
|
# Backtrack
|
|
out[N - 1] = r_min_node
|
|
for c in range(N - 1, 0, -1):
|
|
out[c - 1] = node[out[c], c]
|
|
|
|
return out, cost[r_min_node, N - 1]
|