From cdf7ad12bcd196ccadfb75836e4be009bfe1752d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Fri, 8 Aug 2014 20:08:06 -0400 Subject: [PATCH 1/4] Speedup moments_central function --- skimage/measure/_moments.pyx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/skimage/measure/_moments.pyx b/skimage/measure/_moments.pyx index e6ccdb75..8cb5ae47 100644 --- a/skimage/measure/_moments.pyx +++ b/skimage/measure/_moments.pyx @@ -79,11 +79,15 @@ def moments_central(double[:, :] image, double cr, double cc, """ cdef Py_ssize_t p, q, r, c cdef double[:, ::1] mu = np.zeros((order + 1, order + 1), dtype=np.double) - for p in range(order + 1): - for q in range(order + 1): - for r in range(image.shape[0]): - for c in range(image.shape[1]): - mu[p, q] += image[r, c] * (r - cr) ** q * (c - cc) ** p + cdef double val, dr, dc + for r in range(image.shape[0]): + dr = r - cr + for c in range(image.shape[1]): + dc = c - cc + val = image[r, c] + for p in range(order + 1): + for q in range(order + 1): + mu[p, q] += val * dr ** q * dc ** p return np.asarray(mu) From 8d2fdaa8f56440d095824fa3f9dc43305bbcca14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Fri, 8 Aug 2014 20:11:04 -0400 Subject: [PATCH 2/4] Speedup moments function --- skimage/measure/_moments.pyx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/skimage/measure/_moments.pyx b/skimage/measure/_moments.pyx index 8cb5ae47..f5bb63af 100644 --- a/skimage/measure/_moments.pyx +++ b/skimage/measure/_moments.pyx @@ -39,7 +39,16 @@ def moments(double[:, :] image, Py_ssize_t order=3): .. [4] http://en.wikipedia.org/wiki/Image_moment """ - return moments_central(image, 0, 0, order) + cdef Py_ssize_t p, q, r, c + cdef double[:, ::1] mu = np.zeros((order + 1, order + 1), dtype=np.double) + cdef double val + for r in range(image.shape[0]): + for c in range(image.shape[1]): + val = image[r, c] + for p in range(order + 1): + for q in range(order + 1): + mu[p, q] += val * r ** q * c ** p + return np.asarray(mu) def moments_central(double[:, :] image, double cr, double cc, From 4f1adee2ecf76a326a8596b3a8e9ea1a3aeace16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Sat, 30 Aug 2014 11:41:32 -0400 Subject: [PATCH 3/4] Make moments functions C functions and reuse centralized moments --- skimage/measure/_moments.pyx | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/skimage/measure/_moments.pyx b/skimage/measure/_moments.pyx index f5bb63af..8fdb30c9 100644 --- a/skimage/measure/_moments.pyx +++ b/skimage/measure/_moments.pyx @@ -5,7 +5,7 @@ import numpy as np -def moments(double[:, :] image, Py_ssize_t order=3): +cpdef moments(double[:, :] image, Py_ssize_t order=3): """Calculate all raw image moments up to a certain order. The following properties can be calculated from raw image moments: @@ -39,20 +39,11 @@ def moments(double[:, :] image, Py_ssize_t order=3): .. [4] http://en.wikipedia.org/wiki/Image_moment """ - cdef Py_ssize_t p, q, r, c - cdef double[:, ::1] mu = np.zeros((order + 1, order + 1), dtype=np.double) - cdef double val - for r in range(image.shape[0]): - for c in range(image.shape[1]): - val = image[r, c] - for p in range(order + 1): - for q in range(order + 1): - mu[p, q] += val * r ** q * c ** p - return np.asarray(mu) + return moments_central(image, 0, 0, order) -def moments_central(double[:, :] image, double cr, double cc, - Py_ssize_t order=3): +cpdef moments_central(double[:, :] image, double cr, double cc, + Py_ssize_t order=3): """Calculate all central image moments up to a certain order. Note that central moments are translation invariant but not scale and @@ -88,15 +79,16 @@ def moments_central(double[:, :] image, double cr, double cc, """ cdef Py_ssize_t p, q, r, c cdef double[:, ::1] mu = np.zeros((order + 1, order + 1), dtype=np.double) - cdef double val, dr, dc + cdef double val, dr, dc, dcp for r in range(image.shape[0]): dr = r - cr for c in range(image.shape[1]): dc = c - cc val = image[r, c] for p in range(order + 1): + dcp = dc ** p for q in range(order + 1): - mu[p, q] += val * dr ** q * dc ** p + mu[p, q] += val * dr ** q * dcp return np.asarray(mu) From 23083636fe44b28bf1cb00350800e3ec86ad3a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Sat, 30 Aug 2014 11:46:22 -0400 Subject: [PATCH 4/4] Replace pow() with iterative multiplication --- skimage/measure/_moments.pyx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/skimage/measure/_moments.pyx b/skimage/measure/_moments.pyx index 8fdb30c9..5a9bc11a 100644 --- a/skimage/measure/_moments.pyx +++ b/skimage/measure/_moments.pyx @@ -79,16 +79,19 @@ cpdef moments_central(double[:, :] image, double cr, double cc, """ cdef Py_ssize_t p, q, r, c cdef double[:, ::1] mu = np.zeros((order + 1, order + 1), dtype=np.double) - cdef double val, dr, dc, dcp + cdef double val, dr, dc, dcp, drq for r in range(image.shape[0]): dr = r - cr for c in range(image.shape[1]): dc = c - cc val = image[r, c] + dcp = 1 for p in range(order + 1): - dcp = dc ** p + drq = 1 for q in range(order + 1): - mu[p, q] += val * dr ** q * dcp + mu[p, q] += val * drq * dcp + drq *= dr + dcp *= dc return np.asarray(mu)