Merge branch 'spath'

Conflicts:
	.gitignore
	scikits/image/opencv/setup.py
This commit is contained in:
Stefan van der Walt
2009-11-03 08:31:51 +02:00
8 changed files with 5461 additions and 59 deletions
+1 -1
View File
@@ -6,10 +6,10 @@
*.bak
*.c
.gitignore
*.new
doc/source/api
doc/build
source/api
scikits/image/opencv/*.new
build
dist
scikits/image/version.py
+68
View File
@@ -0,0 +1,68 @@
import os
import shutil
import hashlib
def cython(pyx_files, working_path=''):
"""Use Cython to convert the given files to C.
Parameters
----------
pyx_files : list of str
The input .pyx files.
"""
try:
import Cython
except ImportError:
# If cython is not found, we do nothing -- the build will make use of
# the distributed .c files
pass
else:
for pyxfile in [os.path.join(working_path, f) for f in pyx_files]:
# make a backup of the good c files
c_file = pyxfile[:-4] + 'c'
c_file_new = c_file + '.new'
# run cython compiler
cmd = 'cython -o %s %s' % (c_file_new, pyxfile)
print cmd
status = os.system(cmd)
# if the resulting file is small, cython compilation failed
size = os.path.getsize(c_file_new)
if status != 0 or (size < 100):
print "Cython compilation of %s failed. Falling back " \
"on pre-generated file." % os.path.basename(pyxfile)
continue
# if the generated .c file differs from the one provided,
# use that one instead
if not same_cython(c_file_new, c_file):
shutil.copy(c_file_new, c_file)
def same_cython(f0, f1):
'''Compare two Cython generated C-files, based on their md5-sum.
Returns True if the files are identical, False if not. The first
lines are skipped, due to the timestamp printed there.
'''
def md5sum(f):
m = hashlib.new('md5')
while True:
d = f.read(8096)
if not d:
break
m.update(d)
return m.hexdigest()
if not (os.path.isfile(f0) and os.path.isfile(f1)):
return False
f0 = file(f0)
f0.readline()
f1 = file(f1)
f1.readline()
return md5sum(f0) == md5sum(f1)
+1
View File
@@ -0,0 +1 @@
from spath import shortest_path
+32
View File
@@ -0,0 +1,32 @@
#!/usr/bin/env python
from scikits.image._build import cython
import os.path
base_path = os.path.abspath(os.path.dirname(__file__))
def configuration(parent_package='', top_path=None):
from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs
config = Configuration('analysis', parent_package, top_path)
config.add_data_dir('tests')
# This function tries to create C files from the given .pyx files. If
# it fails, we build the checked-in .c files.
cython(['spath.pyx'], working_path=base_path)
config.add_extension('spath', sources=['spath.c'],
include_dirs=[get_numpy_include_dirs()])
return config
if __name__ == '__main__':
from numpy.distutils.core import setup
setup(maintainer = 'scikits.image Developers',
maintainer_email = 'scikits-image@googlegroups.com',
description = 'Image Analysis Tools',
url = 'http://stefanv.github.com/scikits.image/',
license = 'Modified BSD',
**(configuration(top_path='').todict())
)
File diff suppressed because it is too large Load Diff
+68
View File
@@ -0,0 +1,68 @@
# -*- python -*-
import numpy as np
cimport numpy as np
cdef extern from "math.h":
double fabs(double f)
cpdef shortest_path(np.ndarray arr):
"""Find the shortest left-to-right path through an array.
Parameters
----------
arr : (M,N) ndarray of float64
"""
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 - 1
r_bracket_max = r + 1
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 + 1, r_bracket_max + 1):
delta0 = fabs(data[rb, c] - data[rb, c - 1])
delta1 = fabs(data[rb, 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
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]
@@ -0,0 +1,17 @@
import numpy as np
from numpy.testing import *
from scikits.image.analysis import shortest_path
class TestShortestPath:
def test_basic(self):
x = np.array([[1, 1, 3],
[0, 2, 0],
[4, 3, 1]])
y = np.empty((3,))
path, cost = shortest_path(x)
assert_array_equal(path, [0, 0, 1])
assert_equal(cost, 1)
if __name__ == "__main__":
run_module_suite()
+7 -58
View File
@@ -1,35 +1,10 @@
#!/usr/bin/env python
import os
import shutil
import hashlib
from scikits.image._build import cython
base_path = os.path.dirname(__file__)
def same_cython(f0, f1):
'''Compare two Cython generated C-files, based on their md5-sum.
Returns True if the files are identical, False if not. The first
lines are skipped, due to the timestamp printed there.
'''
def md5sum(f):
m = hashlib.new('md5')
while True:
d = f.read(8096)
if not d:
break
m.update(d)
return m.hexdigest()
f0 = file(f0)
f0.readline()
f1 = file(f1)
f1.readline()
return md5sum(f0) == md5sum(f1)
import os.path
base_path = os.path.abspath(os.path.dirname(__file__))
def configuration(parent_package='', top_path=None):
from numpy.distutils.misc_util import Configuration, get_numpy_include_dirs
@@ -38,40 +13,14 @@ def configuration(parent_package='', top_path=None):
config.add_data_dir('tests')
# since distutils/cython has problems, we'll check to see if cython is
# installed and use that to rebuild the .c files, if not, we'll just build
# directly from the included .c files
cython_files = ['opencv_backend.pyx', 'opencv_cv.pyx']
try:
import Cython
for pyxfile in [os.path.join(base_path, f) for f in cython_files]:
# make a backup of the good c files
c_file = pyxfile[:-4] + 'c'
c_file_new = c_file + '.new'
# run cython compiler
os.system('cython -o %s %s' % (c_file_new, pyxfile))
# if the resulting file is small, cython compilation failed
size = os.path.getsize(c_file_new)
if size < 100:
print "Cython compilation of %s failed. Using " \
"pre-generated file." % os.path.basename(pyxfile)
continue
# if the generated .c file differs from the one provided,
# use that one instead
if not same_cython(c_file_new, c_file):
shutil.copy(c_file_new, c_file)
except ImportError:
# if cython is not found, we just build from the included .c files
pass
# This function tries to create C files from the given .pyx files. If
# it fails, we build the checked-in .c files.
cython(cython_files, working_path=base_path)
for pyxfile in cython_files:
c_file = pyxfile[:-4] + 'c'
c_file = pyxfile[:-4] + '.c'
config.add_extension(pyxfile[:-4],
sources=[c_file],
include_dirs=[get_numpy_include_dirs()])