Commit 31abc3e9 authored by Richard Torenvliet's avatar Richard Torenvliet

Further improve the speed of cython code

parent c2204dea
...@@ -12,7 +12,6 @@ import pca ...@@ -12,7 +12,6 @@ import pca
import aam import aam
import imm_points as imm import imm_points as imm
import halide
from reconstruction import reconstruction from reconstruction import reconstruction
logging.basicConfig(level=logging.INFO, logging.basicConfig(level=logging.INFO,
......
...@@ -84,17 +84,7 @@ cdef inline cartesian2barycentric( ...@@ -84,17 +84,7 @@ cdef inline cartesian2barycentric(
lambdas[1] = ((y_3 - y_1) * (x - x_3) + (x_1 - x_3) * (y - y_3)) / \ lambdas[1] = ((y_3 - y_1) * (x - x_3) + (x_1 - x_3) * (y - y_3)) / \
((y_2 - y_3) * (x_1 - x_3) + (x_3 - x_2) * (y_1 - y_3)) ((y_2 - y_3) * (x_1 - x_3) + (x_3 - x_2) * (y_1 - y_3))
#cdef float lambda_3 = 1 - lambda_1 - lambda_2 lambdas[2] = 1 - lambdas[0] - lambdas[1]
#a = np.array([
# [r1_x, r2_x, r3_x],
# [r1_y, r2_y, r3_y],
# [1, 1, 1]
#])
#b = np.array([r_x, r_y, 1])
#return np.linalg.solve(a, b)
cdef inline np.ndarray[double, ndim=1] cartesian2barycentric_slow( cdef inline np.ndarray[double, ndim=1] cartesian2barycentric_slow(
...@@ -119,19 +109,28 @@ cdef inline np.ndarray[double, ndim=1] cartesian2barycentric_slow( ...@@ -119,19 +109,28 @@ cdef inline np.ndarray[double, ndim=1] cartesian2barycentric_slow(
return np.linalg.solve(a, b) return np.linalg.solve(a, b)
#cdef inline np.ndarray[double, ndim=2] barycentric2cartesian(
# int x1, int x2, int x3, int y1, int y2, int y3,
# np.ndarray[long, ndim=2] matrix,
# np.ndarray[float, ndim=2] Lambdas):
# matrix[0][0] = x1
# matrix[0][1] = x2
# matrix[0][2] = x3
#
# matrix[1][0] = y1
# matrix[1][1] = y2
# matrix[1][2] = y3
#
# return np.dot(matrix, Lambdas)
cdef inline np.ndarray[double, ndim=2] barycentric2cartesian( cdef inline np.ndarray[double, ndim=2] barycentric2cartesian(
int x1, int x2, int x3, int y1, int y2, int y3, int x1, int x2, int x3, int y1, int y2, int y3,
np.ndarray[long, ndim=2] matrix, float[:] lambdas, float[:] output):
np.ndarray[float, ndim=2] Lambdas): # cartesian x
matrix[0][0] = x1 output[0] = x1 * lambdas[0] + x2 * lambdas[1] + x3 * lambdas[2]
matrix[0][1] = x2
matrix[0][2] = x3
matrix[1][0] = y1
matrix[1][1] = y2
matrix[1][2] = y3
return np.dot(matrix, Lambdas) # cartesian y
output[1] = y1 * lambdas[0] + y2 * lambdas[1] + y3 * lambdas[2]
@cython.boundscheck(False) @cython.boundscheck(False)
...@@ -150,16 +149,11 @@ def fill_triangle(np.ndarray[unsigned char, ndim=3] src, ...@@ -150,16 +149,11 @@ def fill_triangle(np.ndarray[unsigned char, ndim=3] src,
cdef int y_min = min(y1, min(y2, y3)) cdef int y_min = min(y1, min(y2, y3))
cdef int y_max = max(y1, max(y2, y3)) cdef int y_max = max(y1, max(y2, y3))
cdef np.ndarray L = np.zeros([3, 1], dtype=DTYPE_float32)
cdef np.ndarray matrix = np.full([3, 3], fill_value=1, dtype=DTYPE_int)
cdef np.ndarray src_loc = np.zeros([3, 1], dtype=DTYPE_float64)
cdef int w = x_max - x_min cdef int w = x_max - x_min
cdef int h = y_max - y_min cdef int h = y_max - y_min
cdef int new_offset cdef int new_offset
cdef c_array.array dst_loc = c_array.array('f', [0., 0.]) cdef c_array.array dst_loc = c_array.array('f', [0., 0., 0.])
for j, y in enumerate(xrange(y_min, y_max)): for j, y in enumerate(xrange(y_min, y_max)):
for i, x in enumerate(xrange(x_min, x_max)): for i, x in enumerate(xrange(x_min, x_max)):
...@@ -170,60 +164,11 @@ def fill_triangle(np.ndarray[unsigned char, ndim=3] src, ...@@ -170,60 +164,11 @@ def fill_triangle(np.ndarray[unsigned char, ndim=3] src,
s = dst_loc[0] s = dst_loc[0]
t = dst_loc[1] t = dst_loc[1]
# notice we have a soft margin of -0.00001, which makes sure there are no # In or out the triangle (with a soft margin)
# gaps due to rounding issues if s >= -0.01 and t >= -0.01 and s + t <= 1.001:
if s >= -0.01 and t >= -0.01 and s + t <= 1.0:
dst[y, x, :] = src[y, x, :] dst[y, x, :] = src[y, x, :]
#@cython.boundscheck(False)
#@cython.wraparound(False)
#def fill_triangle_src_dst(np.ndarray[unsigned char, ndim=3] src,
# np.ndarray[unsigned char, ndim=3] dst,
# int src_x1, int src_y1, int src_x2, int src_y2,
# int src_x3, int src_y3,
# int dst_x1, int dst_y1, int dst_x2, int dst_y2,
# int dst_x3, int dst_y3,
# int offset_x, int offset_y):
#
# cdef np.ndarray triangle_x = np.array([dst_x1, dst_x2, dst_x3])
# cdef np.ndarray triangle_y = np.array([dst_y1, dst_y2, dst_y3])
#
# cdef int x_min = np.argmin(triangle_x)
# cdef int x_max = np.argmax(triangle_x)
# cdef int y_min = np.argmin(triangle_y)
# cdef int y_max = np.argmax(triangle_y)
#
# cdef np.ndarray L = np.zeros([3, 1], dtype=DTYPE_float32)
# cdef np.ndarray matrix = np.full([3, 3], fill_value=1, dtype=DTYPE_int)
#
# cdef np.ndarray src_loc = np.zeros([3, 1], dtype=DTYPE_float64)
# cdef c_array.array dst_loc = c_array.array('f', [0., 0.])
#
# for j, y in enumerate(xrange(triangle_y[y_min], triangle_y[y_max])):
# for i, x in enumerate(xrange(triangle_x[x_min], triangle_x[x_max])):
# cartesian2barycentric(
# dst_x1, dst_y1, dst_x2, dst_y2, dst_x3, dst_y3, x, y, dst_loc
# )
#
# s = dst_loc[0]
# t = dst_loc[1]
#
# if s >= -0.001 and t >= -0.001 and s + t <= 1.001:
# L[0] = s
# L[1] = t
# L[2] = 1 - s - t
#
# src_loc = barycentric2cartesian(
# src_x1, src_x2, src_x3,
# src_y1, src_y2, src_y3,
# matrix,
# L
# )
#
# dst[y, x, :] = src[src_loc[1][0], src_loc[0][0], :]
#
@cython.boundscheck(False) @cython.boundscheck(False)
@cython.wraparound(False) @cython.wraparound(False)
def fill_triangle_src_dst(np.ndarray[unsigned char, ndim=3] src, def fill_triangle_src_dst(np.ndarray[unsigned char, ndim=3] src,
...@@ -236,6 +181,11 @@ def fill_triangle_src_dst(np.ndarray[unsigned char, ndim=3] src, ...@@ -236,6 +181,11 @@ def fill_triangle_src_dst(np.ndarray[unsigned char, ndim=3] src,
Fill a triangle by applying the Barycentric Algorithm for deciding if a Fill a triangle by applying the Barycentric Algorithm for deciding if a
point lies inside or outside a triangle. point lies inside or outside a triangle.
""" """
cdef c_array.array dst_loc = c_array.array('f', [0., 0., 0.])
cdef c_array.array src_loc = c_array.array('f', [0., 0., 0.])
# get bounding box of the triangle
cdef np.ndarray triangle_x = np.array([dst_x1, dst_x2, dst_x3]) cdef np.ndarray triangle_x = np.array([dst_x1, dst_x2, dst_x3])
cdef np.ndarray triangle_y = np.array([dst_y1, dst_y2, dst_y3]) cdef np.ndarray triangle_y = np.array([dst_y1, dst_y2, dst_y3])
...@@ -243,15 +193,12 @@ def fill_triangle_src_dst(np.ndarray[unsigned char, ndim=3] src, ...@@ -243,15 +193,12 @@ def fill_triangle_src_dst(np.ndarray[unsigned char, ndim=3] src,
cdef int x_max = np.argmax(triangle_x) cdef int x_max = np.argmax(triangle_x)
cdef int y_min = np.argmin(triangle_y) cdef int y_min = np.argmin(triangle_y)
cdef int y_max = np.argmax(triangle_y) cdef int y_max = np.argmax(triangle_y)
###
cdef np.ndarray L = np.zeros([3, 1], dtype=DTYPE_float32) # walk over x and y values of this bounding box see if the
cdef np.ndarray matrix = np.full([3, 3], fill_value=1, dtype=DTYPE_int) # pixel is in or out the boudning box
for y in xrange(triangle_y[y_min], triangle_y[y_max]):
cdef np.ndarray src_loc = np.zeros([3, 1], dtype=DTYPE_float64) for x in xrange(triangle_x[x_min], triangle_x[x_max]):
cdef c_array.array dst_loc = c_array.array('f', [0., 0.])
for j, y in enumerate(xrange(triangle_y[y_min], triangle_y[y_max])):
for i, x in enumerate(xrange(triangle_x[x_min], triangle_x[x_max])):
cartesian2barycentric( cartesian2barycentric(
triangle_x[0], triangle_y[0], triangle_x[0], triangle_y[0],
triangle_x[1], triangle_y[1], triangle_x[1], triangle_y[1],
...@@ -262,16 +209,12 @@ def fill_triangle_src_dst(np.ndarray[unsigned char, ndim=3] src, ...@@ -262,16 +209,12 @@ def fill_triangle_src_dst(np.ndarray[unsigned char, ndim=3] src,
s = dst_loc[0] s = dst_loc[0]
t = dst_loc[1] t = dst_loc[1]
# In or out the triangle (with a soft margin)
if s >= -0.01 and t >= -0.01 and s + t <= 1.001: if s >= -0.01 and t >= -0.01 and s + t <= 1.001:
L[0] = s barycentric2cartesian(
L[1] = t
L[2] = 1 - s - t
src_loc = barycentric2cartesian(
src_x1, src_x2, src_x3, src_x1, src_x2, src_x3,
src_y1, src_y2, src_y3, src_y1, src_y2, src_y3,
matrix, dst_loc, src_loc
L
) )
dst[y, x, :] = src[src_loc[1][0], src_loc[0][0], :] dst[y, x, :] = src[src_loc[1], src_loc[0], :]
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment