Commit 18c2bcddd4fbb36ebbef13006c804f4ce661476a
1 parent
73ddbb08
Exists in
master
Moved all cython codes to invesalius_cy
Showing
20 changed files
with
1731 additions
and
1731 deletions
Show diff stats
invesalius/data/cy_mesh.pyx
... | ... | @@ -1,466 +0,0 @@ |
1 | -# distutils: language = c++ | |
2 | -#cython: boundscheck=False | |
3 | -#cython: wraparound=False | |
4 | -#cython: initializedcheck=False | |
5 | -#cython: cdivision=True | |
6 | -#cython: nonecheck=False | |
7 | - | |
8 | -import sys | |
9 | -import time | |
10 | -cimport numpy as np | |
11 | - | |
12 | -from libc.math cimport sin, cos, acos, exp, sqrt, fabs, M_PI | |
13 | -from libc.stdlib cimport abs as cabs | |
14 | -from cython.operator cimport dereference as deref, preincrement as inc | |
15 | -from libcpp.map cimport map | |
16 | -from libcpp.unordered_map cimport unordered_map | |
17 | -from libcpp.set cimport set | |
18 | -from libcpp.vector cimport vector | |
19 | -from libcpp.pair cimport pair | |
20 | -from libcpp cimport bool | |
21 | -from libcpp.deque cimport deque as cdeque | |
22 | -from cython.parallel import prange | |
23 | - | |
24 | -from cy_my_types cimport vertex_t, normal_t, vertex_id_t | |
25 | - | |
26 | -import numpy as np | |
27 | -import vtk | |
28 | - | |
29 | -from vtk.util import numpy_support | |
30 | - | |
31 | -ctypedef float weight_t | |
32 | - | |
33 | -cdef struct Point: | |
34 | - vertex_t x | |
35 | - vertex_t y | |
36 | - vertex_t z | |
37 | - | |
38 | -ctypedef pair[vertex_id_t, vertex_id_t] key | |
39 | - | |
40 | - | |
41 | -cdef class Mesh: | |
42 | - cdef vertex_t[:, :] vertices | |
43 | - cdef vertex_id_t[:, :] faces | |
44 | - cdef normal_t[:, :] normals | |
45 | - | |
46 | - cdef unordered_map[int, vector[vertex_id_t]] map_vface | |
47 | - cdef unordered_map[vertex_id_t, int] border_vertices | |
48 | - | |
49 | - cdef bool _initialized | |
50 | - | |
51 | - def __cinit__(self, pd=None, other=None): | |
52 | - cdef int i | |
53 | - cdef map[key, int] edge_nfaces | |
54 | - cdef map[key, int].iterator it | |
55 | - if pd: | |
56 | - self._initialized = True | |
57 | - _vertices = numpy_support.vtk_to_numpy(pd.GetPoints().GetData()) | |
58 | - _vertices.shape = -1, 3 | |
59 | - | |
60 | - _faces = numpy_support.vtk_to_numpy(pd.GetPolys().GetData()) | |
61 | - _faces.shape = -1, 4 | |
62 | - | |
63 | - _normals = numpy_support.vtk_to_numpy(pd.GetCellData().GetArray("Normals")) | |
64 | - _normals.shape = -1, 3 | |
65 | - | |
66 | - self.vertices = _vertices | |
67 | - self.faces = _faces | |
68 | - self.normals = _normals | |
69 | - | |
70 | - for i in xrange(_faces.shape[0]): | |
71 | - self.map_vface[self.faces[i, 1]].push_back(i) | |
72 | - self.map_vface[self.faces[i, 2]].push_back(i) | |
73 | - self.map_vface[self.faces[i, 3]].push_back(i) | |
74 | - | |
75 | - edge_nfaces[key(min(self.faces[i, 1], self.faces[i, 2]), max(self.faces[i, 1], self.faces[i, 2]))] += 1 | |
76 | - edge_nfaces[key(min(self.faces[i, 2], self.faces[i, 3]), max(self.faces[i, 2], self.faces[i, 3]))] += 1 | |
77 | - edge_nfaces[key(min(self.faces[i, 1], self.faces[i, 3]), max(self.faces[i, 1], self.faces[i, 3]))] += 1 | |
78 | - | |
79 | - it = edge_nfaces.begin() | |
80 | - | |
81 | - while it != edge_nfaces.end(): | |
82 | - if deref(it).second == 1: | |
83 | - self.border_vertices[deref(it).first.first] = 1 | |
84 | - self.border_vertices[deref(it).first.second] = 1 | |
85 | - | |
86 | - inc(it) | |
87 | - | |
88 | - elif other: | |
89 | - _other = <Mesh>other | |
90 | - self._initialized = True | |
91 | - self.vertices = _other.vertices.copy() | |
92 | - self.faces = _other.faces.copy() | |
93 | - self.normals = _other.normals.copy() | |
94 | - self.map_vface = unordered_map[int, vector[vertex_id_t]](_other.map_vface) | |
95 | - self.border_vertices = unordered_map[vertex_id_t, int](_other.border_vertices) | |
96 | - else: | |
97 | - self._initialized = False | |
98 | - | |
99 | - cdef void copy_to(self, Mesh other): | |
100 | - """ | |
101 | - Copies self content to other. | |
102 | - """ | |
103 | - if self._initialized: | |
104 | - other.vertices[:] = self.vertices | |
105 | - other.faces[:] = self.faces | |
106 | - other.normals[:] = self.normals | |
107 | - other.map_vface = unordered_map[int, vector[vertex_id_t]](self.map_vface) | |
108 | - other.border_vertices = unordered_map[vertex_id_t, int](self.border_vertices) | |
109 | - else: | |
110 | - other.vertices = self.vertices.copy() | |
111 | - other.faces = self.faces.copy() | |
112 | - other.normals = self.normals.copy() | |
113 | - | |
114 | - other.map_vface = self.map_vface | |
115 | - other.border_vertices = self.border_vertices | |
116 | - | |
117 | - def to_vtk(self): | |
118 | - """ | |
119 | - Converts Mesh to vtkPolyData. | |
120 | - """ | |
121 | - vertices = np.asarray(self.vertices) | |
122 | - faces = np.asarray(self.faces) | |
123 | - normals = np.asarray(self.normals) | |
124 | - | |
125 | - points = vtk.vtkPoints() | |
126 | - points.SetData(numpy_support.numpy_to_vtk(vertices)) | |
127 | - | |
128 | - id_triangles = numpy_support.numpy_to_vtkIdTypeArray(faces) | |
129 | - triangles = vtk.vtkCellArray() | |
130 | - triangles.SetCells(faces.shape[0], id_triangles) | |
131 | - | |
132 | - pd = vtk.vtkPolyData() | |
133 | - pd.SetPoints(points) | |
134 | - pd.SetPolys(triangles) | |
135 | - | |
136 | - return pd | |
137 | - | |
138 | - cdef vector[vertex_id_t]* get_faces_by_vertex(self, int v_id) nogil: | |
139 | - """ | |
140 | - Returns the faces whose vertex `v_id' is part. | |
141 | - """ | |
142 | - return &self.map_vface[v_id] | |
143 | - | |
144 | - cdef set[vertex_id_t]* get_ring1(self, vertex_id_t v_id) nogil: | |
145 | - """ | |
146 | - Returns the ring1 of vertex `v_id' | |
147 | - """ | |
148 | - cdef vertex_id_t f_id | |
149 | - cdef set[vertex_id_t]* ring1 = new set[vertex_id_t]() | |
150 | - cdef vector[vertex_id_t].iterator it = self.map_vface[v_id].begin() | |
151 | - | |
152 | - while it != self.map_vface[v_id].end(): | |
153 | - f_id = deref(it) | |
154 | - inc(it) | |
155 | - if self.faces[f_id, 1] != v_id: | |
156 | - ring1.insert(self.faces[f_id, 1]) | |
157 | - if self.faces[f_id, 2] != v_id: | |
158 | - ring1.insert(self.faces[f_id, 2]) | |
159 | - if self.faces[f_id, 3] != v_id: | |
160 | - ring1.insert(self.faces[f_id, 3]) | |
161 | - | |
162 | - return ring1 | |
163 | - | |
164 | - cdef bool is_border(self, vertex_id_t v_id) nogil: | |
165 | - """ | |
166 | - Check if vertex `v_id' is a vertex border. | |
167 | - """ | |
168 | - return self.border_vertices.find(v_id) != self.border_vertices.end() | |
169 | - | |
170 | - cdef vector[vertex_id_t]* get_near_vertices_to_v(self, vertex_id_t v_id, float dmax) nogil: | |
171 | - """ | |
172 | - Returns all vertices with distance at most `d' to the vertex `v_id' | |
173 | - | |
174 | - Params: | |
175 | - v_id: id of the vertex | |
176 | - dmax: the maximum distance. | |
177 | - """ | |
178 | - cdef vector[vertex_id_t]* idfaces | |
179 | - cdef vector[vertex_id_t]* near_vertices = new vector[vertex_id_t]() | |
180 | - | |
181 | - cdef cdeque[vertex_id_t] to_visit | |
182 | - cdef unordered_map[vertex_id_t, bool] status_v | |
183 | - cdef unordered_map[vertex_id_t, bool] status_f | |
184 | - | |
185 | - cdef vertex_t *vip | |
186 | - cdef vertex_t *vjp | |
187 | - | |
188 | - cdef float distance | |
189 | - cdef int nf, nid, j | |
190 | - cdef vertex_id_t f_id, vj | |
191 | - | |
192 | - vip = &self.vertices[v_id, 0] | |
193 | - to_visit.push_back(v_id) | |
194 | - while(not to_visit.empty()): | |
195 | - v_id = to_visit.front() | |
196 | - to_visit.pop_front() | |
197 | - | |
198 | - status_v[v_id] = True | |
199 | - | |
200 | - idfaces = self.get_faces_by_vertex(v_id) | |
201 | - nf = idfaces.size() | |
202 | - | |
203 | - for nid in xrange(nf): | |
204 | - f_id = deref(idfaces)[nid] | |
205 | - if status_f.find(f_id) == status_f.end(): | |
206 | - status_f[f_id] = True | |
207 | - | |
208 | - for j in xrange(3): | |
209 | - vj = self.faces[f_id, j+1] | |
210 | - if status_v.find(vj) == status_v.end(): | |
211 | - status_v[vj] = True | |
212 | - vjp = &self.vertices[vj, 0] | |
213 | - distance = sqrt((vip[0] - vjp[0]) * (vip[0] - vjp[0]) \ | |
214 | - + (vip[1] - vjp[1]) * (vip[1] - vjp[1]) \ | |
215 | - + (vip[2] - vjp[2]) * (vip[2] - vjp[2])) | |
216 | - if distance <= dmax: | |
217 | - near_vertices.push_back(vj) | |
218 | - to_visit.push_back(vj) | |
219 | - | |
220 | - return near_vertices | |
221 | - | |
222 | - | |
223 | -cdef vector[weight_t]* calc_artifacts_weight(Mesh mesh, vector[vertex_id_t]& vertices_staircase, float tmax, float bmin) nogil: | |
224 | - """ | |
225 | - Calculate the artifact weight based on distance of each vertex to its | |
226 | - nearest staircase artifact vertex. | |
227 | - | |
228 | - Params: | |
229 | - mesh: Mesh | |
230 | - vertices_staircase: the identified staircase artifact vertices | |
231 | - tmax: max distance the vertex must be to its nearest artifact vertex | |
232 | - to considered to calculate the weight | |
233 | - bmin: The minimum weight. | |
234 | - """ | |
235 | - cdef int vi_id, vj_id, nnv, n_ids, i, j | |
236 | - cdef vector[vertex_id_t]* near_vertices | |
237 | - cdef weight_t value | |
238 | - cdef float d | |
239 | - n_ids = vertices_staircase.size() | |
240 | - | |
241 | - cdef vertex_t* vi | |
242 | - cdef vertex_t* vj | |
243 | - cdef size_t msize | |
244 | - | |
245 | - msize = mesh.vertices.shape[0] | |
246 | - cdef vector[weight_t]* weights = new vector[weight_t](msize) | |
247 | - weights.assign(msize, bmin) | |
248 | - | |
249 | - for i in prange(n_ids, nogil=True): | |
250 | - vi_id = vertices_staircase[i] | |
251 | - deref(weights)[vi_id] = 1.0 | |
252 | - | |
253 | - vi = &mesh.vertices[vi_id, 0] | |
254 | - near_vertices = mesh.get_near_vertices_to_v(vi_id, tmax) | |
255 | - nnv = near_vertices.size() | |
256 | - | |
257 | - for j in xrange(nnv): | |
258 | - vj_id = deref(near_vertices)[j] | |
259 | - vj = &mesh.vertices[vj_id, 0] | |
260 | - | |
261 | - d = sqrt((vi[0] - vj[0]) * (vi[0] - vj[0])\ | |
262 | - + (vi[1] - vj[1]) * (vi[1] - vj[1])\ | |
263 | - + (vi[2] - vj[2]) * (vi[2] - vj[2])) | |
264 | - value = (1.0 - d/tmax) * (1.0 - bmin) + bmin | |
265 | - | |
266 | - if value > deref(weights)[vj_id]: | |
267 | - deref(weights)[vj_id] = value | |
268 | - | |
269 | - del near_vertices | |
270 | - | |
271 | - # for i in xrange(msize): | |
272 | - # if mesh.is_border(i): | |
273 | - # deref(weights)[i] = 0.0 | |
274 | - | |
275 | - # cdef vertex_id_t v0, v1, v2 | |
276 | - # for i in xrange(mesh.faces.shape[0]): | |
277 | - # for j in xrange(1, 4): | |
278 | - # v0 = mesh.faces[i, j] | |
279 | - # vi = &mesh.vertices[v0, 0] | |
280 | - # if mesh.is_border(v0): | |
281 | - # deref(weights)[v0] = 0.0 | |
282 | - # v1 = mesh.faces[i, (j + 1) % 3 + 1] | |
283 | - # if mesh.is_border(v1): | |
284 | - # vi = &mesh.vertices[v1, 0] | |
285 | - # deref(weights)[v0] = 0.0 | |
286 | - | |
287 | - return weights | |
288 | - | |
289 | - | |
290 | -cdef inline Point calc_d(Mesh mesh, vertex_id_t v_id) nogil: | |
291 | - cdef Point D | |
292 | - cdef int nf, f_id, nid | |
293 | - cdef float n=0 | |
294 | - cdef int i | |
295 | - cdef vertex_t* vi | |
296 | - cdef vertex_t* vj | |
297 | - cdef set[vertex_id_t]* vertices | |
298 | - cdef set[vertex_id_t].iterator it | |
299 | - cdef vertex_id_t vj_id | |
300 | - | |
301 | - D.x = 0.0 | |
302 | - D.y = 0.0 | |
303 | - D.z = 0.0 | |
304 | - | |
305 | - vertices = mesh.get_ring1(v_id) | |
306 | - vi = &mesh.vertices[v_id, 0] | |
307 | - | |
308 | - if mesh.is_border(v_id): | |
309 | - it = vertices.begin() | |
310 | - while it != vertices.end(): | |
311 | - vj_id = deref(it) | |
312 | - if mesh.is_border(vj_id): | |
313 | - vj = &mesh.vertices[vj_id, 0] | |
314 | - | |
315 | - D.x = D.x + (vi[0] - vj[0]) | |
316 | - D.y = D.y + (vi[1] - vj[1]) | |
317 | - D.z = D.z + (vi[2] - vj[2]) | |
318 | - n += 1.0 | |
319 | - | |
320 | - inc(it) | |
321 | - else: | |
322 | - it = vertices.begin() | |
323 | - while it != vertices.end(): | |
324 | - vj_id = deref(it) | |
325 | - vj = &mesh.vertices[vj_id, 0] | |
326 | - | |
327 | - D.x = D.x + (vi[0] - vj[0]) | |
328 | - D.y = D.y + (vi[1] - vj[1]) | |
329 | - D.z = D.z + (vi[2] - vj[2]) | |
330 | - n += 1.0 | |
331 | - | |
332 | - inc(it) | |
333 | - | |
334 | - del vertices | |
335 | - | |
336 | - D.x = D.x / n | |
337 | - D.y = D.y / n | |
338 | - D.z = D.z / n | |
339 | - return D | |
340 | - | |
341 | -cdef vector[vertex_id_t]* find_staircase_artifacts(Mesh mesh, double[3] stack_orientation, double T) nogil: | |
342 | - """ | |
343 | - This function is used to find vertices at staircase artifacts, which are | |
344 | - those vertices whose incident faces' orientation differences are | |
345 | - greater than T. | |
346 | - | |
347 | - Params: | |
348 | - mesh: Mesh | |
349 | - stack_orientation: orientation of slice stacking | |
350 | - T: Min angle (between vertex faces and stack_orientation) to consider a | |
351 | - vertex a staircase artifact. | |
352 | - """ | |
353 | - cdef int nv, nf, f_id, v_id | |
354 | - cdef double of_z, of_y, of_x, min_z, max_z, min_y, max_y, min_x, max_x; | |
355 | - cdef vector[vertex_id_t]* f_ids | |
356 | - cdef normal_t* normal | |
357 | - | |
358 | - cdef vector[vertex_id_t]* output = new vector[vertex_id_t]() | |
359 | - cdef int i | |
360 | - | |
361 | - nv = mesh.vertices.shape[0] | |
362 | - | |
363 | - for v_id in xrange(nv): | |
364 | - max_z = -10000 | |
365 | - min_z = 10000 | |
366 | - max_y = -10000 | |
367 | - min_y = 10000 | |
368 | - max_x = -10000 | |
369 | - min_x = 10000 | |
370 | - | |
371 | - f_ids = mesh.get_faces_by_vertex(v_id) | |
372 | - nf = deref(f_ids).size() | |
373 | - | |
374 | - for i in xrange(nf): | |
375 | - f_id = deref(f_ids)[i] | |
376 | - normal = &mesh.normals[f_id, 0] | |
377 | - | |
378 | - of_z = 1 - fabs(normal[0]*stack_orientation[0] + normal[1]*stack_orientation[1] + normal[2]*stack_orientation[2]); | |
379 | - of_y = 1 - fabs(normal[0]*0 + normal[1]*1 + normal[2]*0); | |
380 | - of_x = 1 - fabs(normal[0]*1 + normal[1]*0 + normal[2]*0); | |
381 | - | |
382 | - if (of_z > max_z): | |
383 | - max_z = of_z | |
384 | - | |
385 | - if (of_z < min_z): | |
386 | - min_z = of_z | |
387 | - | |
388 | - if (of_y > max_y): | |
389 | - max_y = of_y | |
390 | - | |
391 | - if (of_y < min_y): | |
392 | - min_y = of_y | |
393 | - | |
394 | - if (of_x > max_x): | |
395 | - max_x = of_x | |
396 | - | |
397 | - if (of_x < min_x): | |
398 | - min_x = of_x | |
399 | - | |
400 | - | |
401 | - if ((fabs(max_z - min_z) >= T) or (fabs(max_y - min_y) >= T) or (fabs(max_x - min_x) >= T)): | |
402 | - output.push_back(v_id) | |
403 | - break | |
404 | - return output | |
405 | - | |
406 | - | |
407 | -cdef void taubin_smooth(Mesh mesh, vector[weight_t]& weights, float l, float m, int steps): | |
408 | - """ | |
409 | - Implementation of Taubin's smooth algorithm described in the paper "A | |
410 | - Signal Processing Approach To Fair Surface Design". His benefeat is it | |
411 | - avoids surface shrinking. | |
412 | - """ | |
413 | - cdef int s, i, nvertices | |
414 | - nvertices = mesh.vertices.shape[0] | |
415 | - cdef vector[Point] D = vector[Point](nvertices) | |
416 | - cdef vertex_t* vi | |
417 | - for s in xrange(steps): | |
418 | - for i in prange(nvertices, nogil=True): | |
419 | - D[i] = calc_d(mesh, i) | |
420 | - | |
421 | - for i in prange(nvertices, nogil=True): | |
422 | - mesh.vertices[i, 0] += weights[i]*l*D[i].x; | |
423 | - mesh.vertices[i, 1] += weights[i]*l*D[i].y; | |
424 | - mesh.vertices[i, 2] += weights[i]*l*D[i].z; | |
425 | - | |
426 | - for i in prange(nvertices, nogil=True): | |
427 | - D[i] = calc_d(mesh, i) | |
428 | - | |
429 | - for i in prange(nvertices, nogil=True): | |
430 | - mesh.vertices[i, 0] += weights[i]*m*D[i].x; | |
431 | - mesh.vertices[i, 1] += weights[i]*m*D[i].y; | |
432 | - mesh.vertices[i, 2] += weights[i]*m*D[i].z; | |
433 | - | |
434 | - | |
435 | -def ca_smoothing(Mesh mesh, double T, double tmax, double bmin, int n_iters): | |
436 | - """ | |
437 | - This is a implementation of the paper "Context-aware mesh smoothing for | |
438 | - biomedical applications". It can be used to smooth meshes generated by | |
439 | - binary images to remove its staircase artifacts and keep the fine features. | |
440 | - | |
441 | - Params: | |
442 | - mesh: Mesh | |
443 | - T: Min angle (between vertex faces and stack_orientation) to consider a | |
444 | - vertex a staircase artifact | |
445 | - tmax: max distance the vertex must be to its nearest artifact vertex | |
446 | - to considered to calculate the weight | |
447 | - bmin: The minimum weight | |
448 | - n_iters: Number of iterations. | |
449 | - """ | |
450 | - cdef double[3] stack_orientation = [0.0, 0.0, 1.0] | |
451 | - | |
452 | - t0 = time.time() | |
453 | - cdef vector[vertex_id_t]* vertices_staircase = find_staircase_artifacts(mesh, stack_orientation, T) | |
454 | - print "vertices staircase", time.time() - t0 | |
455 | - | |
456 | - t0 = time.time() | |
457 | - cdef vector[weight_t]* weights = calc_artifacts_weight(mesh, deref(vertices_staircase), tmax, bmin) | |
458 | - print "Weights", time.time() - t0 | |
459 | - | |
460 | - del vertices_staircase | |
461 | - | |
462 | - t0 = time.time() | |
463 | - taubin_smooth(mesh, deref(weights), 0.5, -0.53, n_iters) | |
464 | - print "taubin", time.time() - t0 | |
465 | - | |
466 | - del weights |
invesalius/data/cy_my_types.pxd
... | ... | @@ -1,21 +0,0 @@ |
1 | -import numpy as np | |
2 | -cimport numpy as np | |
3 | -cimport cython | |
4 | - | |
5 | -# ctypedef np.uint16_t image_t | |
6 | - | |
7 | -ctypedef fused image_t: | |
8 | - np.float64_t | |
9 | - np.int16_t | |
10 | - np.uint8_t | |
11 | - | |
12 | -ctypedef np.uint8_t mask_t | |
13 | - | |
14 | -ctypedef np.float32_t vertex_t | |
15 | -ctypedef np.float32_t normal_t | |
16 | - | |
17 | -# To compile in windows 64 | |
18 | -IF UNAME_MACHINE == 'AMD64': | |
19 | - ctypedef np.int64_t vertex_id_t | |
20 | -ELSE: | |
21 | - ctypedef np.int_t vertex_id_t |
invesalius/data/floodfill.pyx
... | ... | @@ -1,274 +0,0 @@ |
1 | -import numpy as np | |
2 | -cimport numpy as np | |
3 | -cimport cython | |
4 | - | |
5 | -from collections import deque | |
6 | - | |
7 | -from cython.parallel import prange | |
8 | -from libc.math cimport floor, ceil | |
9 | -from libcpp cimport bool | |
10 | -from libcpp.deque cimport deque as cdeque | |
11 | -from libcpp.vector cimport vector | |
12 | - | |
13 | -from cy_my_types cimport image_t, mask_t | |
14 | - | |
15 | -cdef struct s_coord: | |
16 | - int x | |
17 | - int y | |
18 | - int z | |
19 | - | |
20 | -ctypedef s_coord coord | |
21 | - | |
22 | - | |
23 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
24 | -@cython.wraparound(False) | |
25 | -@cython.nonecheck(False) | |
26 | -@cython.cdivision(True) | |
27 | -cdef inline void append_queue(cdeque[int]& stack, int x, int y, int z, int d, int h, int w) nogil: | |
28 | - stack.push_back(z*h*w + y*w + x) | |
29 | - | |
30 | - | |
31 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
32 | -@cython.wraparound(False) | |
33 | -@cython.nonecheck(False) | |
34 | -@cython.cdivision(True) | |
35 | -cdef inline void pop_queue(cdeque[int]& stack, int* x, int* y, int* z, int d, int h, int w) nogil: | |
36 | - cdef int i = stack.front() | |
37 | - stack.pop_front() | |
38 | - x[0] = i % w | |
39 | - y[0] = (i / w) % h | |
40 | - z[0] = i / (h * w) | |
41 | - | |
42 | - | |
43 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
44 | -def floodfill(np.ndarray[image_t, ndim=3] data, int i, int j, int k, int v, int fill, np.ndarray[mask_t, ndim=3] out): | |
45 | - | |
46 | - cdef int to_return = 0 | |
47 | - if out is None: | |
48 | - out = np.zeros_like(data) | |
49 | - to_return = 1 | |
50 | - | |
51 | - cdef int x, y, z | |
52 | - cdef int w, h, d | |
53 | - | |
54 | - d = data.shape[0] | |
55 | - h = data.shape[1] | |
56 | - w = data.shape[2] | |
57 | - | |
58 | - stack = [(i, j, k), ] | |
59 | - out[k, j, i] = fill | |
60 | - | |
61 | - while stack: | |
62 | - x, y, z = stack.pop() | |
63 | - | |
64 | - if z + 1 < d and data[z + 1, y, x] == v and out[z + 1, y, x] != fill: | |
65 | - out[z + 1, y, x] = fill | |
66 | - stack.append((x, y, z + 1)) | |
67 | - | |
68 | - if z - 1 >= 0 and data[z - 1, y, x] == v and out[z - 1, y, x] != fill: | |
69 | - out[z - 1, y, x] = fill | |
70 | - stack.append((x, y, z - 1)) | |
71 | - | |
72 | - if y + 1 < h and data[z, y + 1, x] == v and out[z, y + 1, x] != fill: | |
73 | - out[z, y + 1, x] = fill | |
74 | - stack.append((x, y + 1, z)) | |
75 | - | |
76 | - if y - 1 >= 0 and data[z, y - 1, x] == v and out[z, y - 1, x] != fill: | |
77 | - out[z, y - 1, x] = fill | |
78 | - stack.append((x, y - 1, z)) | |
79 | - | |
80 | - if x + 1 < w and data[z, y, x + 1] == v and out[z, y, x + 1] != fill: | |
81 | - out[z, y, x + 1] = fill | |
82 | - stack.append((x + 1, y, z)) | |
83 | - | |
84 | - if x - 1 >= 0 and data[z, y, x - 1] == v and out[z, y, x - 1] != fill: | |
85 | - out[z, y, x - 1] = fill | |
86 | - stack.append((x - 1, y, z)) | |
87 | - | |
88 | - if to_return: | |
89 | - return out | |
90 | - | |
91 | - | |
92 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
93 | -@cython.wraparound(False) | |
94 | -@cython.nonecheck(False) | |
95 | -def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, int t1, int fill, np.ndarray[mask_t, ndim=3] strct, np.ndarray[mask_t, ndim=3] out): | |
96 | - | |
97 | - cdef int to_return = 0 | |
98 | - if out is None: | |
99 | - out = np.zeros_like(data) | |
100 | - to_return = 1 | |
101 | - | |
102 | - cdef int x, y, z | |
103 | - cdef int dx, dy, dz | |
104 | - cdef int odx, ody, odz | |
105 | - cdef int xo, yo, zo | |
106 | - cdef int i, j, k | |
107 | - cdef int offset_x, offset_y, offset_z | |
108 | - | |
109 | - dz = data.shape[0] | |
110 | - dy = data.shape[1] | |
111 | - dx = data.shape[2] | |
112 | - | |
113 | - odz = strct.shape[0] | |
114 | - ody = strct.shape[1] | |
115 | - odx = strct.shape[2] | |
116 | - | |
117 | - cdef cdeque[coord] stack | |
118 | - cdef coord c | |
119 | - | |
120 | - offset_z = odz / 2 | |
121 | - offset_y = ody / 2 | |
122 | - offset_x = odx / 2 | |
123 | - | |
124 | - for i, j, k in seeds: | |
125 | - if data[k, j, i] >= t0 and data[k, j, i] <= t1: | |
126 | - c.x = i | |
127 | - c.y = j | |
128 | - c.z = k | |
129 | - stack.push_back(c) | |
130 | - out[k, j, i] = fill | |
131 | - | |
132 | - with nogil: | |
133 | - while stack.size(): | |
134 | - c = stack.back() | |
135 | - stack.pop_back() | |
136 | - | |
137 | - x = c.x | |
138 | - y = c.y | |
139 | - z = c.z | |
140 | - | |
141 | - out[z, y, x] = fill | |
142 | - | |
143 | - for k in xrange(odz): | |
144 | - zo = z + k - offset_z | |
145 | - for j in xrange(ody): | |
146 | - yo = y + j - offset_y | |
147 | - for i in xrange(odx): | |
148 | - if strct[k, j, i]: | |
149 | - xo = x + i - offset_x | |
150 | - if 0 <= xo < dx and 0 <= yo < dy and 0 <= zo < dz and out[zo, yo, xo] != fill and t0 <= data[zo, yo, xo] <= t1: | |
151 | - out[zo, yo, xo] = fill | |
152 | - c.x = xo | |
153 | - c.y = yo | |
154 | - c.z = zo | |
155 | - stack.push_back(c) | |
156 | - | |
157 | - if to_return: | |
158 | - return out | |
159 | - | |
160 | - | |
161 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
162 | -@cython.wraparound(False) | |
163 | -@cython.nonecheck(False) | |
164 | -def floodfill_auto_threshold(np.ndarray[image_t, ndim=3] data, list seeds, float p, int fill, np.ndarray[mask_t, ndim=3] out): | |
165 | - | |
166 | - cdef int to_return = 0 | |
167 | - if out is None: | |
168 | - out = np.zeros_like(data) | |
169 | - to_return = 1 | |
170 | - | |
171 | - cdef cdeque[int] stack | |
172 | - cdef int x, y, z | |
173 | - cdef int w, h, d | |
174 | - cdef int xo, yo, zo | |
175 | - cdef int t0, t1 | |
176 | - | |
177 | - cdef int i, j, k | |
178 | - | |
179 | - d = data.shape[0] | |
180 | - h = data.shape[1] | |
181 | - w = data.shape[2] | |
182 | - | |
183 | - | |
184 | - # stack = deque() | |
185 | - | |
186 | - x = 0 | |
187 | - y = 0 | |
188 | - z = 0 | |
189 | - | |
190 | - | |
191 | - for i, j, k in seeds: | |
192 | - append_queue(stack, i, j, k, d, h, w) | |
193 | - out[k, j, i] = fill | |
194 | - print i, j, k, d, h, w | |
195 | - | |
196 | - with nogil: | |
197 | - while stack.size(): | |
198 | - pop_queue(stack, &x, &y, &z, d, h, w) | |
199 | - | |
200 | - # print x, y, z, d, h, w | |
201 | - | |
202 | - xo = x | |
203 | - yo = y | |
204 | - zo = z | |
205 | - | |
206 | - t0 = <int>ceil(data[z, y, x] * (1 - p)) | |
207 | - t1 = <int>floor(data[z, y, x] * (1 + p)) | |
208 | - | |
209 | - if z + 1 < d and data[z + 1, y, x] >= t0 and data[z + 1, y, x] <= t1 and out[zo + 1, yo, xo] != fill: | |
210 | - out[zo + 1, yo, xo] = fill | |
211 | - append_queue(stack, x, y, z+1, d, h, w) | |
212 | - | |
213 | - if z - 1 >= 0 and data[z - 1, y, x] >= t0 and data[z - 1, y, x] <= t1 and out[zo - 1, yo, xo] != fill: | |
214 | - out[zo - 1, yo, xo] = fill | |
215 | - append_queue(stack, x, y, z-1, d, h, w) | |
216 | - | |
217 | - if y + 1 < h and data[z, y + 1, x] >= t0 and data[z, y + 1, x] <= t1 and out[zo, yo + 1, xo] != fill: | |
218 | - out[zo, yo + 1, xo] = fill | |
219 | - append_queue(stack, x, y+1, z, d, h, w) | |
220 | - | |
221 | - if y - 1 >= 0 and data[z, y - 1, x] >= t0 and data[z, y - 1, x] <= t1 and out[zo, yo - 1, xo] != fill: | |
222 | - out[zo, yo - 1, xo] = fill | |
223 | - append_queue(stack, x, y-1, z, d, h, w) | |
224 | - | |
225 | - if x + 1 < w and data[z, y, x + 1] >= t0 and data[z, y, x + 1] <= t1 and out[zo, yo, xo + 1] != fill: | |
226 | - out[zo, yo, xo + 1] = fill | |
227 | - append_queue(stack, x+1, y, z, d, h, w) | |
228 | - | |
229 | - if x - 1 >= 0 and data[z, y, x - 1] >= t0 and data[z, y, x - 1] <= t1 and out[zo, yo, xo - 1] != fill: | |
230 | - out[zo, yo, xo - 1] = fill | |
231 | - append_queue(stack, x-1, y, z, d, h, w) | |
232 | - | |
233 | - if to_return: | |
234 | - return out | |
235 | - | |
236 | - | |
237 | -@cython.boundscheck(False) | |
238 | -@cython.wraparound(False) | |
239 | -@cython.nonecheck(False) | |
240 | -def fill_holes_automatically(np.ndarray[mask_t, ndim=3] mask, np.ndarray[np.uint16_t, ndim=3] labels, unsigned int nlabels, unsigned int max_size): | |
241 | - """ | |
242 | - Fill mask holes automatically. The hole must <= max_size. Return True if any hole were filled. | |
243 | - """ | |
244 | - cdef np.ndarray[np.uint32_t, ndim=1] sizes = np.zeros(shape=(nlabels + 1), dtype=np.uint32) | |
245 | - cdef int x, y, z | |
246 | - cdef int dx, dy, dz | |
247 | - cdef int i | |
248 | - | |
249 | - cdef bool modified = False | |
250 | - | |
251 | - dz = mask.shape[0] | |
252 | - dy = mask.shape[1] | |
253 | - dx = mask.shape[2] | |
254 | - | |
255 | - for z in xrange(dz): | |
256 | - for y in xrange(dy): | |
257 | - for x in xrange(dx): | |
258 | - sizes[labels[z, y, x]] += 1 | |
259 | - | |
260 | - #Checking if any hole will be filled | |
261 | - for i in xrange(nlabels + 1): | |
262 | - if sizes[i] <= max_size: | |
263 | - modified = True | |
264 | - | |
265 | - if not modified: | |
266 | - return 0 | |
267 | - | |
268 | - for z in prange(dz, nogil=True): | |
269 | - for y in xrange(dy): | |
270 | - for x in xrange(dx): | |
271 | - if sizes[labels[z, y, x]] <= max_size: | |
272 | - mask[z, y, x] = 254 | |
273 | - | |
274 | - return modified |
invesalius/data/interpolation.pxd
... | ... | @@ -1,8 +0,0 @@ |
1 | -from .cy_my_types cimport image_t | |
2 | - | |
3 | -cdef double interpolate(image_t[:, :, :], double, double, double) nogil | |
4 | -cdef double tricub_interpolate(image_t[:, :, :], double, double, double) nogil | |
5 | -cdef double tricubicInterpolate (image_t[:, :, :], double, double, double) nogil | |
6 | -cdef double lanczos3 (image_t[:, :, :], double, double, double) nogil | |
7 | - | |
8 | -cdef double nearest_neighbour_interp(image_t[:, :, :], double, double, double) nogil |
invesalius/data/interpolation.pyx
... | ... | @@ -1,392 +0,0 @@ |
1 | -# from interpolation cimport interpolate | |
2 | - | |
3 | -import numpy as np | |
4 | -cimport numpy as np | |
5 | -cimport cython | |
6 | - | |
7 | -from libc.math cimport floor, ceil, sqrt, fabs, sin, M_PI | |
8 | -from cython.parallel import prange | |
9 | - | |
10 | -DEF LANCZOS_A = 4 | |
11 | -DEF SIZE_LANCZOS_TMP = LANCZOS_A * 2 - 1 | |
12 | - | |
13 | -cdef double[64][64] temp = [ | |
14 | - [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
15 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
16 | - [-3, 3, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
17 | - [ 2, -2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
18 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
19 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
20 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
21 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
22 | - [-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
23 | - [ 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
24 | - [ 9, -9,-9, 9, 0, 0, 0, 0, 6, 3,-6,-3, 0, 0, 0, 0, 6,-6, 3,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
25 | - [-6, 6, 6,-6, 0, 0, 0, 0,-3,-3, 3, 3, 0, 0, 0, 0,-4, 4,-2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-2,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
26 | - [ 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
27 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
28 | - [-6, 6, 6,-6, 0, 0, 0, 0,-4,-2, 4, 2, 0, 0, 0, 0,-3, 3,-3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-1,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
29 | - [ 4, -4,-4, 4, 0, 0, 0, 0, 2, 2,-2,-2, 0, 0, 0, 0, 2,-2, 2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
30 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
31 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
32 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
33 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
34 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
35 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], | |
36 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0], | |
37 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0], | |
38 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
39 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0, 0, 0, 0, 0], | |
40 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,-9,-9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3,-6,-3, 0, 0, 0, 0, 6,-6, 3,-3, 0, 0, 0, 0, 4, 2, 2, 1, 0, 0, 0, 0], | |
41 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3,-3, 3, 3, 0, 0, 0, 0,-4, 4,-2, 2, 0, 0, 0, 0,-2,-2,-1,-1, 0, 0, 0, 0], | |
42 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
43 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0], | |
44 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4,-2, 4, 2, 0, 0, 0, 0,-3, 3,-3, 3, 0, 0, 0, 0,-2,-1,-2,-1, 0, 0, 0, 0], | |
45 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,-4,-4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,-2,-2, 0, 0, 0, 0, 2,-2, 2,-2, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0], | |
46 | - [-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
47 | - [ 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
48 | - [ 9, -9, 0, 0,-9, 9, 0, 0, 6, 3, 0, 0,-6,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,-6, 0, 0, 3,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
49 | - [-6, 6, 0, 0, 6,-6, 0, 0,-3,-3, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4, 4, 0, 0,-2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-2, 0, 0,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
50 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
51 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 0, 0,-1, 0, 0, 0], | |
52 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,-9, 0, 0,-9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0,-6,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,-6, 0, 0, 3,-3, 0, 0, 4, 2, 0, 0, 2, 1, 0, 0], | |
53 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 0, 0, 6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3,-3, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4, 4, 0, 0,-2, 2, 0, 0,-2,-2, 0, 0,-1,-1, 0, 0], | |
54 | - [ 9, 0,-9, 0,-9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 0,-6, 0,-3, 0, 6, 0,-6, 0, 3, 0,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
55 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,-9, 0,-9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 0,-6, 0,-3, 0, 6, 0,-6, 0, 3, 0,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 2, 0, 2, 0, 1, 0], | |
56 | - [-27, 27,27,-27,27,-27,-27,27,-18,-9,18, 9,18, 9,-18,-9,-18,18,-9, 9,18,-18, 9,-9,-18,18,18,-18,-9, 9, 9,-9,-12,-6,-6,-3,12, 6, 6, 3,-12,-6,12, 6,-6,-3, 6, 3,-12,12,-6, 6,-6, 6,-3, 3,-8,-4,-4,-2,-4,-2,-2,-1], | |
57 | - [18, -18,-18,18,-18,18,18,-18, 9, 9,-9,-9,-9,-9, 9, 9,12,-12, 6,-6,-12,12,-6, 6,12,-12,-12,12, 6,-6,-6, 6, 6, 6, 3, 3,-6,-6,-3,-3, 6, 6,-6,-6, 3, 3,-3,-3, 8,-8, 4,-4, 4,-4, 2,-2, 4, 4, 2, 2, 2, 2, 1, 1], | |
58 | - [-6, 0, 6, 0, 6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0,-3, 0, 3, 0, 3, 0,-4, 0, 4, 0,-2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-2, 0,-1, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
59 | - [ 0, 0, 0, 0, 0, 0, 0, 0,-6, 0, 6, 0, 6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0,-3, 0, 3, 0, 3, 0,-4, 0, 4, 0,-2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-2, 0,-1, 0,-1, 0], | |
60 | - [18, -18,-18,18,-18,18,18,-18,12, 6,-12,-6,-12,-6,12, 6, 9,-9, 9,-9,-9, 9,-9, 9,12,-12,-12,12, 6,-6,-6, 6, 6, 3, 6, 3,-6,-3,-6,-3, 8, 4,-8,-4, 4, 2,-4,-2, 6,-6, 6,-6, 3,-3, 3,-3, 4, 2, 4, 2, 2, 1, 2, 1], | |
61 | - [-12, 12,12,-12,12,-12,-12,12,-6,-6, 6, 6, 6, 6,-6,-6,-6, 6,-6, 6, 6,-6, 6,-6,-8, 8, 8,-8,-4, 4, 4,-4,-3,-3,-3,-3, 3, 3, 3, 3,-4,-4, 4, 4,-2,-2, 2, 2,-4, 4,-4, 4,-2, 2,-2, 2,-2,-2,-2,-2,-1,-1,-1,-1], | |
62 | - [ 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
63 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
64 | - [-6, 6, 0, 0, 6,-6, 0, 0,-4,-2, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0,-3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
65 | - [ 4, -4, 0, 0,-4, 4, 0, 0, 2, 2, 0, 0,-2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
66 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
67 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0], | |
68 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 0, 0, 6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4,-2, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0,-3, 3, 0, 0,-2,-1, 0, 0,-2,-1, 0, 0], | |
69 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,-4, 0, 0,-4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0,-2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 2,-2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0], | |
70 | - [-6, 0, 6, 0, 6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4, 0,-2, 0, 4, 0, 2, 0,-3, 0, 3, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
71 | - [ 0, 0, 0, 0, 0, 0, 0, 0,-6, 0, 6, 0, 6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4, 0,-2, 0, 4, 0, 2, 0,-3, 0, 3, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0,-2, 0,-1, 0], | |
72 | - [18, -18,-18,18,-18,18,18,-18,12, 6,-12,-6,-12,-6,12, 6,12,-12, 6,-6,-12,12,-6, 6, 9,-9,-9, 9, 9,-9,-9, 9, 8, 4, 4, 2,-8,-4,-4,-2, 6, 3,-6,-3, 6, 3,-6,-3, 6,-6, 3,-3, 6,-6, 3,-3, 4, 2, 2, 1, 4, 2, 2, 1], | |
73 | - [-12, 12,12,-12,12,-12,-12,12,-6,-6, 6, 6, 6, 6,-6,-6,-8, 8,-4, 4, 8,-8, 4,-4,-6, 6, 6,-6,-6, 6, 6,-6,-4,-4,-2,-2, 4, 4, 2, 2,-3,-3, 3, 3,-3,-3, 3, 3,-4, 4,-2, 2,-4, 4,-2, 2,-2,-2,-1,-1,-2,-2,-1,-1], | |
74 | - [ 4, 0,-4, 0,-4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0,-2, 0,-2, 0, 2, 0,-2, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
75 | - [ 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,-4, 0,-4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0,-2, 0,-2, 0, 2, 0,-2, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0], | |
76 | - [-12, 12,12,-12,12,-12,-12,12,-8,-4, 8, 4, 8, 4,-8,-4,-6, 6,-6, 6, 6,-6, 6,-6,-6, 6, 6,-6,-6, 6, 6,-6,-4,-2,-4,-2, 4, 2, 4, 2,-4,-2, 4, 2,-4,-2, 4, 2,-3, 3,-3, 3,-3, 3,-3, 3,-2,-1,-2,-1,-2,-1,-2,-1], | |
77 | - [ 8, -8,-8, 8,-8, 8, 8,-8, 4, 4,-4,-4,-4,-4, 4, 4, 4,-4, 4,-4,-4, 4,-4, 4, 4,-4,-4, 4, 4,-4,-4, 4, 2, 2, 2, 2,-2,-2,-2,-2, 2, 2,-2,-2, 2, 2,-2,-2, 2,-2, 2,-2, 2,-2, 2,-2, 1, 1, 1, 1, 1, 1, 1, 1] | |
78 | -] | |
79 | - | |
80 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
81 | -@cython.cdivision(True) | |
82 | -@cython.wraparound(False) | |
83 | -cdef double nearest_neighbour_interp(image_t[:, :, :] V, double x, double y, double z) nogil: | |
84 | - return V[<int>(z), <int>(y), <int>(x)] | |
85 | - | |
86 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
87 | -@cython.cdivision(True) | |
88 | -@cython.wraparound(False) | |
89 | -cdef double interpolate(image_t[:, :, :] V, double x, double y, double z) nogil: | |
90 | - cdef double xd, yd, zd | |
91 | - cdef double c00, c10, c01, c11 | |
92 | - cdef double c0, c1 | |
93 | - cdef double c | |
94 | - | |
95 | - cdef int x0 = <int>floor(x) | |
96 | - cdef int x1 = x0 + 1 | |
97 | - | |
98 | - cdef int y0 = <int>floor(y) | |
99 | - cdef int y1 = y0 + 1 | |
100 | - | |
101 | - cdef int z0 = <int>floor(z) | |
102 | - cdef int z1 = z0 + 1 | |
103 | - | |
104 | - if x0 == x1: | |
105 | - xd = 1.0 | |
106 | - else: | |
107 | - xd = (x - x0) / (x1 - x0) | |
108 | - | |
109 | - if y0 == y1: | |
110 | - yd = 1.0 | |
111 | - else: | |
112 | - yd = (y - y0) / (y1 - y0) | |
113 | - | |
114 | - if z0 == z1: | |
115 | - zd = 1.0 | |
116 | - else: | |
117 | - zd = (z - z0) / (z1 - z0) | |
118 | - | |
119 | - c00 = _G(V, x0, y0, z0)*(1 - xd) + _G(V, x1, y0, z0)*xd | |
120 | - c10 = _G(V, x0, y1, z0)*(1 - xd) + _G(V, x1, y1, z0)*xd | |
121 | - c01 = _G(V, x0, y0, z1)*(1 - xd) + _G(V, x1, y0, z1)*xd | |
122 | - c11 = _G(V, x0, y1, z1)*(1 - xd) + _G(V, x1, y1, z1)*xd | |
123 | - | |
124 | - c0 = c00*(1 - yd) + c10*yd | |
125 | - c1 = c01*(1 - yd) + c11*yd | |
126 | - | |
127 | - c = c0*(1 - zd) + c1*zd | |
128 | - | |
129 | - return c | |
130 | - | |
131 | - | |
132 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
133 | -@cython.cdivision(True) | |
134 | -@cython.wraparound(False) | |
135 | -cdef inline double lanczos3_L(double x, int a) nogil: | |
136 | - if x == 0: | |
137 | - return 1.0 | |
138 | - elif -a <= x < a: | |
139 | - return (a * sin(M_PI * x) * sin(M_PI * (x / a)))/(M_PI**2 * x**2) | |
140 | - else: | |
141 | - return 0.0 | |
142 | - | |
143 | - | |
144 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
145 | -@cython.cdivision(True) | |
146 | -@cython.wraparound(False) | |
147 | -cdef double lanczos3(image_t[:, :, :] V, double x, double y, double z) nogil: | |
148 | - cdef int a = LANCZOS_A | |
149 | - | |
150 | - cdef int xd = <int>floor(x) | |
151 | - cdef int yd = <int>floor(y) | |
152 | - cdef int zd = <int>floor(z) | |
153 | - | |
154 | - cdef int xi = xd - a + 1 | |
155 | - cdef int xf = xd + a | |
156 | - | |
157 | - cdef int yi = yd - a + 1 | |
158 | - cdef int yf = yd + a | |
159 | - | |
160 | - cdef int zi = zd - a + 1 | |
161 | - cdef int zf = zd + a | |
162 | - | |
163 | - cdef double lx = 0.0 | |
164 | - cdef double ly = 0.0 | |
165 | - cdef double lz = 0.0 | |
166 | - | |
167 | - cdef double[SIZE_LANCZOS_TMP][SIZE_LANCZOS_TMP] temp_x | |
168 | - cdef double[SIZE_LANCZOS_TMP] temp_y | |
169 | - | |
170 | - cdef int i, j, k | |
171 | - cdef int m, n, o | |
172 | - | |
173 | - m = 0 | |
174 | - for k in xrange(zi, zf): | |
175 | - n = 0 | |
176 | - for j in xrange(yi, yf): | |
177 | - lx = 0 | |
178 | - for i in xrange(xi, xf): | |
179 | - lx += _G(V, i, j, k) * lanczos3_L(x - i, a) | |
180 | - temp_x[m][n] = lx | |
181 | - n += 1 | |
182 | - m += 1 | |
183 | - | |
184 | - m = 0 | |
185 | - for k in xrange(zi, zf): | |
186 | - n = 0 | |
187 | - ly = 0 | |
188 | - for j in xrange(yi, yf): | |
189 | - ly += temp_x[m][n] * lanczos3_L(y - j, a) | |
190 | - n += 1 | |
191 | - temp_y[m] = ly | |
192 | - m += 1 | |
193 | - | |
194 | - m = 0 | |
195 | - for k in xrange(zi, zf): | |
196 | - lz += temp_y[m] * lanczos3_L(z - k, a) | |
197 | - m += 1 | |
198 | - | |
199 | - return lz | |
200 | - | |
201 | - | |
202 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
203 | -@cython.cdivision(True) | |
204 | -@cython.wraparound(False) | |
205 | -cdef image_t _G(image_t[:, :, :] V, int x, int y, int z) nogil: | |
206 | - cdef int dz, dy, dx | |
207 | - dz = V.shape[0] - 1 | |
208 | - dy = V.shape[1] - 1 | |
209 | - dx = V.shape[2] - 1 | |
210 | - | |
211 | - if x < 0: | |
212 | - x = dx + x + 1 | |
213 | - elif x > dx: | |
214 | - x = x - dx - 1 | |
215 | - | |
216 | - if y < 0: | |
217 | - y = dy + y + 1 | |
218 | - elif y > dy: | |
219 | - y = y - dy - 1 | |
220 | - | |
221 | - if z < 0: | |
222 | - z = dz + z + 1 | |
223 | - elif z > dz: | |
224 | - z = z - dz - 1 | |
225 | - | |
226 | - return V[z, y, x] | |
227 | - | |
228 | - | |
229 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
230 | -@cython.cdivision(True) | |
231 | -@cython.wraparound(False) | |
232 | -cdef void calc_coef_tricub(image_t[:, :, :] V, double x, double y, double z, double [64] coef) nogil: | |
233 | - cdef int xi = <int>floor(x) | |
234 | - cdef int yi = <int>floor(y) | |
235 | - cdef int zi = <int>floor(z) | |
236 | - | |
237 | - cdef double[64] _x | |
238 | - | |
239 | - cdef int i, j | |
240 | - | |
241 | - _x[0] = _G(V, xi, yi, zi) | |
242 | - _x[1] = _G(V, xi + 1, yi, zi) | |
243 | - _x[2] = _G(V, xi, yi + 1, zi) | |
244 | - _x[3] = _G(V, xi + 1, yi + 1, zi) | |
245 | - _x[4] = _G(V, xi, yi, zi + 1) | |
246 | - _x[5] = _G(V, xi + 1, yi, zi + 1) | |
247 | - _x[6] = _G(V, xi, yi + 1, zi + 1) | |
248 | - _x[7] = _G(V, xi + 1, yi + 1, zi + 1) | |
249 | - | |
250 | - _x[8] = 0.5*(_G(V, xi+1,yi,zi) - _G(V, xi-1, yi, zi)) | |
251 | - _x[9] = 0.5*(_G(V, xi+2,yi,zi) - _G(V, xi, yi, zi)) | |
252 | - _x[10] = 0.5*(_G(V, xi+1, yi+1,zi) - _G(V, xi-1, yi+1, zi)) | |
253 | - _x[11] = 0.5*(_G(V, xi+2, yi+1,zi) - _G(V, xi, yi+1, zi)) | |
254 | - _x[12] = 0.5*(_G(V, xi+1, yi,zi+1) - _G(V, xi-1, yi, zi+1)) | |
255 | - _x[13] = 0.5*(_G(V, xi+2, yi,zi+1) - _G(V, xi, yi, zi+1)) | |
256 | - _x[14] = 0.5*(_G(V, xi+1, yi+1,zi+1) - _G(V, xi-1, yi+1, zi+1)) | |
257 | - _x[15] = 0.5*(_G(V, xi+2, yi+1,zi+1) - _G(V, xi, yi+1, zi+1)) | |
258 | - _x[16] = 0.5*(_G(V, xi, yi+1,zi) - _G(V, xi, yi-1, zi)) | |
259 | - _x[17] = 0.5*(_G(V, xi+1, yi+1,zi) - _G(V, xi+1, yi-1, zi)) | |
260 | - _x[18] = 0.5*(_G(V, xi, yi+2,zi) - _G(V, xi, yi, zi)) | |
261 | - _x[19] = 0.5*(_G(V, xi+1, yi+2,zi) - _G(V, xi+1, yi, zi)) | |
262 | - _x[20] = 0.5*(_G(V, xi, yi+1,zi+1) - _G(V, xi, yi-1, zi+1)) | |
263 | - _x[21] = 0.5*(_G(V, xi+1, yi+1,zi+1) - _G(V, xi+1, yi-1, zi+1)) | |
264 | - _x[22] = 0.5*(_G(V, xi, yi+2,zi+1) - _G(V, xi, yi, zi+1)) | |
265 | - _x[23] = 0.5*(_G(V, xi+1, yi+2,zi+1) - _G(V, xi+1, yi, zi+1)) | |
266 | - _x[24] = 0.5*(_G(V, xi, yi,zi+1) - _G(V, xi, yi, zi-1)) | |
267 | - _x[25] = 0.5*(_G(V, xi+1, yi,zi+1) - _G(V, xi+1, yi, zi-1)) | |
268 | - _x[26] = 0.5*(_G(V, xi, yi+1,zi+1) - _G(V, xi, yi+1, zi-1)) | |
269 | - _x[27] = 0.5*(_G(V, xi+1, yi+1,zi+1) - _G(V, xi+1, yi+1, zi-1)) | |
270 | - _x[28] = 0.5*(_G(V, xi, yi,zi+2) - _G(V, xi, yi, zi)) | |
271 | - _x[29] = 0.5*(_G(V, xi+1, yi,zi+2) - _G(V, xi+1, yi, zi)) | |
272 | - _x[30] = 0.5*(_G(V, xi, yi+1,zi+2) - _G(V, xi, yi+1, zi)) | |
273 | - _x[31] = 0.5*(_G(V, xi+1, yi+1,zi+2) - _G(V, xi+1, yi+1, zi)) | |
274 | - | |
275 | - _x [32] = 0.25*(_G(V, xi+1, yi+1, zi) - _G(V, xi-1, yi+1, zi) - _G(V, xi+1, yi-1, zi) + _G(V, xi-1, yi-1, zi)) | |
276 | - _x [33] = 0.25*(_G(V, xi+2, yi+1, zi) - _G(V, xi, yi+1, zi) - _G(V, xi+2, yi-1, zi) + _G(V, xi, yi-1, zi)) | |
277 | - _x [34] = 0.25*(_G(V, xi+1, yi+2, zi) - _G(V, xi-1, yi+2, zi) - _G(V, xi+1, yi, zi) + _G(V, xi-1, yi, zi)) | |
278 | - _x [35] = 0.25*(_G(V, xi+2, yi+2, zi) - _G(V, xi, yi+2, zi) - _G(V, xi+2, yi, zi) + _G(V, xi, yi, zi)) | |
279 | - _x [36] = 0.25*(_G(V, xi+1, yi+1, zi+1) - _G(V, xi-1, yi+1, zi+1) - _G(V, xi+1, yi-1, zi+1) + _G(V, xi-1, yi-1, zi+1)) | |
280 | - _x [37] = 0.25*(_G(V, xi+2, yi+1, zi+1) - _G(V, xi, yi+1, zi+1) - _G(V, xi+2, yi-1, zi+1) + _G(V, xi, yi-1, zi+1)) | |
281 | - _x [38] = 0.25*(_G(V, xi+1, yi+2, zi+1) - _G(V, xi-1, yi+2, zi+1) - _G(V, xi+1, yi, zi+1) + _G(V, xi-1, yi, zi+1)) | |
282 | - _x [39] = 0.25*(_G(V, xi+2, yi+2, zi+1) - _G(V, xi, yi+2, zi+1) - _G(V, xi+2, yi, zi+1) + _G(V, xi, yi, zi+1)) | |
283 | - _x [40] = 0.25*(_G(V, xi+1, yi, zi+1) - _G(V, xi-1, yi, zi+1) - _G(V, xi+1, yi, zi-1) + _G(V, xi-1, yi, zi-1)) | |
284 | - _x [41] = 0.25*(_G(V, xi+2, yi, zi+1) - _G(V, xi, yi, zi+1) - _G(V, xi+2, yi, zi-1) + _G(V, xi, yi, zi-1)) | |
285 | - _x [42] = 0.25*(_G(V, xi+1, yi+1, zi+1) - _G(V, xi-1, yi+1, zi+1) - _G(V, xi+1, yi+1, zi-1) + _G(V, xi-1, yi+1, zi-1)) | |
286 | - _x [43] = 0.25*(_G(V, xi+2, yi+1, zi+1) - _G(V, xi, yi+1, zi+1) - _G(V, xi+2, yi+1, zi-1) + _G(V, xi, yi+1, zi-1)) | |
287 | - _x [44] = 0.25*(_G(V, xi+1, yi, zi+2) - _G(V, xi-1, yi, zi+2) - _G(V, xi+1, yi, zi) + _G(V, xi-1, yi, zi)) | |
288 | - _x [45] = 0.25*(_G(V, xi+2, yi, zi+2) - _G(V, xi, yi, zi+2) - _G(V, xi+2, yi, zi) + _G(V, xi, yi, zi)) | |
289 | - _x [46] = 0.25*(_G(V, xi+1, yi+1, zi+2) - _G(V, xi-1, yi+1, zi+2) - _G(V, xi+1, yi+1, zi) + _G(V, xi-1, yi+1, zi)) | |
290 | - _x [47] = 0.25*(_G(V, xi+2, yi+1, zi+2) - _G(V, xi, yi+1, zi+2) - _G(V, xi+2, yi+1, zi) + _G(V, xi, yi+1, zi)) | |
291 | - _x [48] = 0.25*(_G(V, xi, yi+1, zi+1) - _G(V, xi, yi-1, zi+1) - _G(V, xi, yi+1, zi-1) + _G(V, xi, yi-1, zi-1)) | |
292 | - _x [49] = 0.25*(_G(V, xi+1, yi+1, zi+1) - _G(V, xi+1, yi-1, zi+1) - _G(V, xi+1, yi+1, zi-1) + _G(V, xi+1, yi-1, zi-1)) | |
293 | - _x [50] = 0.25*(_G(V, xi, yi+2, zi+1) - _G(V, xi, yi, zi+1) - _G(V, xi, yi+2, zi-1) + _G(V, xi, yi, zi-1)) | |
294 | - _x [51] = 0.25*(_G(V, xi+1, yi+2, zi+1) - _G(V, xi+1, yi, zi+1) - _G(V, xi+1, yi+2, zi-1) + _G(V, xi+1, yi, zi-1)) | |
295 | - _x [52] = 0.25*(_G(V, xi, yi+1, zi+2) - _G(V, xi, yi-1, zi+2) - _G(V, xi, yi+1, zi) + _G(V, xi, yi-1, zi)) | |
296 | - _x [53] = 0.25*(_G(V, xi+1, yi+1, zi+2) - _G(V, xi+1, yi-1, zi+2) - _G(V, xi+1, yi+1, zi) + _G(V, xi+1, yi-1, zi)) | |
297 | - _x [54] = 0.25*(_G(V, xi, yi+2, zi+2) - _G(V, xi, yi, zi+2) - _G(V, xi, yi+2, zi) + _G(V, xi, yi, zi)) | |
298 | - _x [55] = 0.25*(_G(V, xi+1, yi+2, zi+2) - _G(V, xi+1, yi, zi+2) - _G(V, xi+1, yi+2, zi) + _G(V, xi+1, yi, zi)) | |
299 | - | |
300 | - _x[56] = 0.125*(_G(V, xi+1, yi+1, zi+1) - _G(V, xi-1, yi+1, zi+1) - _G(V, xi+1, yi-1, zi+1) + _G(V, xi-1, yi-1, zi+1) - _G(V, xi+1, yi+1, zi-1) + _G(V, xi-1,yi+1,zi-1)+_G(V, xi+1,yi-1,zi-1)-_G(V, xi-1,yi-1,zi-1)) | |
301 | - _x[57] = 0.125*(_G(V, xi+2, yi+1, zi+1) - _G(V, xi, yi+1, zi+1) - _G(V, xi+2, yi-1, zi+1) + _G(V, xi, yi-1, zi+1) - _G(V, xi+2, yi+1, zi-1) + _G(V, xi,yi+1,zi-1)+_G(V, xi+2,yi-1,zi-1)-_G(V, xi,yi-1,zi-1)) | |
302 | - _x[58] = 0.125*(_G(V, xi+1, yi+2, zi+1) - _G(V, xi-1, yi+2, zi+1) - _G(V, xi+1, yi, zi+1) + _G(V, xi-1, yi, zi+1) - _G(V, xi+1, yi+2, zi-1) + _G(V, xi-1,yi+2,zi-1)+_G(V, xi+1,yi,zi-1)-_G(V, xi-1,yi,zi-1)) | |
303 | - _x[59] = 0.125*(_G(V, xi+2, yi+2, zi+1) - _G(V, xi, yi+2, zi+1) - _G(V, xi+2, yi, zi+1) + _G(V, xi, yi, zi+1) - _G(V, xi+2, yi+2, zi-1) + _G(V, xi,yi+2,zi-1)+_G(V, xi+2,yi,zi-1)-_G(V, xi,yi,zi-1)) | |
304 | - _x[60] = 0.125*(_G(V, xi+1, yi+1, zi+2) - _G(V, xi-1, yi+1, zi+2) - _G(V, xi+1, yi-1, zi+2) + _G(V, xi-1, yi-1, zi+2) - _G(V, xi+1, yi+1, zi) + _G(V, xi-1,yi+1,zi)+_G(V, xi+1,yi-1,zi)-_G(V, xi-1,yi-1,zi)) | |
305 | - _x[61] = 0.125*(_G(V, xi+2, yi+1, zi+2) - _G(V, xi, yi+1, zi+2) - _G(V, xi+2, yi-1, zi+2) + _G(V, xi, yi-1, zi+2) - _G(V, xi+2, yi+1, zi) + _G(V, xi,yi+1,zi)+_G(V, xi+2,yi-1,zi)-_G(V, xi,yi-1,zi)) | |
306 | - _x[62] = 0.125*(_G(V, xi+1, yi+2, zi+2) - _G(V, xi-1, yi+2, zi+2) - _G(V, xi+1, yi, zi+2) + _G(V, xi-1, yi, zi+2) - _G(V, xi+1, yi+2, zi) + _G(V, xi-1,yi+2,zi)+_G(V, xi+1,yi,zi)-_G(V, xi-1,yi,zi)) | |
307 | - _x[63] = 0.125*(_G(V, xi+2, yi+2, zi+2) - _G(V, xi, yi+2, zi+2) - _G(V, xi+2, yi, zi+2) + _G(V, xi, yi, zi+2) - _G(V, xi+2, yi+2, zi) + _G(V, xi,yi+2,zi)+_G(V, xi+2,yi,zi)-_G(V, xi,yi,zi)) | |
308 | - | |
309 | - for j in prange(64): | |
310 | - coef[j] = 0.0 | |
311 | - for i in xrange(64): | |
312 | - coef[j] += (temp[j][i] * _x[i]) | |
313 | - | |
314 | - | |
315 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
316 | -@cython.cdivision(True) | |
317 | -@cython.wraparound(False) | |
318 | -cdef double tricub_interpolate(image_t[:, :, :] V, double x, double y, double z) nogil: | |
319 | - # From: Tricubic interpolation in three dimensions. Lekien and Marsden | |
320 | - cdef double[64] coef | |
321 | - cdef double result = 0.0 | |
322 | - calc_coef_tricub(V, x, y, z, coef) | |
323 | - | |
324 | - cdef int i, j, k | |
325 | - | |
326 | - cdef int xi = <int>floor(x) | |
327 | - cdef int yi = <int>floor(y) | |
328 | - cdef int zi = <int>floor(z) | |
329 | - | |
330 | - for i in xrange(4): | |
331 | - for j in xrange(4): | |
332 | - for k in xrange(4): | |
333 | - result += (coef[i+4*j+16*k] * ((x-xi)**i) * ((y-yi)**j) * ((z-zi)**k)) | |
334 | - # return V[<int>z, <int>y, <int>x] | |
335 | - # with gil: | |
336 | - # print result | |
337 | - return result | |
338 | - | |
339 | - | |
340 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
341 | -@cython.cdivision(True) | |
342 | -@cython.wraparound(False) | |
343 | -cdef double cubicInterpolate(double p[4], double x) nogil: | |
344 | - return p[1] + 0.5 * x*(p[2] - p[0] + x*(2.0*p[0] - 5.0*p[1] + 4.0*p[2] - p[3] + x*(3.0*(p[1] - p[2]) + p[3] - p[0]))) | |
345 | - | |
346 | - | |
347 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
348 | -@cython.cdivision(True) | |
349 | -@cython.wraparound(False) | |
350 | -cdef double bicubicInterpolate (double p[4][4], double x, double y) nogil: | |
351 | - cdef double arr[4] | |
352 | - arr[0] = cubicInterpolate(p[0], y) | |
353 | - arr[1] = cubicInterpolate(p[1], y) | |
354 | - arr[2] = cubicInterpolate(p[2], y) | |
355 | - arr[3] = cubicInterpolate(p[3], y) | |
356 | - return cubicInterpolate(arr, x) | |
357 | - | |
358 | - | |
359 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
360 | -@cython.cdivision(True) | |
361 | -@cython.wraparound(False) | |
362 | -cdef double tricubicInterpolate(image_t[:, :, :] V, double x, double y, double z) nogil: | |
363 | - # From http://www.paulinternet.nl/?page=bicubic | |
364 | - cdef double p[4][4][4] | |
365 | - | |
366 | - cdef int xi = <int>floor(x) | |
367 | - cdef int yi = <int>floor(y) | |
368 | - cdef int zi = <int>floor(z) | |
369 | - | |
370 | - cdef int i, j, k | |
371 | - | |
372 | - for i in xrange(4): | |
373 | - for j in xrange(4): | |
374 | - for k in xrange(4): | |
375 | - p[i][j][k] = _G(V, xi + i -1, yi + j -1, zi + k - 1) | |
376 | - | |
377 | - cdef double arr[4] | |
378 | - arr[0] = bicubicInterpolate(p[0], y-yi, z-zi) | |
379 | - arr[1] = bicubicInterpolate(p[1], y-yi, z-zi) | |
380 | - arr[2] = bicubicInterpolate(p[2], y-yi, z-zi) | |
381 | - arr[3] = bicubicInterpolate(p[3], y-yi, z-zi) | |
382 | - return cubicInterpolate(arr, x-xi) | |
383 | - | |
384 | - | |
385 | -def tricub_interpolate_py(image_t[:, :, :] V, double x, double y, double z): | |
386 | - return tricub_interpolate(V, x, y, z) | |
387 | - | |
388 | -def tricub_interpolate2_py(image_t[:, :, :] V, double x, double y, double z): | |
389 | - return tricubicInterpolate(V, x, y, z) | |
390 | - | |
391 | -def trilin_interpolate_py(image_t[:, :, :] V, double x, double y, double z): | |
392 | - return interpolate(V, x, y, z) |
invesalius/data/mask.py
... | ... | @@ -30,7 +30,7 @@ import invesalius.constants as const |
30 | 30 | import invesalius.data.imagedata_utils as iu |
31 | 31 | import invesalius.session as ses |
32 | 32 | |
33 | -from . import floodfill | |
33 | +from invesalius_cy import floodfill | |
34 | 34 | |
35 | 35 | from wx.lib.pubsub import pub as Publisher |
36 | 36 | from scipy import ndimage | ... | ... |
invesalius/data/mips.pyx
... | ... | @@ -1,379 +0,0 @@ |
1 | -#http://en.wikipedia.org/wiki/Local_maximum_intensity_projection | |
2 | -import numpy as np | |
3 | -cimport numpy as np | |
4 | -cimport cython | |
5 | - | |
6 | -from libc.math cimport floor, ceil, sqrt, fabs | |
7 | -from cython.parallel import prange | |
8 | - | |
9 | -DTYPE = np.uint8 | |
10 | -ctypedef np.uint8_t DTYPE_t | |
11 | - | |
12 | -DTYPE16 = np.int16 | |
13 | -ctypedef np.int16_t DTYPE16_t | |
14 | - | |
15 | -DTYPEF32 = np.float32 | |
16 | -ctypedef np.float32_t DTYPEF32_t | |
17 | - | |
18 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
19 | -def lmip(np.ndarray[DTYPE16_t, ndim=3] image, int axis, DTYPE16_t tmin, | |
20 | - DTYPE16_t tmax, np.ndarray[DTYPE16_t, ndim=2] out): | |
21 | - cdef DTYPE16_t max | |
22 | - cdef int start | |
23 | - cdef int sz = image.shape[0] | |
24 | - cdef int sy = image.shape[1] | |
25 | - cdef int sx = image.shape[2] | |
26 | - | |
27 | - # AXIAL | |
28 | - if axis == 0: | |
29 | - for x in xrange(sx): | |
30 | - for y in xrange(sy): | |
31 | - max = image[0, y, x] | |
32 | - if max >= tmin and max <= tmax: | |
33 | - start = 1 | |
34 | - else: | |
35 | - start = 0 | |
36 | - for z in xrange(sz): | |
37 | - if image[z, y, x] > max: | |
38 | - max = image[z, y, x] | |
39 | - | |
40 | - elif image[z, y, x] < max and start: | |
41 | - break | |
42 | - | |
43 | - if image[z, y, x] >= tmin and image[z, y, x] <= tmax: | |
44 | - start = 1 | |
45 | - | |
46 | - out[y, x] = max | |
47 | - | |
48 | - #CORONAL | |
49 | - elif axis == 1: | |
50 | - for z in xrange(sz): | |
51 | - for x in xrange(sx): | |
52 | - max = image[z, 0, x] | |
53 | - if max >= tmin and max <= tmax: | |
54 | - start = 1 | |
55 | - else: | |
56 | - start = 0 | |
57 | - for y in xrange(sy): | |
58 | - if image[z, y, x] > max: | |
59 | - max = image[z, y, x] | |
60 | - | |
61 | - elif image[z, y, x] < max and start: | |
62 | - break | |
63 | - | |
64 | - if image[z, y, x] >= tmin and image[z, y, x] <= tmax: | |
65 | - start = 1 | |
66 | - | |
67 | - out[z, x] = max | |
68 | - | |
69 | - #CORONAL | |
70 | - elif axis == 2: | |
71 | - for z in xrange(sz): | |
72 | - for y in xrange(sy): | |
73 | - max = image[z, y, 0] | |
74 | - if max >= tmin and max <= tmax: | |
75 | - start = 1 | |
76 | - else: | |
77 | - start = 0 | |
78 | - for x in xrange(sx): | |
79 | - if image[z, y, x] > max: | |
80 | - max = image[z, y, x] | |
81 | - | |
82 | - elif image[z, y, x] < max and start: | |
83 | - break | |
84 | - | |
85 | - if image[z, y, x] >= tmin and image[z, y, x] <= tmax: | |
86 | - start = 1 | |
87 | - | |
88 | - out[z, y] = max | |
89 | - | |
90 | - | |
91 | -cdef DTYPE16_t get_colour(DTYPE16_t vl, DTYPE16_t wl, DTYPE16_t ww): | |
92 | - cdef DTYPE16_t out_colour | |
93 | - cdef DTYPE16_t min_value = wl - (ww / 2) | |
94 | - cdef DTYPE16_t max_value = wl + (ww / 2) | |
95 | - if vl < min_value: | |
96 | - out_colour = min_value | |
97 | - elif vl > max_value: | |
98 | - out_colour = max_value | |
99 | - else: | |
100 | - out_colour = vl | |
101 | - | |
102 | - return out_colour | |
103 | - | |
104 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
105 | -@cython.cdivision(True) | |
106 | -cdef float get_opacity(DTYPE16_t vl, DTYPE16_t wl, DTYPE16_t ww) nogil: | |
107 | - cdef float out_opacity | |
108 | - cdef DTYPE16_t min_value = wl - (ww / 2) | |
109 | - cdef DTYPE16_t max_value = wl + (ww / 2) | |
110 | - if vl < min_value: | |
111 | - out_opacity = 0.0 | |
112 | - elif vl > max_value: | |
113 | - out_opacity = 1.0 | |
114 | - else: | |
115 | - out_opacity = 1.0/(max_value - min_value) * (vl - min_value) | |
116 | - | |
117 | - return out_opacity | |
118 | - | |
119 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
120 | -@cython.cdivision(True) | |
121 | -cdef float get_opacity_f32(DTYPEF32_t vl, DTYPE16_t wl, DTYPE16_t ww) nogil: | |
122 | - cdef float out_opacity | |
123 | - cdef DTYPE16_t min_value = wl - (ww / 2) | |
124 | - cdef DTYPE16_t max_value = wl + (ww / 2) | |
125 | - if vl < min_value: | |
126 | - out_opacity = 0.0 | |
127 | - elif vl > max_value: | |
128 | - out_opacity = 1.0 | |
129 | - else: | |
130 | - out_opacity = 1.0/(max_value - min_value) * (vl - min_value) | |
131 | - | |
132 | - return out_opacity | |
133 | - | |
134 | - | |
135 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
136 | -@cython.cdivision(True) | |
137 | -def mida(np.ndarray[DTYPE16_t, ndim=3] image, int axis, DTYPE16_t wl, | |
138 | - DTYPE16_t ww, np.ndarray[DTYPE16_t, ndim=2] out): | |
139 | - cdef int sz = image.shape[0] | |
140 | - cdef int sy = image.shape[1] | |
141 | - cdef int sx = image.shape[2] | |
142 | - | |
143 | - cdef DTYPE16_t min = image.min() | |
144 | - cdef DTYPE16_t max = image.max() | |
145 | - cdef DTYPE16_t vl | |
146 | - | |
147 | - cdef DTYPE16_t min_value = wl - (ww / 2) | |
148 | - cdef DTYPE16_t max_value = wl + (ww / 2) | |
149 | - | |
150 | - cdef float fmax=0.0 | |
151 | - cdef float fpi | |
152 | - cdef float dl | |
153 | - cdef float bt | |
154 | - | |
155 | - cdef float alpha | |
156 | - cdef float alpha_p = 0.0 | |
157 | - cdef float colour | |
158 | - cdef float colour_p = 0 | |
159 | - | |
160 | - cdef int x, y, z | |
161 | - | |
162 | - # AXIAL | |
163 | - if axis == 0: | |
164 | - for x in prange(sx, nogil=True): | |
165 | - for y in xrange(sy): | |
166 | - fmax = 0.0 | |
167 | - alpha_p = 0.0 | |
168 | - colour_p = 0.0 | |
169 | - for z in xrange(sz): | |
170 | - vl = image[z, y, x] | |
171 | - fpi = 1.0/(max - min) * (vl - min) | |
172 | - if fpi > fmax: | |
173 | - dl = fpi - fmax | |
174 | - fmax = fpi | |
175 | - else: | |
176 | - dl = 0.0 | |
177 | - | |
178 | - bt = 1.0 - dl | |
179 | - | |
180 | - colour = fpi | |
181 | - alpha = get_opacity(vl, wl, ww) | |
182 | - colour = (bt * colour_p) + (1 - bt * alpha_p) * colour * alpha | |
183 | - alpha = (bt * alpha_p) + (1 - bt * alpha_p) * alpha | |
184 | - | |
185 | - colour_p = colour | |
186 | - alpha_p = alpha | |
187 | - | |
188 | - if alpha >= 1.0: | |
189 | - break | |
190 | - | |
191 | - | |
192 | - #out[y, x] = <DTYPE16_t>((max_value - min_value) * colour + min_value) | |
193 | - out[y, x] = <DTYPE16_t>((max - min) * colour + min) | |
194 | - | |
195 | - | |
196 | - #CORONAL | |
197 | - elif axis == 1: | |
198 | - for z in prange(sz, nogil=True): | |
199 | - for x in xrange(sx): | |
200 | - fmax = 0.0 | |
201 | - alpha_p = 0.0 | |
202 | - colour_p = 0.0 | |
203 | - for y in xrange(sy): | |
204 | - vl = image[z, y, x] | |
205 | - fpi = 1.0/(max - min) * (vl - min) | |
206 | - if fpi > fmax: | |
207 | - dl = fpi - fmax | |
208 | - fmax = fpi | |
209 | - else: | |
210 | - dl = 0.0 | |
211 | - | |
212 | - bt = 1.0 - dl | |
213 | - | |
214 | - colour = fpi | |
215 | - alpha = get_opacity(vl, wl, ww) | |
216 | - colour = (bt * colour_p) + (1 - bt * alpha_p) * colour * alpha | |
217 | - alpha = (bt * alpha_p) + (1 - bt * alpha_p) * alpha | |
218 | - | |
219 | - colour_p = colour | |
220 | - alpha_p = alpha | |
221 | - | |
222 | - if alpha >= 1.0: | |
223 | - break | |
224 | - | |
225 | - out[z, x] = <DTYPE16_t>((max - min) * colour + min) | |
226 | - | |
227 | - #AXIAL | |
228 | - elif axis == 2: | |
229 | - for z in prange(sz, nogil=True): | |
230 | - for y in xrange(sy): | |
231 | - fmax = 0.0 | |
232 | - alpha_p = 0.0 | |
233 | - colour_p = 0.0 | |
234 | - for x in xrange(sx): | |
235 | - vl = image[z, y, x] | |
236 | - fpi = 1.0/(max - min) * (vl - min) | |
237 | - if fpi > fmax: | |
238 | - dl = fpi - fmax | |
239 | - fmax = fpi | |
240 | - else: | |
241 | - dl = 0.0 | |
242 | - | |
243 | - bt = 1.0 - dl | |
244 | - | |
245 | - colour = fpi | |
246 | - alpha = get_opacity(vl, wl, ww) | |
247 | - colour = (bt * colour_p) + (1 - bt * alpha_p) * colour * alpha | |
248 | - alpha = (bt * alpha_p) + (1 - bt * alpha_p) * alpha | |
249 | - | |
250 | - colour_p = colour | |
251 | - alpha_p = alpha | |
252 | - | |
253 | - if alpha >= 1.0: | |
254 | - break | |
255 | - | |
256 | - out[z, y] = <DTYPE16_t>((max - min) * colour + min) | |
257 | - | |
258 | - | |
259 | - | |
260 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
261 | -@cython.cdivision(True) | |
262 | -cdef inline void finite_difference(DTYPE16_t[:, :, :] image, | |
263 | - int x, int y, int z, float h, float *g) nogil: | |
264 | - cdef int px, py, pz, fx, fy, fz | |
265 | - | |
266 | - cdef int sz = image.shape[0] | |
267 | - cdef int sy = image.shape[1] | |
268 | - cdef int sx = image.shape[2] | |
269 | - | |
270 | - cdef float gx, gy, gz | |
271 | - | |
272 | - if x == 0: | |
273 | - px = 0 | |
274 | - fx = 1 | |
275 | - elif x == sx - 1: | |
276 | - px = x - 1 | |
277 | - fx = x | |
278 | - else: | |
279 | - px = x - 1 | |
280 | - fx = x + 1 | |
281 | - | |
282 | - if y == 0: | |
283 | - py = 0 | |
284 | - fy = 1 | |
285 | - elif y == sy - 1: | |
286 | - py = y - 1 | |
287 | - fy = y | |
288 | - else: | |
289 | - py = y - 1 | |
290 | - fy = y + 1 | |
291 | - | |
292 | - if z == 0: | |
293 | - pz = 0 | |
294 | - fz = 1 | |
295 | - elif z == sz - 1: | |
296 | - pz = z - 1 | |
297 | - fz = z | |
298 | - else: | |
299 | - pz = z - 1 | |
300 | - fz = z + 1 | |
301 | - | |
302 | - gx = (image[z, y, fx] - image[z, y, px]) / (2*h) | |
303 | - gy = (image[z, fy, x] - image[z, py, x]) / (2*h) | |
304 | - gz = (image[fz, y, x] - image[pz, y, x]) / (2*h) | |
305 | - | |
306 | - g[0] = gx | |
307 | - g[1] = gy | |
308 | - g[2] = gz | |
309 | - | |
310 | - | |
311 | - | |
312 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
313 | -@cython.cdivision(True) | |
314 | -cdef inline float calc_fcm_itensity(DTYPE16_t[:, :, :] image, | |
315 | - int x, int y, int z, float n, float* dir) nogil: | |
316 | - cdef float g[3] | |
317 | - finite_difference(image, x, y, z, 1.0, g) | |
318 | - cdef float gm = sqrt(g[0]*g[0] + g[1]*g[1] + g[2]*g[2]) | |
319 | - cdef float d = g[0]*dir[0] + g[1]*dir[1] + g[2]*dir[2] | |
320 | - cdef float sf = (1.0 - fabs(d/gm))**n | |
321 | - #alpha = get_opacity_f32(gm, wl, ww) | |
322 | - cdef float vl = gm * sf | |
323 | - return vl | |
324 | - | |
325 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
326 | -@cython.cdivision(True) | |
327 | -def fast_countour_mip(np.ndarray[DTYPE16_t, ndim=3] image, | |
328 | - float n, | |
329 | - int axis, | |
330 | - DTYPE16_t wl, DTYPE16_t ww, | |
331 | - int tmip, | |
332 | - np.ndarray[DTYPE16_t, ndim=2] out): | |
333 | - cdef int sz = image.shape[0] | |
334 | - cdef int sy = image.shape[1] | |
335 | - cdef int sx = image.shape[2] | |
336 | - cdef float gm | |
337 | - cdef float alpha | |
338 | - cdef float sf | |
339 | - cdef float d | |
340 | - | |
341 | - cdef float* g | |
342 | - cdef float* dir = [ 0, 0, 0 ] | |
343 | - | |
344 | - cdef DTYPE16_t[:, :, :] vimage = image | |
345 | - cdef np.ndarray[DTYPE16_t, ndim=3] tmp = np.empty_like(image) | |
346 | - | |
347 | - cdef DTYPE16_t min = image.min() | |
348 | - cdef DTYPE16_t max = image.max() | |
349 | - cdef float fmin = <float>min | |
350 | - cdef float fmax = <float>max | |
351 | - cdef float vl | |
352 | - cdef DTYPE16_t V | |
353 | - | |
354 | - cdef int x, y, z | |
355 | - | |
356 | - if axis == 0: | |
357 | - dir[2] = 1.0 | |
358 | - elif axis == 1: | |
359 | - dir[1] = 1.0 | |
360 | - elif axis == 2: | |
361 | - dir[0] = 1.0 | |
362 | - | |
363 | - for z in prange(sz, nogil=True): | |
364 | - for y in range(sy): | |
365 | - for x in range(sx): | |
366 | - vl = calc_fcm_itensity(vimage, x, y, z, n, dir) | |
367 | - tmp[z, y, x] = <DTYPE16_t>vl | |
368 | - | |
369 | - cdef DTYPE16_t tmin = tmp.min() | |
370 | - cdef DTYPE16_t tmax = tmp.max() | |
371 | - | |
372 | - #tmp = ((max - min)/<float>(tmax - tmin)) * (tmp - tmin) + min | |
373 | - | |
374 | - if tmip == 0: | |
375 | - out[:] = tmp.max(axis) | |
376 | - elif tmip == 1: | |
377 | - lmip(tmp, axis, 700, 3033, out) | |
378 | - elif tmip == 2: | |
379 | - mida(tmp, axis, wl, ww, out) |
invesalius/data/slice_.py
... | ... | @@ -28,13 +28,13 @@ from wx.lib.pubsub import pub as Publisher |
28 | 28 | import invesalius.constants as const |
29 | 29 | import invesalius.data.converters as converters |
30 | 30 | import invesalius.data.imagedata_utils as iu |
31 | -import invesalius.data.transformations as transformations | |
32 | 31 | import invesalius.session as ses |
33 | 32 | import invesalius.style as st |
34 | 33 | import invesalius.utils as utils |
35 | -from invesalius.data import mips, transforms | |
34 | +from invesalius.data import transformations | |
36 | 35 | from invesalius.data.mask import Mask |
37 | 36 | from invesalius.project import Project |
37 | +from invesalius_cy import mips, transforms | |
38 | 38 | |
39 | 39 | OTHER = 0 |
40 | 40 | PLIST = 1 | ... | ... |
invesalius/data/styles.py
... | ... | @@ -46,7 +46,7 @@ import invesalius.utils as utils |
46 | 46 | from invesalius.data.measures import (CircleDensityMeasure, MeasureData, |
47 | 47 | PolygonDensityMeasure) |
48 | 48 | |
49 | -from . import floodfill | |
49 | +from invesalius_cy import floodfill | |
50 | 50 | |
51 | 51 | ORIENTATIONS = { |
52 | 52 | "AXIAL": const.AXIAL, | ... | ... |
invesalius/data/surface.py
... | ... | @@ -59,9 +59,9 @@ import invesalius.utils as utl |
59 | 59 | import invesalius.data.vtk_utils as vu |
60 | 60 | |
61 | 61 | from invesalius.gui import dialogs |
62 | +from invesalius_cy import cy_mesh | |
62 | 63 | |
63 | -from invesalius.data import cy_mesh | |
64 | -# TODO: Verificar ReleaseDataFlagOn and SetSource | |
64 | +# TODO: Verificar ReleaseDataFlagOn and SetSource | |
65 | 65 | |
66 | 66 | |
67 | 67 | class Surface(): | ... | ... |
invesalius/data/surface_process.py
invesalius/data/transforms.pyx
... | ... | @@ -1,174 +0,0 @@ |
1 | -import numpy as np | |
2 | -cimport numpy as np | |
3 | -cimport cython | |
4 | - | |
5 | -from .cy_my_types cimport image_t | |
6 | -from .interpolation cimport interpolate, tricub_interpolate, tricubicInterpolate, lanczos3, nearest_neighbour_interp | |
7 | - | |
8 | -from libc.math cimport floor, ceil, sqrt, fabs, round | |
9 | -from cython.parallel import prange | |
10 | - | |
11 | -ctypedef double (*interp_function)(image_t[:, :, :], double, double, double) nogil | |
12 | - | |
13 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
14 | -@cython.cdivision(True) | |
15 | -@cython.wraparound(False) | |
16 | -cdef void mul_mat4_vec4(double[:, :] M, | |
17 | - double* coord, | |
18 | - double* out) nogil: | |
19 | - | |
20 | - out[0] = coord[0] * M[0, 0] + coord[1] * M[0, 1] + coord[2] * M[0, 2] + coord[3] * M[0, 3] | |
21 | - out[1] = coord[0] * M[1, 0] + coord[1] * M[1, 1] + coord[2] * M[1, 2] + coord[3] * M[1, 3] | |
22 | - out[2] = coord[0] * M[2, 0] + coord[1] * M[2, 1] + coord[2] * M[2, 2] + coord[3] * M[2, 3] | |
23 | - out[3] = coord[0] * M[3, 0] + coord[1] * M[3, 1] + coord[2] * M[3, 2] + coord[3] * M[3, 3] | |
24 | - | |
25 | - | |
26 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
27 | -@cython.cdivision(True) | |
28 | -@cython.wraparound(False) | |
29 | -cdef image_t coord_transform(image_t[:, :, :] volume, double[:, :] M, int x, int y, int z, double sx, double sy, double sz, interp_function f_interp, image_t cval) nogil: | |
30 | - | |
31 | - cdef double coord[4] | |
32 | - coord[0] = z*sz | |
33 | - coord[1] = y*sy | |
34 | - coord[2] = x*sx | |
35 | - coord[3] = 1.0 | |
36 | - | |
37 | - cdef double _ncoord[4] | |
38 | - _ncoord[3] = 1 | |
39 | - # _ncoord[:] = [0.0, 0.0, 0.0, 1.0] | |
40 | - | |
41 | - cdef unsigned int dz, dy, dx | |
42 | - dz = volume.shape[0] | |
43 | - dy = volume.shape[1] | |
44 | - dx = volume.shape[2] | |
45 | - | |
46 | - | |
47 | - mul_mat4_vec4(M, coord, _ncoord) | |
48 | - | |
49 | - cdef double nz, ny, nx | |
50 | - nz = (_ncoord[0]/_ncoord[3])/sz | |
51 | - ny = (_ncoord[1]/_ncoord[3])/sy | |
52 | - nx = (_ncoord[2]/_ncoord[3])/sx | |
53 | - | |
54 | - cdef double v | |
55 | - | |
56 | - if 0 <= nz <= (dz-1) and 0 <= ny <= (dy-1) and 0 <= nx <= (dx-1): | |
57 | - return <image_t>f_interp(volume, nx, ny, nz) | |
58 | - # if minterpol == 0: | |
59 | - # return <image_t>nearest_neighbour_interp(volume, nx, ny, nz) | |
60 | - # elif minterpol == 1: | |
61 | - # return <image_t>interpolate(volume, nx, ny, nz) | |
62 | - # elif minterpol == 2: | |
63 | - # v = tricubicInterpolate(volume, nx, ny, nz) | |
64 | - # if (v < cval): | |
65 | - # v = cval | |
66 | - # return <image_t>v | |
67 | - # else: | |
68 | - # v = lanczos3(volume, nx, ny, nz) | |
69 | - # if (v < cval): | |
70 | - # v = cval | |
71 | - # return <image_t>v | |
72 | - else: | |
73 | - return cval | |
74 | - | |
75 | - | |
76 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
77 | -@cython.cdivision(True) | |
78 | -@cython.wraparound(False) | |
79 | -def apply_view_matrix_transform(image_t[:, :, :] volume, | |
80 | - spacing, | |
81 | - double[:, :] M, | |
82 | - unsigned int n, str orientation, | |
83 | - int minterpol, | |
84 | - image_t cval, | |
85 | - image_t[:, :, :] out): | |
86 | - | |
87 | - cdef int dz, dy, dx | |
88 | - cdef int z, y, x | |
89 | - dz = volume.shape[0] | |
90 | - dy = volume.shape[1] | |
91 | - dx = volume.shape[2] | |
92 | - | |
93 | - cdef unsigned int odz, ody, odx | |
94 | - odz = out.shape[0] | |
95 | - ody = out.shape[1] | |
96 | - odx = out.shape[2] | |
97 | - | |
98 | - cdef unsigned int count = 0 | |
99 | - | |
100 | - cdef double sx, sy, sz | |
101 | - sx = spacing[0] | |
102 | - sy = spacing[1] | |
103 | - sz = spacing[2] | |
104 | - | |
105 | - cdef interp_function f_interp | |
106 | - | |
107 | - if minterpol == 0: | |
108 | - f_interp = nearest_neighbour_interp | |
109 | - elif minterpol == 1: | |
110 | - f_interp = interpolate | |
111 | - elif minterpol == 2: | |
112 | - f_interp = tricubicInterpolate | |
113 | - else: | |
114 | - f_interp = lanczos3 | |
115 | - | |
116 | - if orientation == 'AXIAL': | |
117 | - for z in xrange(n, n+odz): | |
118 | - for y in prange(dy, nogil=True): | |
119 | - for x in xrange(dx): | |
120 | - out[count, y, x] = coord_transform(volume, M, x, y, z, sx, sy, sz, f_interp, cval) | |
121 | - count += 1 | |
122 | - | |
123 | - elif orientation == 'CORONAL': | |
124 | - for y in xrange(n, n+ody): | |
125 | - for z in prange(dz, nogil=True): | |
126 | - for x in xrange(dx): | |
127 | - out[z, count, x] = coord_transform(volume, M, x, y, z, sx, sy, sz, f_interp, cval) | |
128 | - count += 1 | |
129 | - | |
130 | - elif orientation == 'SAGITAL': | |
131 | - for x in xrange(n, n+odx): | |
132 | - for z in prange(dz, nogil=True): | |
133 | - for y in xrange(dy): | |
134 | - out[z, y, count] = coord_transform(volume, M, x, y, z, sx, sy, sz, f_interp, cval) | |
135 | - count += 1 | |
136 | - | |
137 | - | |
138 | -@cython.boundscheck(False) # turn of bounds-checking for entire function | |
139 | -@cython.cdivision(True) | |
140 | -@cython.wraparound(False) | |
141 | -def convolve_non_zero(image_t[:, :, :] volume, | |
142 | - image_t[:, :, :] kernel, | |
143 | - image_t cval): | |
144 | - cdef Py_ssize_t x, y, z, sx, sy, sz, kx, ky, kz, skx, sky, skz, i, j, k | |
145 | - cdef image_t v | |
146 | - | |
147 | - cdef image_t[:, :, :] out = np.zeros_like(volume) | |
148 | - | |
149 | - sz = volume.shape[0] | |
150 | - sy = volume.shape[1] | |
151 | - sx = volume.shape[2] | |
152 | - | |
153 | - skz = kernel.shape[0] | |
154 | - sky = kernel.shape[1] | |
155 | - skx = kernel.shape[2] | |
156 | - | |
157 | - for z in prange(sz, nogil=True): | |
158 | - for y in xrange(sy): | |
159 | - for x in xrange(sx): | |
160 | - if volume[z, y, x] != 0: | |
161 | - for k in xrange(skz): | |
162 | - kz = z - skz // 2 + k | |
163 | - for j in xrange(sky): | |
164 | - ky = y - sky // 2 + j | |
165 | - for i in xrange(skx): | |
166 | - kx = x - skx // 2 + i | |
167 | - | |
168 | - if 0 <= kz < sz and 0 <= ky < sy and 0 <= kx < sx: | |
169 | - v = volume[kz, ky, kx] | |
170 | - else: | |
171 | - v = cval | |
172 | - | |
173 | - out[z, y, x] += (v * kernel[k, j, i]) | |
174 | - return np.asarray(out) |
... | ... | @@ -0,0 +1,466 @@ |
1 | +# distutils: language = c++ | |
2 | +#cython: boundscheck=False | |
3 | +#cython: wraparound=False | |
4 | +#cython: initializedcheck=False | |
5 | +#cython: cdivision=True | |
6 | +#cython: nonecheck=False | |
7 | + | |
8 | +import sys | |
9 | +import time | |
10 | +cimport numpy as np | |
11 | + | |
12 | +from libc.math cimport sin, cos, acos, exp, sqrt, fabs, M_PI | |
13 | +from libc.stdlib cimport abs as cabs | |
14 | +from cython.operator cimport dereference as deref, preincrement as inc | |
15 | +from libcpp.map cimport map | |
16 | +from libcpp.unordered_map cimport unordered_map | |
17 | +from libcpp.set cimport set | |
18 | +from libcpp.vector cimport vector | |
19 | +from libcpp.pair cimport pair | |
20 | +from libcpp cimport bool | |
21 | +from libcpp.deque cimport deque as cdeque | |
22 | +from cython.parallel import prange | |
23 | + | |
24 | +from cy_my_types cimport vertex_t, normal_t, vertex_id_t | |
25 | + | |
26 | +import numpy as np | |
27 | +import vtk | |
28 | + | |
29 | +from vtk.util import numpy_support | |
30 | + | |
31 | +ctypedef float weight_t | |
32 | + | |
33 | +cdef struct Point: | |
34 | + vertex_t x | |
35 | + vertex_t y | |
36 | + vertex_t z | |
37 | + | |
38 | +ctypedef pair[vertex_id_t, vertex_id_t] key | |
39 | + | |
40 | + | |
41 | +cdef class Mesh: | |
42 | + cdef vertex_t[:, :] vertices | |
43 | + cdef vertex_id_t[:, :] faces | |
44 | + cdef normal_t[:, :] normals | |
45 | + | |
46 | + cdef unordered_map[int, vector[vertex_id_t]] map_vface | |
47 | + cdef unordered_map[vertex_id_t, int] border_vertices | |
48 | + | |
49 | + cdef bool _initialized | |
50 | + | |
51 | + def __cinit__(self, pd=None, other=None): | |
52 | + cdef int i | |
53 | + cdef map[key, int] edge_nfaces | |
54 | + cdef map[key, int].iterator it | |
55 | + if pd: | |
56 | + self._initialized = True | |
57 | + _vertices = numpy_support.vtk_to_numpy(pd.GetPoints().GetData()) | |
58 | + _vertices.shape = -1, 3 | |
59 | + | |
60 | + _faces = numpy_support.vtk_to_numpy(pd.GetPolys().GetData()) | |
61 | + _faces.shape = -1, 4 | |
62 | + | |
63 | + _normals = numpy_support.vtk_to_numpy(pd.GetCellData().GetArray("Normals")) | |
64 | + _normals.shape = -1, 3 | |
65 | + | |
66 | + self.vertices = _vertices | |
67 | + self.faces = _faces | |
68 | + self.normals = _normals | |
69 | + | |
70 | + for i in xrange(_faces.shape[0]): | |
71 | + self.map_vface[self.faces[i, 1]].push_back(i) | |
72 | + self.map_vface[self.faces[i, 2]].push_back(i) | |
73 | + self.map_vface[self.faces[i, 3]].push_back(i) | |
74 | + | |
75 | + edge_nfaces[key(min(self.faces[i, 1], self.faces[i, 2]), max(self.faces[i, 1], self.faces[i, 2]))] += 1 | |
76 | + edge_nfaces[key(min(self.faces[i, 2], self.faces[i, 3]), max(self.faces[i, 2], self.faces[i, 3]))] += 1 | |
77 | + edge_nfaces[key(min(self.faces[i, 1], self.faces[i, 3]), max(self.faces[i, 1], self.faces[i, 3]))] += 1 | |
78 | + | |
79 | + it = edge_nfaces.begin() | |
80 | + | |
81 | + while it != edge_nfaces.end(): | |
82 | + if deref(it).second == 1: | |
83 | + self.border_vertices[deref(it).first.first] = 1 | |
84 | + self.border_vertices[deref(it).first.second] = 1 | |
85 | + | |
86 | + inc(it) | |
87 | + | |
88 | + elif other: | |
89 | + _other = <Mesh>other | |
90 | + self._initialized = True | |
91 | + self.vertices = _other.vertices.copy() | |
92 | + self.faces = _other.faces.copy() | |
93 | + self.normals = _other.normals.copy() | |
94 | + self.map_vface = unordered_map[int, vector[vertex_id_t]](_other.map_vface) | |
95 | + self.border_vertices = unordered_map[vertex_id_t, int](_other.border_vertices) | |
96 | + else: | |
97 | + self._initialized = False | |
98 | + | |
99 | + cdef void copy_to(self, Mesh other): | |
100 | + """ | |
101 | + Copies self content to other. | |
102 | + """ | |
103 | + if self._initialized: | |
104 | + other.vertices[:] = self.vertices | |
105 | + other.faces[:] = self.faces | |
106 | + other.normals[:] = self.normals | |
107 | + other.map_vface = unordered_map[int, vector[vertex_id_t]](self.map_vface) | |
108 | + other.border_vertices = unordered_map[vertex_id_t, int](self.border_vertices) | |
109 | + else: | |
110 | + other.vertices = self.vertices.copy() | |
111 | + other.faces = self.faces.copy() | |
112 | + other.normals = self.normals.copy() | |
113 | + | |
114 | + other.map_vface = self.map_vface | |
115 | + other.border_vertices = self.border_vertices | |
116 | + | |
117 | + def to_vtk(self): | |
118 | + """ | |
119 | + Converts Mesh to vtkPolyData. | |
120 | + """ | |
121 | + vertices = np.asarray(self.vertices) | |
122 | + faces = np.asarray(self.faces) | |
123 | + normals = np.asarray(self.normals) | |
124 | + | |
125 | + points = vtk.vtkPoints() | |
126 | + points.SetData(numpy_support.numpy_to_vtk(vertices)) | |
127 | + | |
128 | + id_triangles = numpy_support.numpy_to_vtkIdTypeArray(faces) | |
129 | + triangles = vtk.vtkCellArray() | |
130 | + triangles.SetCells(faces.shape[0], id_triangles) | |
131 | + | |
132 | + pd = vtk.vtkPolyData() | |
133 | + pd.SetPoints(points) | |
134 | + pd.SetPolys(triangles) | |
135 | + | |
136 | + return pd | |
137 | + | |
138 | + cdef vector[vertex_id_t]* get_faces_by_vertex(self, int v_id) nogil: | |
139 | + """ | |
140 | + Returns the faces whose vertex `v_id' is part. | |
141 | + """ | |
142 | + return &self.map_vface[v_id] | |
143 | + | |
144 | + cdef set[vertex_id_t]* get_ring1(self, vertex_id_t v_id) nogil: | |
145 | + """ | |
146 | + Returns the ring1 of vertex `v_id' | |
147 | + """ | |
148 | + cdef vertex_id_t f_id | |
149 | + cdef set[vertex_id_t]* ring1 = new set[vertex_id_t]() | |
150 | + cdef vector[vertex_id_t].iterator it = self.map_vface[v_id].begin() | |
151 | + | |
152 | + while it != self.map_vface[v_id].end(): | |
153 | + f_id = deref(it) | |
154 | + inc(it) | |
155 | + if self.faces[f_id, 1] != v_id: | |
156 | + ring1.insert(self.faces[f_id, 1]) | |
157 | + if self.faces[f_id, 2] != v_id: | |
158 | + ring1.insert(self.faces[f_id, 2]) | |
159 | + if self.faces[f_id, 3] != v_id: | |
160 | + ring1.insert(self.faces[f_id, 3]) | |
161 | + | |
162 | + return ring1 | |
163 | + | |
164 | + cdef bool is_border(self, vertex_id_t v_id) nogil: | |
165 | + """ | |
166 | + Check if vertex `v_id' is a vertex border. | |
167 | + """ | |
168 | + return self.border_vertices.find(v_id) != self.border_vertices.end() | |
169 | + | |
170 | + cdef vector[vertex_id_t]* get_near_vertices_to_v(self, vertex_id_t v_id, float dmax) nogil: | |
171 | + """ | |
172 | + Returns all vertices with distance at most `d' to the vertex `v_id' | |
173 | + | |
174 | + Params: | |
175 | + v_id: id of the vertex | |
176 | + dmax: the maximum distance. | |
177 | + """ | |
178 | + cdef vector[vertex_id_t]* idfaces | |
179 | + cdef vector[vertex_id_t]* near_vertices = new vector[vertex_id_t]() | |
180 | + | |
181 | + cdef cdeque[vertex_id_t] to_visit | |
182 | + cdef unordered_map[vertex_id_t, bool] status_v | |
183 | + cdef unordered_map[vertex_id_t, bool] status_f | |
184 | + | |
185 | + cdef vertex_t *vip | |
186 | + cdef vertex_t *vjp | |
187 | + | |
188 | + cdef float distance | |
189 | + cdef int nf, nid, j | |
190 | + cdef vertex_id_t f_id, vj | |
191 | + | |
192 | + vip = &self.vertices[v_id, 0] | |
193 | + to_visit.push_back(v_id) | |
194 | + while(not to_visit.empty()): | |
195 | + v_id = to_visit.front() | |
196 | + to_visit.pop_front() | |
197 | + | |
198 | + status_v[v_id] = True | |
199 | + | |
200 | + idfaces = self.get_faces_by_vertex(v_id) | |
201 | + nf = idfaces.size() | |
202 | + | |
203 | + for nid in xrange(nf): | |
204 | + f_id = deref(idfaces)[nid] | |
205 | + if status_f.find(f_id) == status_f.end(): | |
206 | + status_f[f_id] = True | |
207 | + | |
208 | + for j in xrange(3): | |
209 | + vj = self.faces[f_id, j+1] | |
210 | + if status_v.find(vj) == status_v.end(): | |
211 | + status_v[vj] = True | |
212 | + vjp = &self.vertices[vj, 0] | |
213 | + distance = sqrt((vip[0] - vjp[0]) * (vip[0] - vjp[0]) \ | |
214 | + + (vip[1] - vjp[1]) * (vip[1] - vjp[1]) \ | |
215 | + + (vip[2] - vjp[2]) * (vip[2] - vjp[2])) | |
216 | + if distance <= dmax: | |
217 | + near_vertices.push_back(vj) | |
218 | + to_visit.push_back(vj) | |
219 | + | |
220 | + return near_vertices | |
221 | + | |
222 | + | |
223 | +cdef vector[weight_t]* calc_artifacts_weight(Mesh mesh, vector[vertex_id_t]& vertices_staircase, float tmax, float bmin) nogil: | |
224 | + """ | |
225 | + Calculate the artifact weight based on distance of each vertex to its | |
226 | + nearest staircase artifact vertex. | |
227 | + | |
228 | + Params: | |
229 | + mesh: Mesh | |
230 | + vertices_staircase: the identified staircase artifact vertices | |
231 | + tmax: max distance the vertex must be to its nearest artifact vertex | |
232 | + to considered to calculate the weight | |
233 | + bmin: The minimum weight. | |
234 | + """ | |
235 | + cdef int vi_id, vj_id, nnv, n_ids, i, j | |
236 | + cdef vector[vertex_id_t]* near_vertices | |
237 | + cdef weight_t value | |
238 | + cdef float d | |
239 | + n_ids = vertices_staircase.size() | |
240 | + | |
241 | + cdef vertex_t* vi | |
242 | + cdef vertex_t* vj | |
243 | + cdef size_t msize | |
244 | + | |
245 | + msize = mesh.vertices.shape[0] | |
246 | + cdef vector[weight_t]* weights = new vector[weight_t](msize) | |
247 | + weights.assign(msize, bmin) | |
248 | + | |
249 | + for i in prange(n_ids, nogil=True): | |
250 | + vi_id = vertices_staircase[i] | |
251 | + deref(weights)[vi_id] = 1.0 | |
252 | + | |
253 | + vi = &mesh.vertices[vi_id, 0] | |
254 | + near_vertices = mesh.get_near_vertices_to_v(vi_id, tmax) | |
255 | + nnv = near_vertices.size() | |
256 | + | |
257 | + for j in xrange(nnv): | |
258 | + vj_id = deref(near_vertices)[j] | |
259 | + vj = &mesh.vertices[vj_id, 0] | |
260 | + | |
261 | + d = sqrt((vi[0] - vj[0]) * (vi[0] - vj[0])\ | |
262 | + + (vi[1] - vj[1]) * (vi[1] - vj[1])\ | |
263 | + + (vi[2] - vj[2]) * (vi[2] - vj[2])) | |
264 | + value = (1.0 - d/tmax) * (1.0 - bmin) + bmin | |
265 | + | |
266 | + if value > deref(weights)[vj_id]: | |
267 | + deref(weights)[vj_id] = value | |
268 | + | |
269 | + del near_vertices | |
270 | + | |
271 | + # for i in xrange(msize): | |
272 | + # if mesh.is_border(i): | |
273 | + # deref(weights)[i] = 0.0 | |
274 | + | |
275 | + # cdef vertex_id_t v0, v1, v2 | |
276 | + # for i in xrange(mesh.faces.shape[0]): | |
277 | + # for j in xrange(1, 4): | |
278 | + # v0 = mesh.faces[i, j] | |
279 | + # vi = &mesh.vertices[v0, 0] | |
280 | + # if mesh.is_border(v0): | |
281 | + # deref(weights)[v0] = 0.0 | |
282 | + # v1 = mesh.faces[i, (j + 1) % 3 + 1] | |
283 | + # if mesh.is_border(v1): | |
284 | + # vi = &mesh.vertices[v1, 0] | |
285 | + # deref(weights)[v0] = 0.0 | |
286 | + | |
287 | + return weights | |
288 | + | |
289 | + | |
290 | +cdef inline Point calc_d(Mesh mesh, vertex_id_t v_id) nogil: | |
291 | + cdef Point D | |
292 | + cdef int nf, f_id, nid | |
293 | + cdef float n=0 | |
294 | + cdef int i | |
295 | + cdef vertex_t* vi | |
296 | + cdef vertex_t* vj | |
297 | + cdef set[vertex_id_t]* vertices | |
298 | + cdef set[vertex_id_t].iterator it | |
299 | + cdef vertex_id_t vj_id | |
300 | + | |
301 | + D.x = 0.0 | |
302 | + D.y = 0.0 | |
303 | + D.z = 0.0 | |
304 | + | |
305 | + vertices = mesh.get_ring1(v_id) | |
306 | + vi = &mesh.vertices[v_id, 0] | |
307 | + | |
308 | + if mesh.is_border(v_id): | |
309 | + it = vertices.begin() | |
310 | + while it != vertices.end(): | |
311 | + vj_id = deref(it) | |
312 | + if mesh.is_border(vj_id): | |
313 | + vj = &mesh.vertices[vj_id, 0] | |
314 | + | |
315 | + D.x = D.x + (vi[0] - vj[0]) | |
316 | + D.y = D.y + (vi[1] - vj[1]) | |
317 | + D.z = D.z + (vi[2] - vj[2]) | |
318 | + n += 1.0 | |
319 | + | |
320 | + inc(it) | |
321 | + else: | |
322 | + it = vertices.begin() | |
323 | + while it != vertices.end(): | |
324 | + vj_id = deref(it) | |
325 | + vj = &mesh.vertices[vj_id, 0] | |
326 | + | |
327 | + D.x = D.x + (vi[0] - vj[0]) | |
328 | + D.y = D.y + (vi[1] - vj[1]) | |
329 | + D.z = D.z + (vi[2] - vj[2]) | |
330 | + n += 1.0 | |
331 | + | |
332 | + inc(it) | |
333 | + | |
334 | + del vertices | |
335 | + | |
336 | + D.x = D.x / n | |
337 | + D.y = D.y / n | |
338 | + D.z = D.z / n | |
339 | + return D | |
340 | + | |
341 | +cdef vector[vertex_id_t]* find_staircase_artifacts(Mesh mesh, double[3] stack_orientation, double T) nogil: | |
342 | + """ | |
343 | + This function is used to find vertices at staircase artifacts, which are | |
344 | + those vertices whose incident faces' orientation differences are | |
345 | + greater than T. | |
346 | + | |
347 | + Params: | |
348 | + mesh: Mesh | |
349 | + stack_orientation: orientation of slice stacking | |
350 | + T: Min angle (between vertex faces and stack_orientation) to consider a | |
351 | + vertex a staircase artifact. | |
352 | + """ | |
353 | + cdef int nv, nf, f_id, v_id | |
354 | + cdef double of_z, of_y, of_x, min_z, max_z, min_y, max_y, min_x, max_x; | |
355 | + cdef vector[vertex_id_t]* f_ids | |
356 | + cdef normal_t* normal | |
357 | + | |
358 | + cdef vector[vertex_id_t]* output = new vector[vertex_id_t]() | |
359 | + cdef int i | |
360 | + | |
361 | + nv = mesh.vertices.shape[0] | |
362 | + | |
363 | + for v_id in xrange(nv): | |
364 | + max_z = -10000 | |
365 | + min_z = 10000 | |
366 | + max_y = -10000 | |
367 | + min_y = 10000 | |
368 | + max_x = -10000 | |
369 | + min_x = 10000 | |
370 | + | |
371 | + f_ids = mesh.get_faces_by_vertex(v_id) | |
372 | + nf = deref(f_ids).size() | |
373 | + | |
374 | + for i in xrange(nf): | |
375 | + f_id = deref(f_ids)[i] | |
376 | + normal = &mesh.normals[f_id, 0] | |
377 | + | |
378 | + of_z = 1 - fabs(normal[0]*stack_orientation[0] + normal[1]*stack_orientation[1] + normal[2]*stack_orientation[2]); | |
379 | + of_y = 1 - fabs(normal[0]*0 + normal[1]*1 + normal[2]*0); | |
380 | + of_x = 1 - fabs(normal[0]*1 + normal[1]*0 + normal[2]*0); | |
381 | + | |
382 | + if (of_z > max_z): | |
383 | + max_z = of_z | |
384 | + | |
385 | + if (of_z < min_z): | |
386 | + min_z = of_z | |
387 | + | |
388 | + if (of_y > max_y): | |
389 | + max_y = of_y | |
390 | + | |
391 | + if (of_y < min_y): | |
392 | + min_y = of_y | |
393 | + | |
394 | + if (of_x > max_x): | |
395 | + max_x = of_x | |
396 | + | |
397 | + if (of_x < min_x): | |
398 | + min_x = of_x | |
399 | + | |
400 | + | |
401 | + if ((fabs(max_z - min_z) >= T) or (fabs(max_y - min_y) >= T) or (fabs(max_x - min_x) >= T)): | |
402 | + output.push_back(v_id) | |
403 | + break | |
404 | + return output | |
405 | + | |
406 | + | |
407 | +cdef void taubin_smooth(Mesh mesh, vector[weight_t]& weights, float l, float m, int steps): | |
408 | + """ | |
409 | + Implementation of Taubin's smooth algorithm described in the paper "A | |
410 | + Signal Processing Approach To Fair Surface Design". His benefeat is it | |
411 | + avoids surface shrinking. | |
412 | + """ | |
413 | + cdef int s, i, nvertices | |
414 | + nvertices = mesh.vertices.shape[0] | |
415 | + cdef vector[Point] D = vector[Point](nvertices) | |
416 | + cdef vertex_t* vi | |
417 | + for s in xrange(steps): | |
418 | + for i in prange(nvertices, nogil=True): | |
419 | + D[i] = calc_d(mesh, i) | |
420 | + | |
421 | + for i in prange(nvertices, nogil=True): | |
422 | + mesh.vertices[i, 0] += weights[i]*l*D[i].x; | |
423 | + mesh.vertices[i, 1] += weights[i]*l*D[i].y; | |
424 | + mesh.vertices[i, 2] += weights[i]*l*D[i].z; | |
425 | + | |
426 | + for i in prange(nvertices, nogil=True): | |
427 | + D[i] = calc_d(mesh, i) | |
428 | + | |
429 | + for i in prange(nvertices, nogil=True): | |
430 | + mesh.vertices[i, 0] += weights[i]*m*D[i].x; | |
431 | + mesh.vertices[i, 1] += weights[i]*m*D[i].y; | |
432 | + mesh.vertices[i, 2] += weights[i]*m*D[i].z; | |
433 | + | |
434 | + | |
435 | +def ca_smoothing(Mesh mesh, double T, double tmax, double bmin, int n_iters): | |
436 | + """ | |
437 | + This is a implementation of the paper "Context-aware mesh smoothing for | |
438 | + biomedical applications". It can be used to smooth meshes generated by | |
439 | + binary images to remove its staircase artifacts and keep the fine features. | |
440 | + | |
441 | + Params: | |
442 | + mesh: Mesh | |
443 | + T: Min angle (between vertex faces and stack_orientation) to consider a | |
444 | + vertex a staircase artifact | |
445 | + tmax: max distance the vertex must be to its nearest artifact vertex | |
446 | + to considered to calculate the weight | |
447 | + bmin: The minimum weight | |
448 | + n_iters: Number of iterations. | |
449 | + """ | |
450 | + cdef double[3] stack_orientation = [0.0, 0.0, 1.0] | |
451 | + | |
452 | + t0 = time.time() | |
453 | + cdef vector[vertex_id_t]* vertices_staircase = find_staircase_artifacts(mesh, stack_orientation, T) | |
454 | + print "vertices staircase", time.time() - t0 | |
455 | + | |
456 | + t0 = time.time() | |
457 | + cdef vector[weight_t]* weights = calc_artifacts_weight(mesh, deref(vertices_staircase), tmax, bmin) | |
458 | + print "Weights", time.time() - t0 | |
459 | + | |
460 | + del vertices_staircase | |
461 | + | |
462 | + t0 = time.time() | |
463 | + taubin_smooth(mesh, deref(weights), 0.5, -0.53, n_iters) | |
464 | + print "taubin", time.time() - t0 | |
465 | + | |
466 | + del weights | ... | ... |
... | ... | @@ -0,0 +1,21 @@ |
1 | +import numpy as np | |
2 | +cimport numpy as np | |
3 | +cimport cython | |
4 | + | |
5 | +# ctypedef np.uint16_t image_t | |
6 | + | |
7 | +ctypedef fused image_t: | |
8 | + np.float64_t | |
9 | + np.int16_t | |
10 | + np.uint8_t | |
11 | + | |
12 | +ctypedef np.uint8_t mask_t | |
13 | + | |
14 | +ctypedef np.float32_t vertex_t | |
15 | +ctypedef np.float32_t normal_t | |
16 | + | |
17 | +# To compile in windows 64 | |
18 | +IF UNAME_MACHINE == 'AMD64': | |
19 | + ctypedef np.int64_t vertex_id_t | |
20 | +ELSE: | |
21 | + ctypedef np.int_t vertex_id_t | ... | ... |
... | ... | @@ -0,0 +1,274 @@ |
1 | +import numpy as np | |
2 | +cimport numpy as np | |
3 | +cimport cython | |
4 | + | |
5 | +from collections import deque | |
6 | + | |
7 | +from cython.parallel import prange | |
8 | +from libc.math cimport floor, ceil | |
9 | +from libcpp cimport bool | |
10 | +from libcpp.deque cimport deque as cdeque | |
11 | +from libcpp.vector cimport vector | |
12 | + | |
13 | +from cy_my_types cimport image_t, mask_t | |
14 | + | |
15 | +cdef struct s_coord: | |
16 | + int x | |
17 | + int y | |
18 | + int z | |
19 | + | |
20 | +ctypedef s_coord coord | |
21 | + | |
22 | + | |
23 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
24 | +@cython.wraparound(False) | |
25 | +@cython.nonecheck(False) | |
26 | +@cython.cdivision(True) | |
27 | +cdef inline void append_queue(cdeque[int]& stack, int x, int y, int z, int d, int h, int w) nogil: | |
28 | + stack.push_back(z*h*w + y*w + x) | |
29 | + | |
30 | + | |
31 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
32 | +@cython.wraparound(False) | |
33 | +@cython.nonecheck(False) | |
34 | +@cython.cdivision(True) | |
35 | +cdef inline void pop_queue(cdeque[int]& stack, int* x, int* y, int* z, int d, int h, int w) nogil: | |
36 | + cdef int i = stack.front() | |
37 | + stack.pop_front() | |
38 | + x[0] = i % w | |
39 | + y[0] = (i / w) % h | |
40 | + z[0] = i / (h * w) | |
41 | + | |
42 | + | |
43 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
44 | +def floodfill(np.ndarray[image_t, ndim=3] data, int i, int j, int k, int v, int fill, np.ndarray[mask_t, ndim=3] out): | |
45 | + | |
46 | + cdef int to_return = 0 | |
47 | + if out is None: | |
48 | + out = np.zeros_like(data) | |
49 | + to_return = 1 | |
50 | + | |
51 | + cdef int x, y, z | |
52 | + cdef int w, h, d | |
53 | + | |
54 | + d = data.shape[0] | |
55 | + h = data.shape[1] | |
56 | + w = data.shape[2] | |
57 | + | |
58 | + stack = [(i, j, k), ] | |
59 | + out[k, j, i] = fill | |
60 | + | |
61 | + while stack: | |
62 | + x, y, z = stack.pop() | |
63 | + | |
64 | + if z + 1 < d and data[z + 1, y, x] == v and out[z + 1, y, x] != fill: | |
65 | + out[z + 1, y, x] = fill | |
66 | + stack.append((x, y, z + 1)) | |
67 | + | |
68 | + if z - 1 >= 0 and data[z - 1, y, x] == v and out[z - 1, y, x] != fill: | |
69 | + out[z - 1, y, x] = fill | |
70 | + stack.append((x, y, z - 1)) | |
71 | + | |
72 | + if y + 1 < h and data[z, y + 1, x] == v and out[z, y + 1, x] != fill: | |
73 | + out[z, y + 1, x] = fill | |
74 | + stack.append((x, y + 1, z)) | |
75 | + | |
76 | + if y - 1 >= 0 and data[z, y - 1, x] == v and out[z, y - 1, x] != fill: | |
77 | + out[z, y - 1, x] = fill | |
78 | + stack.append((x, y - 1, z)) | |
79 | + | |
80 | + if x + 1 < w and data[z, y, x + 1] == v and out[z, y, x + 1] != fill: | |
81 | + out[z, y, x + 1] = fill | |
82 | + stack.append((x + 1, y, z)) | |
83 | + | |
84 | + if x - 1 >= 0 and data[z, y, x - 1] == v and out[z, y, x - 1] != fill: | |
85 | + out[z, y, x - 1] = fill | |
86 | + stack.append((x - 1, y, z)) | |
87 | + | |
88 | + if to_return: | |
89 | + return out | |
90 | + | |
91 | + | |
92 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
93 | +@cython.wraparound(False) | |
94 | +@cython.nonecheck(False) | |
95 | +def floodfill_threshold(np.ndarray[image_t, ndim=3] data, list seeds, int t0, int t1, int fill, np.ndarray[mask_t, ndim=3] strct, np.ndarray[mask_t, ndim=3] out): | |
96 | + | |
97 | + cdef int to_return = 0 | |
98 | + if out is None: | |
99 | + out = np.zeros_like(data) | |
100 | + to_return = 1 | |
101 | + | |
102 | + cdef int x, y, z | |
103 | + cdef int dx, dy, dz | |
104 | + cdef int odx, ody, odz | |
105 | + cdef int xo, yo, zo | |
106 | + cdef int i, j, k | |
107 | + cdef int offset_x, offset_y, offset_z | |
108 | + | |
109 | + dz = data.shape[0] | |
110 | + dy = data.shape[1] | |
111 | + dx = data.shape[2] | |
112 | + | |
113 | + odz = strct.shape[0] | |
114 | + ody = strct.shape[1] | |
115 | + odx = strct.shape[2] | |
116 | + | |
117 | + cdef cdeque[coord] stack | |
118 | + cdef coord c | |
119 | + | |
120 | + offset_z = odz / 2 | |
121 | + offset_y = ody / 2 | |
122 | + offset_x = odx / 2 | |
123 | + | |
124 | + for i, j, k in seeds: | |
125 | + if data[k, j, i] >= t0 and data[k, j, i] <= t1: | |
126 | + c.x = i | |
127 | + c.y = j | |
128 | + c.z = k | |
129 | + stack.push_back(c) | |
130 | + out[k, j, i] = fill | |
131 | + | |
132 | + with nogil: | |
133 | + while stack.size(): | |
134 | + c = stack.back() | |
135 | + stack.pop_back() | |
136 | + | |
137 | + x = c.x | |
138 | + y = c.y | |
139 | + z = c.z | |
140 | + | |
141 | + out[z, y, x] = fill | |
142 | + | |
143 | + for k in xrange(odz): | |
144 | + zo = z + k - offset_z | |
145 | + for j in xrange(ody): | |
146 | + yo = y + j - offset_y | |
147 | + for i in xrange(odx): | |
148 | + if strct[k, j, i]: | |
149 | + xo = x + i - offset_x | |
150 | + if 0 <= xo < dx and 0 <= yo < dy and 0 <= zo < dz and out[zo, yo, xo] != fill and t0 <= data[zo, yo, xo] <= t1: | |
151 | + out[zo, yo, xo] = fill | |
152 | + c.x = xo | |
153 | + c.y = yo | |
154 | + c.z = zo | |
155 | + stack.push_back(c) | |
156 | + | |
157 | + if to_return: | |
158 | + return out | |
159 | + | |
160 | + | |
161 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
162 | +@cython.wraparound(False) | |
163 | +@cython.nonecheck(False) | |
164 | +def floodfill_auto_threshold(np.ndarray[image_t, ndim=3] data, list seeds, float p, int fill, np.ndarray[mask_t, ndim=3] out): | |
165 | + | |
166 | + cdef int to_return = 0 | |
167 | + if out is None: | |
168 | + out = np.zeros_like(data) | |
169 | + to_return = 1 | |
170 | + | |
171 | + cdef cdeque[int] stack | |
172 | + cdef int x, y, z | |
173 | + cdef int w, h, d | |
174 | + cdef int xo, yo, zo | |
175 | + cdef int t0, t1 | |
176 | + | |
177 | + cdef int i, j, k | |
178 | + | |
179 | + d = data.shape[0] | |
180 | + h = data.shape[1] | |
181 | + w = data.shape[2] | |
182 | + | |
183 | + | |
184 | + # stack = deque() | |
185 | + | |
186 | + x = 0 | |
187 | + y = 0 | |
188 | + z = 0 | |
189 | + | |
190 | + | |
191 | + for i, j, k in seeds: | |
192 | + append_queue(stack, i, j, k, d, h, w) | |
193 | + out[k, j, i] = fill | |
194 | + print i, j, k, d, h, w | |
195 | + | |
196 | + with nogil: | |
197 | + while stack.size(): | |
198 | + pop_queue(stack, &x, &y, &z, d, h, w) | |
199 | + | |
200 | + # print x, y, z, d, h, w | |
201 | + | |
202 | + xo = x | |
203 | + yo = y | |
204 | + zo = z | |
205 | + | |
206 | + t0 = <int>ceil(data[z, y, x] * (1 - p)) | |
207 | + t1 = <int>floor(data[z, y, x] * (1 + p)) | |
208 | + | |
209 | + if z + 1 < d and data[z + 1, y, x] >= t0 and data[z + 1, y, x] <= t1 and out[zo + 1, yo, xo] != fill: | |
210 | + out[zo + 1, yo, xo] = fill | |
211 | + append_queue(stack, x, y, z+1, d, h, w) | |
212 | + | |
213 | + if z - 1 >= 0 and data[z - 1, y, x] >= t0 and data[z - 1, y, x] <= t1 and out[zo - 1, yo, xo] != fill: | |
214 | + out[zo - 1, yo, xo] = fill | |
215 | + append_queue(stack, x, y, z-1, d, h, w) | |
216 | + | |
217 | + if y + 1 < h and data[z, y + 1, x] >= t0 and data[z, y + 1, x] <= t1 and out[zo, yo + 1, xo] != fill: | |
218 | + out[zo, yo + 1, xo] = fill | |
219 | + append_queue(stack, x, y+1, z, d, h, w) | |
220 | + | |
221 | + if y - 1 >= 0 and data[z, y - 1, x] >= t0 and data[z, y - 1, x] <= t1 and out[zo, yo - 1, xo] != fill: | |
222 | + out[zo, yo - 1, xo] = fill | |
223 | + append_queue(stack, x, y-1, z, d, h, w) | |
224 | + | |
225 | + if x + 1 < w and data[z, y, x + 1] >= t0 and data[z, y, x + 1] <= t1 and out[zo, yo, xo + 1] != fill: | |
226 | + out[zo, yo, xo + 1] = fill | |
227 | + append_queue(stack, x+1, y, z, d, h, w) | |
228 | + | |
229 | + if x - 1 >= 0 and data[z, y, x - 1] >= t0 and data[z, y, x - 1] <= t1 and out[zo, yo, xo - 1] != fill: | |
230 | + out[zo, yo, xo - 1] = fill | |
231 | + append_queue(stack, x-1, y, z, d, h, w) | |
232 | + | |
233 | + if to_return: | |
234 | + return out | |
235 | + | |
236 | + | |
237 | +@cython.boundscheck(False) | |
238 | +@cython.wraparound(False) | |
239 | +@cython.nonecheck(False) | |
240 | +def fill_holes_automatically(np.ndarray[mask_t, ndim=3] mask, np.ndarray[np.uint16_t, ndim=3] labels, unsigned int nlabels, unsigned int max_size): | |
241 | + """ | |
242 | + Fill mask holes automatically. The hole must <= max_size. Return True if any hole were filled. | |
243 | + """ | |
244 | + cdef np.ndarray[np.uint32_t, ndim=1] sizes = np.zeros(shape=(nlabels + 1), dtype=np.uint32) | |
245 | + cdef int x, y, z | |
246 | + cdef int dx, dy, dz | |
247 | + cdef int i | |
248 | + | |
249 | + cdef bool modified = False | |
250 | + | |
251 | + dz = mask.shape[0] | |
252 | + dy = mask.shape[1] | |
253 | + dx = mask.shape[2] | |
254 | + | |
255 | + for z in xrange(dz): | |
256 | + for y in xrange(dy): | |
257 | + for x in xrange(dx): | |
258 | + sizes[labels[z, y, x]] += 1 | |
259 | + | |
260 | + #Checking if any hole will be filled | |
261 | + for i in xrange(nlabels + 1): | |
262 | + if sizes[i] <= max_size: | |
263 | + modified = True | |
264 | + | |
265 | + if not modified: | |
266 | + return 0 | |
267 | + | |
268 | + for z in prange(dz, nogil=True): | |
269 | + for y in xrange(dy): | |
270 | + for x in xrange(dx): | |
271 | + if sizes[labels[z, y, x]] <= max_size: | |
272 | + mask[z, y, x] = 254 | |
273 | + | |
274 | + return modified | ... | ... |
... | ... | @@ -0,0 +1,8 @@ |
1 | +from .cy_my_types cimport image_t | |
2 | + | |
3 | +cdef double interpolate(image_t[:, :, :], double, double, double) nogil | |
4 | +cdef double tricub_interpolate(image_t[:, :, :], double, double, double) nogil | |
5 | +cdef double tricubicInterpolate (image_t[:, :, :], double, double, double) nogil | |
6 | +cdef double lanczos3 (image_t[:, :, :], double, double, double) nogil | |
7 | + | |
8 | +cdef double nearest_neighbour_interp(image_t[:, :, :], double, double, double) nogil | ... | ... |
... | ... | @@ -0,0 +1,392 @@ |
1 | +# from interpolation cimport interpolate | |
2 | + | |
3 | +import numpy as np | |
4 | +cimport numpy as np | |
5 | +cimport cython | |
6 | + | |
7 | +from libc.math cimport floor, ceil, sqrt, fabs, sin, M_PI | |
8 | +from cython.parallel import prange | |
9 | + | |
10 | +DEF LANCZOS_A = 4 | |
11 | +DEF SIZE_LANCZOS_TMP = LANCZOS_A * 2 - 1 | |
12 | + | |
13 | +cdef double[64][64] temp = [ | |
14 | + [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
15 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
16 | + [-3, 3, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
17 | + [ 2, -2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
18 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
19 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
20 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
21 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
22 | + [-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
23 | + [ 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
24 | + [ 9, -9,-9, 9, 0, 0, 0, 0, 6, 3,-6,-3, 0, 0, 0, 0, 6,-6, 3,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
25 | + [-6, 6, 6,-6, 0, 0, 0, 0,-3,-3, 3, 3, 0, 0, 0, 0,-4, 4,-2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-2,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
26 | + [ 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
27 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
28 | + [-6, 6, 6,-6, 0, 0, 0, 0,-4,-2, 4, 2, 0, 0, 0, 0,-3, 3,-3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-1,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
29 | + [ 4, -4,-4, 4, 0, 0, 0, 0, 2, 2,-2,-2, 0, 0, 0, 0, 2,-2, 2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
30 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
31 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
32 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
33 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
34 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
35 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], | |
36 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0], | |
37 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0], | |
38 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
39 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0, 0, 0, 0, 0], | |
40 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,-9,-9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3,-6,-3, 0, 0, 0, 0, 6,-6, 3,-3, 0, 0, 0, 0, 4, 2, 2, 1, 0, 0, 0, 0], | |
41 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3,-3, 3, 3, 0, 0, 0, 0,-4, 4,-2, 2, 0, 0, 0, 0,-2,-2,-1,-1, 0, 0, 0, 0], | |
42 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
43 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0], | |
44 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4,-2, 4, 2, 0, 0, 0, 0,-3, 3,-3, 3, 0, 0, 0, 0,-2,-1,-2,-1, 0, 0, 0, 0], | |
45 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,-4,-4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,-2,-2, 0, 0, 0, 0, 2,-2, 2,-2, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0], | |
46 | + [-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
47 | + [ 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
48 | + [ 9, -9, 0, 0,-9, 9, 0, 0, 6, 3, 0, 0,-6,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,-6, 0, 0, 3,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
49 | + [-6, 6, 0, 0, 6,-6, 0, 0,-3,-3, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4, 4, 0, 0,-2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-2, 0, 0,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
50 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
51 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0, 0, 0,-1, 0, 0, 0], | |
52 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,-9, 0, 0,-9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 0, 0,-6,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,-6, 0, 0, 3,-3, 0, 0, 4, 2, 0, 0, 2, 1, 0, 0], | |
53 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 0, 0, 6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3,-3, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4, 4, 0, 0,-2, 2, 0, 0,-2,-2, 0, 0,-1,-1, 0, 0], | |
54 | + [ 9, 0,-9, 0,-9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 0,-6, 0,-3, 0, 6, 0,-6, 0, 3, 0,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
55 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,-9, 0,-9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 3, 0,-6, 0,-3, 0, 6, 0,-6, 0, 3, 0,-3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 2, 0, 2, 0, 1, 0], | |
56 | + [-27, 27,27,-27,27,-27,-27,27,-18,-9,18, 9,18, 9,-18,-9,-18,18,-9, 9,18,-18, 9,-9,-18,18,18,-18,-9, 9, 9,-9,-12,-6,-6,-3,12, 6, 6, 3,-12,-6,12, 6,-6,-3, 6, 3,-12,12,-6, 6,-6, 6,-3, 3,-8,-4,-4,-2,-4,-2,-2,-1], | |
57 | + [18, -18,-18,18,-18,18,18,-18, 9, 9,-9,-9,-9,-9, 9, 9,12,-12, 6,-6,-12,12,-6, 6,12,-12,-12,12, 6,-6,-6, 6, 6, 6, 3, 3,-6,-6,-3,-3, 6, 6,-6,-6, 3, 3,-3,-3, 8,-8, 4,-4, 4,-4, 2,-2, 4, 4, 2, 2, 2, 2, 1, 1], | |
58 | + [-6, 0, 6, 0, 6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0,-3, 0, 3, 0, 3, 0,-4, 0, 4, 0,-2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-2, 0,-1, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
59 | + [ 0, 0, 0, 0, 0, 0, 0, 0,-6, 0, 6, 0, 6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 0,-3, 0, 3, 0, 3, 0,-4, 0, 4, 0,-2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-2, 0,-1, 0,-1, 0], | |
60 | + [18, -18,-18,18,-18,18,18,-18,12, 6,-12,-6,-12,-6,12, 6, 9,-9, 9,-9,-9, 9,-9, 9,12,-12,-12,12, 6,-6,-6, 6, 6, 3, 6, 3,-6,-3,-6,-3, 8, 4,-8,-4, 4, 2,-4,-2, 6,-6, 6,-6, 3,-3, 3,-3, 4, 2, 4, 2, 2, 1, 2, 1], | |
61 | + [-12, 12,12,-12,12,-12,-12,12,-6,-6, 6, 6, 6, 6,-6,-6,-6, 6,-6, 6, 6,-6, 6,-6,-8, 8, 8,-8,-4, 4, 4,-4,-3,-3,-3,-3, 3, 3, 3, 3,-4,-4, 4, 4,-2,-2, 2, 2,-4, 4,-4, 4,-2, 2,-2, 2,-2,-2,-2,-2,-1,-1,-1,-1], | |
62 | + [ 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
63 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
64 | + [-6, 6, 0, 0, 6,-6, 0, 0,-4,-2, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0,-3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2,-1, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
65 | + [ 4, -4, 0, 0,-4, 4, 0, 0, 2, 2, 0, 0,-2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
66 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
67 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0], | |
68 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-6, 6, 0, 0, 6,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4,-2, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0,-3, 3, 0, 0,-2,-1, 0, 0,-2,-1, 0, 0], | |
69 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4,-4, 0, 0,-4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0,-2,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 2,-2, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0], | |
70 | + [-6, 0, 6, 0, 6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4, 0,-2, 0, 4, 0, 2, 0,-3, 0, 3, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0,-2, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
71 | + [ 0, 0, 0, 0, 0, 0, 0, 0,-6, 0, 6, 0, 6, 0,-6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-4, 0,-2, 0, 4, 0, 2, 0,-3, 0, 3, 0,-3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,-2, 0,-1, 0,-2, 0,-1, 0], | |
72 | + [18, -18,-18,18,-18,18,18,-18,12, 6,-12,-6,-12,-6,12, 6,12,-12, 6,-6,-12,12,-6, 6, 9,-9,-9, 9, 9,-9,-9, 9, 8, 4, 4, 2,-8,-4,-4,-2, 6, 3,-6,-3, 6, 3,-6,-3, 6,-6, 3,-3, 6,-6, 3,-3, 4, 2, 2, 1, 4, 2, 2, 1], | |
73 | + [-12, 12,12,-12,12,-12,-12,12,-6,-6, 6, 6, 6, 6,-6,-6,-8, 8,-4, 4, 8,-8, 4,-4,-6, 6, 6,-6,-6, 6, 6,-6,-4,-4,-2,-2, 4, 4, 2, 2,-3,-3, 3, 3,-3,-3, 3, 3,-4, 4,-2, 2,-4, 4,-2, 2,-2,-2,-1,-1,-2,-2,-1,-1], | |
74 | + [ 4, 0,-4, 0,-4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0,-2, 0,-2, 0, 2, 0,-2, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], | |
75 | + [ 0, 0, 0, 0, 0, 0, 0, 0, 4, 0,-4, 0,-4, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0,-2, 0,-2, 0, 2, 0,-2, 0, 2, 0,-2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0], | |
76 | + [-12, 12,12,-12,12,-12,-12,12,-8,-4, 8, 4, 8, 4,-8,-4,-6, 6,-6, 6, 6,-6, 6,-6,-6, 6, 6,-6,-6, 6, 6,-6,-4,-2,-4,-2, 4, 2, 4, 2,-4,-2, 4, 2,-4,-2, 4, 2,-3, 3,-3, 3,-3, 3,-3, 3,-2,-1,-2,-1,-2,-1,-2,-1], | |
77 | + [ 8, -8,-8, 8,-8, 8, 8,-8, 4, 4,-4,-4,-4,-4, 4, 4, 4,-4, 4,-4,-4, 4,-4, 4, 4,-4,-4, 4, 4,-4,-4, 4, 2, 2, 2, 2,-2,-2,-2,-2, 2, 2,-2,-2, 2, 2,-2,-2, 2,-2, 2,-2, 2,-2, 2,-2, 1, 1, 1, 1, 1, 1, 1, 1] | |
78 | +] | |
79 | + | |
80 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
81 | +@cython.cdivision(True) | |
82 | +@cython.wraparound(False) | |
83 | +cdef double nearest_neighbour_interp(image_t[:, :, :] V, double x, double y, double z) nogil: | |
84 | + return V[<int>(z), <int>(y), <int>(x)] | |
85 | + | |
86 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
87 | +@cython.cdivision(True) | |
88 | +@cython.wraparound(False) | |
89 | +cdef double interpolate(image_t[:, :, :] V, double x, double y, double z) nogil: | |
90 | + cdef double xd, yd, zd | |
91 | + cdef double c00, c10, c01, c11 | |
92 | + cdef double c0, c1 | |
93 | + cdef double c | |
94 | + | |
95 | + cdef int x0 = <int>floor(x) | |
96 | + cdef int x1 = x0 + 1 | |
97 | + | |
98 | + cdef int y0 = <int>floor(y) | |
99 | + cdef int y1 = y0 + 1 | |
100 | + | |
101 | + cdef int z0 = <int>floor(z) | |
102 | + cdef int z1 = z0 + 1 | |
103 | + | |
104 | + if x0 == x1: | |
105 | + xd = 1.0 | |
106 | + else: | |
107 | + xd = (x - x0) / (x1 - x0) | |
108 | + | |
109 | + if y0 == y1: | |
110 | + yd = 1.0 | |
111 | + else: | |
112 | + yd = (y - y0) / (y1 - y0) | |
113 | + | |
114 | + if z0 == z1: | |
115 | + zd = 1.0 | |
116 | + else: | |
117 | + zd = (z - z0) / (z1 - z0) | |
118 | + | |
119 | + c00 = _G(V, x0, y0, z0)*(1 - xd) + _G(V, x1, y0, z0)*xd | |
120 | + c10 = _G(V, x0, y1, z0)*(1 - xd) + _G(V, x1, y1, z0)*xd | |
121 | + c01 = _G(V, x0, y0, z1)*(1 - xd) + _G(V, x1, y0, z1)*xd | |
122 | + c11 = _G(V, x0, y1, z1)*(1 - xd) + _G(V, x1, y1, z1)*xd | |
123 | + | |
124 | + c0 = c00*(1 - yd) + c10*yd | |
125 | + c1 = c01*(1 - yd) + c11*yd | |
126 | + | |
127 | + c = c0*(1 - zd) + c1*zd | |
128 | + | |
129 | + return c | |
130 | + | |
131 | + | |
132 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
133 | +@cython.cdivision(True) | |
134 | +@cython.wraparound(False) | |
135 | +cdef inline double lanczos3_L(double x, int a) nogil: | |
136 | + if x == 0: | |
137 | + return 1.0 | |
138 | + elif -a <= x < a: | |
139 | + return (a * sin(M_PI * x) * sin(M_PI * (x / a)))/(M_PI**2 * x**2) | |
140 | + else: | |
141 | + return 0.0 | |
142 | + | |
143 | + | |
144 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
145 | +@cython.cdivision(True) | |
146 | +@cython.wraparound(False) | |
147 | +cdef double lanczos3(image_t[:, :, :] V, double x, double y, double z) nogil: | |
148 | + cdef int a = LANCZOS_A | |
149 | + | |
150 | + cdef int xd = <int>floor(x) | |
151 | + cdef int yd = <int>floor(y) | |
152 | + cdef int zd = <int>floor(z) | |
153 | + | |
154 | + cdef int xi = xd - a + 1 | |
155 | + cdef int xf = xd + a | |
156 | + | |
157 | + cdef int yi = yd - a + 1 | |
158 | + cdef int yf = yd + a | |
159 | + | |
160 | + cdef int zi = zd - a + 1 | |
161 | + cdef int zf = zd + a | |
162 | + | |
163 | + cdef double lx = 0.0 | |
164 | + cdef double ly = 0.0 | |
165 | + cdef double lz = 0.0 | |
166 | + | |
167 | + cdef double[SIZE_LANCZOS_TMP][SIZE_LANCZOS_TMP] temp_x | |
168 | + cdef double[SIZE_LANCZOS_TMP] temp_y | |
169 | + | |
170 | + cdef int i, j, k | |
171 | + cdef int m, n, o | |
172 | + | |
173 | + m = 0 | |
174 | + for k in xrange(zi, zf): | |
175 | + n = 0 | |
176 | + for j in xrange(yi, yf): | |
177 | + lx = 0 | |
178 | + for i in xrange(xi, xf): | |
179 | + lx += _G(V, i, j, k) * lanczos3_L(x - i, a) | |
180 | + temp_x[m][n] = lx | |
181 | + n += 1 | |
182 | + m += 1 | |
183 | + | |
184 | + m = 0 | |
185 | + for k in xrange(zi, zf): | |
186 | + n = 0 | |
187 | + ly = 0 | |
188 | + for j in xrange(yi, yf): | |
189 | + ly += temp_x[m][n] * lanczos3_L(y - j, a) | |
190 | + n += 1 | |
191 | + temp_y[m] = ly | |
192 | + m += 1 | |
193 | + | |
194 | + m = 0 | |
195 | + for k in xrange(zi, zf): | |
196 | + lz += temp_y[m] * lanczos3_L(z - k, a) | |
197 | + m += 1 | |
198 | + | |
199 | + return lz | |
200 | + | |
201 | + | |
202 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
203 | +@cython.cdivision(True) | |
204 | +@cython.wraparound(False) | |
205 | +cdef image_t _G(image_t[:, :, :] V, int x, int y, int z) nogil: | |
206 | + cdef int dz, dy, dx | |
207 | + dz = V.shape[0] - 1 | |
208 | + dy = V.shape[1] - 1 | |
209 | + dx = V.shape[2] - 1 | |
210 | + | |
211 | + if x < 0: | |
212 | + x = dx + x + 1 | |
213 | + elif x > dx: | |
214 | + x = x - dx - 1 | |
215 | + | |
216 | + if y < 0: | |
217 | + y = dy + y + 1 | |
218 | + elif y > dy: | |
219 | + y = y - dy - 1 | |
220 | + | |
221 | + if z < 0: | |
222 | + z = dz + z + 1 | |
223 | + elif z > dz: | |
224 | + z = z - dz - 1 | |
225 | + | |
226 | + return V[z, y, x] | |
227 | + | |
228 | + | |
229 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
230 | +@cython.cdivision(True) | |
231 | +@cython.wraparound(False) | |
232 | +cdef void calc_coef_tricub(image_t[:, :, :] V, double x, double y, double z, double [64] coef) nogil: | |
233 | + cdef int xi = <int>floor(x) | |
234 | + cdef int yi = <int>floor(y) | |
235 | + cdef int zi = <int>floor(z) | |
236 | + | |
237 | + cdef double[64] _x | |
238 | + | |
239 | + cdef int i, j | |
240 | + | |
241 | + _x[0] = _G(V, xi, yi, zi) | |
242 | + _x[1] = _G(V, xi + 1, yi, zi) | |
243 | + _x[2] = _G(V, xi, yi + 1, zi) | |
244 | + _x[3] = _G(V, xi + 1, yi + 1, zi) | |
245 | + _x[4] = _G(V, xi, yi, zi + 1) | |
246 | + _x[5] = _G(V, xi + 1, yi, zi + 1) | |
247 | + _x[6] = _G(V, xi, yi + 1, zi + 1) | |
248 | + _x[7] = _G(V, xi + 1, yi + 1, zi + 1) | |
249 | + | |
250 | + _x[8] = 0.5*(_G(V, xi+1,yi,zi) - _G(V, xi-1, yi, zi)) | |
251 | + _x[9] = 0.5*(_G(V, xi+2,yi,zi) - _G(V, xi, yi, zi)) | |
252 | + _x[10] = 0.5*(_G(V, xi+1, yi+1,zi) - _G(V, xi-1, yi+1, zi)) | |
253 | + _x[11] = 0.5*(_G(V, xi+2, yi+1,zi) - _G(V, xi, yi+1, zi)) | |
254 | + _x[12] = 0.5*(_G(V, xi+1, yi,zi+1) - _G(V, xi-1, yi, zi+1)) | |
255 | + _x[13] = 0.5*(_G(V, xi+2, yi,zi+1) - _G(V, xi, yi, zi+1)) | |
256 | + _x[14] = 0.5*(_G(V, xi+1, yi+1,zi+1) - _G(V, xi-1, yi+1, zi+1)) | |
257 | + _x[15] = 0.5*(_G(V, xi+2, yi+1,zi+1) - _G(V, xi, yi+1, zi+1)) | |
258 | + _x[16] = 0.5*(_G(V, xi, yi+1,zi) - _G(V, xi, yi-1, zi)) | |
259 | + _x[17] = 0.5*(_G(V, xi+1, yi+1,zi) - _G(V, xi+1, yi-1, zi)) | |
260 | + _x[18] = 0.5*(_G(V, xi, yi+2,zi) - _G(V, xi, yi, zi)) | |
261 | + _x[19] = 0.5*(_G(V, xi+1, yi+2,zi) - _G(V, xi+1, yi, zi)) | |
262 | + _x[20] = 0.5*(_G(V, xi, yi+1,zi+1) - _G(V, xi, yi-1, zi+1)) | |
263 | + _x[21] = 0.5*(_G(V, xi+1, yi+1,zi+1) - _G(V, xi+1, yi-1, zi+1)) | |
264 | + _x[22] = 0.5*(_G(V, xi, yi+2,zi+1) - _G(V, xi, yi, zi+1)) | |
265 | + _x[23] = 0.5*(_G(V, xi+1, yi+2,zi+1) - _G(V, xi+1, yi, zi+1)) | |
266 | + _x[24] = 0.5*(_G(V, xi, yi,zi+1) - _G(V, xi, yi, zi-1)) | |
267 | + _x[25] = 0.5*(_G(V, xi+1, yi,zi+1) - _G(V, xi+1, yi, zi-1)) | |
268 | + _x[26] = 0.5*(_G(V, xi, yi+1,zi+1) - _G(V, xi, yi+1, zi-1)) | |
269 | + _x[27] = 0.5*(_G(V, xi+1, yi+1,zi+1) - _G(V, xi+1, yi+1, zi-1)) | |
270 | + _x[28] = 0.5*(_G(V, xi, yi,zi+2) - _G(V, xi, yi, zi)) | |
271 | + _x[29] = 0.5*(_G(V, xi+1, yi,zi+2) - _G(V, xi+1, yi, zi)) | |
272 | + _x[30] = 0.5*(_G(V, xi, yi+1,zi+2) - _G(V, xi, yi+1, zi)) | |
273 | + _x[31] = 0.5*(_G(V, xi+1, yi+1,zi+2) - _G(V, xi+1, yi+1, zi)) | |
274 | + | |
275 | + _x [32] = 0.25*(_G(V, xi+1, yi+1, zi) - _G(V, xi-1, yi+1, zi) - _G(V, xi+1, yi-1, zi) + _G(V, xi-1, yi-1, zi)) | |
276 | + _x [33] = 0.25*(_G(V, xi+2, yi+1, zi) - _G(V, xi, yi+1, zi) - _G(V, xi+2, yi-1, zi) + _G(V, xi, yi-1, zi)) | |
277 | + _x [34] = 0.25*(_G(V, xi+1, yi+2, zi) - _G(V, xi-1, yi+2, zi) - _G(V, xi+1, yi, zi) + _G(V, xi-1, yi, zi)) | |
278 | + _x [35] = 0.25*(_G(V, xi+2, yi+2, zi) - _G(V, xi, yi+2, zi) - _G(V, xi+2, yi, zi) + _G(V, xi, yi, zi)) | |
279 | + _x [36] = 0.25*(_G(V, xi+1, yi+1, zi+1) - _G(V, xi-1, yi+1, zi+1) - _G(V, xi+1, yi-1, zi+1) + _G(V, xi-1, yi-1, zi+1)) | |
280 | + _x [37] = 0.25*(_G(V, xi+2, yi+1, zi+1) - _G(V, xi, yi+1, zi+1) - _G(V, xi+2, yi-1, zi+1) + _G(V, xi, yi-1, zi+1)) | |
281 | + _x [38] = 0.25*(_G(V, xi+1, yi+2, zi+1) - _G(V, xi-1, yi+2, zi+1) - _G(V, xi+1, yi, zi+1) + _G(V, xi-1, yi, zi+1)) | |
282 | + _x [39] = 0.25*(_G(V, xi+2, yi+2, zi+1) - _G(V, xi, yi+2, zi+1) - _G(V, xi+2, yi, zi+1) + _G(V, xi, yi, zi+1)) | |
283 | + _x [40] = 0.25*(_G(V, xi+1, yi, zi+1) - _G(V, xi-1, yi, zi+1) - _G(V, xi+1, yi, zi-1) + _G(V, xi-1, yi, zi-1)) | |
284 | + _x [41] = 0.25*(_G(V, xi+2, yi, zi+1) - _G(V, xi, yi, zi+1) - _G(V, xi+2, yi, zi-1) + _G(V, xi, yi, zi-1)) | |
285 | + _x [42] = 0.25*(_G(V, xi+1, yi+1, zi+1) - _G(V, xi-1, yi+1, zi+1) - _G(V, xi+1, yi+1, zi-1) + _G(V, xi-1, yi+1, zi-1)) | |
286 | + _x [43] = 0.25*(_G(V, xi+2, yi+1, zi+1) - _G(V, xi, yi+1, zi+1) - _G(V, xi+2, yi+1, zi-1) + _G(V, xi, yi+1, zi-1)) | |
287 | + _x [44] = 0.25*(_G(V, xi+1, yi, zi+2) - _G(V, xi-1, yi, zi+2) - _G(V, xi+1, yi, zi) + _G(V, xi-1, yi, zi)) | |
288 | + _x [45] = 0.25*(_G(V, xi+2, yi, zi+2) - _G(V, xi, yi, zi+2) - _G(V, xi+2, yi, zi) + _G(V, xi, yi, zi)) | |
289 | + _x [46] = 0.25*(_G(V, xi+1, yi+1, zi+2) - _G(V, xi-1, yi+1, zi+2) - _G(V, xi+1, yi+1, zi) + _G(V, xi-1, yi+1, zi)) | |
290 | + _x [47] = 0.25*(_G(V, xi+2, yi+1, zi+2) - _G(V, xi, yi+1, zi+2) - _G(V, xi+2, yi+1, zi) + _G(V, xi, yi+1, zi)) | |
291 | + _x [48] = 0.25*(_G(V, xi, yi+1, zi+1) - _G(V, xi, yi-1, zi+1) - _G(V, xi, yi+1, zi-1) + _G(V, xi, yi-1, zi-1)) | |
292 | + _x [49] = 0.25*(_G(V, xi+1, yi+1, zi+1) - _G(V, xi+1, yi-1, zi+1) - _G(V, xi+1, yi+1, zi-1) + _G(V, xi+1, yi-1, zi-1)) | |
293 | + _x [50] = 0.25*(_G(V, xi, yi+2, zi+1) - _G(V, xi, yi, zi+1) - _G(V, xi, yi+2, zi-1) + _G(V, xi, yi, zi-1)) | |
294 | + _x [51] = 0.25*(_G(V, xi+1, yi+2, zi+1) - _G(V, xi+1, yi, zi+1) - _G(V, xi+1, yi+2, zi-1) + _G(V, xi+1, yi, zi-1)) | |
295 | + _x [52] = 0.25*(_G(V, xi, yi+1, zi+2) - _G(V, xi, yi-1, zi+2) - _G(V, xi, yi+1, zi) + _G(V, xi, yi-1, zi)) | |
296 | + _x [53] = 0.25*(_G(V, xi+1, yi+1, zi+2) - _G(V, xi+1, yi-1, zi+2) - _G(V, xi+1, yi+1, zi) + _G(V, xi+1, yi-1, zi)) | |
297 | + _x [54] = 0.25*(_G(V, xi, yi+2, zi+2) - _G(V, xi, yi, zi+2) - _G(V, xi, yi+2, zi) + _G(V, xi, yi, zi)) | |
298 | + _x [55] = 0.25*(_G(V, xi+1, yi+2, zi+2) - _G(V, xi+1, yi, zi+2) - _G(V, xi+1, yi+2, zi) + _G(V, xi+1, yi, zi)) | |
299 | + | |
300 | + _x[56] = 0.125*(_G(V, xi+1, yi+1, zi+1) - _G(V, xi-1, yi+1, zi+1) - _G(V, xi+1, yi-1, zi+1) + _G(V, xi-1, yi-1, zi+1) - _G(V, xi+1, yi+1, zi-1) + _G(V, xi-1,yi+1,zi-1)+_G(V, xi+1,yi-1,zi-1)-_G(V, xi-1,yi-1,zi-1)) | |
301 | + _x[57] = 0.125*(_G(V, xi+2, yi+1, zi+1) - _G(V, xi, yi+1, zi+1) - _G(V, xi+2, yi-1, zi+1) + _G(V, xi, yi-1, zi+1) - _G(V, xi+2, yi+1, zi-1) + _G(V, xi,yi+1,zi-1)+_G(V, xi+2,yi-1,zi-1)-_G(V, xi,yi-1,zi-1)) | |
302 | + _x[58] = 0.125*(_G(V, xi+1, yi+2, zi+1) - _G(V, xi-1, yi+2, zi+1) - _G(V, xi+1, yi, zi+1) + _G(V, xi-1, yi, zi+1) - _G(V, xi+1, yi+2, zi-1) + _G(V, xi-1,yi+2,zi-1)+_G(V, xi+1,yi,zi-1)-_G(V, xi-1,yi,zi-1)) | |
303 | + _x[59] = 0.125*(_G(V, xi+2, yi+2, zi+1) - _G(V, xi, yi+2, zi+1) - _G(V, xi+2, yi, zi+1) + _G(V, xi, yi, zi+1) - _G(V, xi+2, yi+2, zi-1) + _G(V, xi,yi+2,zi-1)+_G(V, xi+2,yi,zi-1)-_G(V, xi,yi,zi-1)) | |
304 | + _x[60] = 0.125*(_G(V, xi+1, yi+1, zi+2) - _G(V, xi-1, yi+1, zi+2) - _G(V, xi+1, yi-1, zi+2) + _G(V, xi-1, yi-1, zi+2) - _G(V, xi+1, yi+1, zi) + _G(V, xi-1,yi+1,zi)+_G(V, xi+1,yi-1,zi)-_G(V, xi-1,yi-1,zi)) | |
305 | + _x[61] = 0.125*(_G(V, xi+2, yi+1, zi+2) - _G(V, xi, yi+1, zi+2) - _G(V, xi+2, yi-1, zi+2) + _G(V, xi, yi-1, zi+2) - _G(V, xi+2, yi+1, zi) + _G(V, xi,yi+1,zi)+_G(V, xi+2,yi-1,zi)-_G(V, xi,yi-1,zi)) | |
306 | + _x[62] = 0.125*(_G(V, xi+1, yi+2, zi+2) - _G(V, xi-1, yi+2, zi+2) - _G(V, xi+1, yi, zi+2) + _G(V, xi-1, yi, zi+2) - _G(V, xi+1, yi+2, zi) + _G(V, xi-1,yi+2,zi)+_G(V, xi+1,yi,zi)-_G(V, xi-1,yi,zi)) | |
307 | + _x[63] = 0.125*(_G(V, xi+2, yi+2, zi+2) - _G(V, xi, yi+2, zi+2) - _G(V, xi+2, yi, zi+2) + _G(V, xi, yi, zi+2) - _G(V, xi+2, yi+2, zi) + _G(V, xi,yi+2,zi)+_G(V, xi+2,yi,zi)-_G(V, xi,yi,zi)) | |
308 | + | |
309 | + for j in prange(64): | |
310 | + coef[j] = 0.0 | |
311 | + for i in xrange(64): | |
312 | + coef[j] += (temp[j][i] * _x[i]) | |
313 | + | |
314 | + | |
315 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
316 | +@cython.cdivision(True) | |
317 | +@cython.wraparound(False) | |
318 | +cdef double tricub_interpolate(image_t[:, :, :] V, double x, double y, double z) nogil: | |
319 | + # From: Tricubic interpolation in three dimensions. Lekien and Marsden | |
320 | + cdef double[64] coef | |
321 | + cdef double result = 0.0 | |
322 | + calc_coef_tricub(V, x, y, z, coef) | |
323 | + | |
324 | + cdef int i, j, k | |
325 | + | |
326 | + cdef int xi = <int>floor(x) | |
327 | + cdef int yi = <int>floor(y) | |
328 | + cdef int zi = <int>floor(z) | |
329 | + | |
330 | + for i in xrange(4): | |
331 | + for j in xrange(4): | |
332 | + for k in xrange(4): | |
333 | + result += (coef[i+4*j+16*k] * ((x-xi)**i) * ((y-yi)**j) * ((z-zi)**k)) | |
334 | + # return V[<int>z, <int>y, <int>x] | |
335 | + # with gil: | |
336 | + # print result | |
337 | + return result | |
338 | + | |
339 | + | |
340 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
341 | +@cython.cdivision(True) | |
342 | +@cython.wraparound(False) | |
343 | +cdef double cubicInterpolate(double p[4], double x) nogil: | |
344 | + return p[1] + 0.5 * x*(p[2] - p[0] + x*(2.0*p[0] - 5.0*p[1] + 4.0*p[2] - p[3] + x*(3.0*(p[1] - p[2]) + p[3] - p[0]))) | |
345 | + | |
346 | + | |
347 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
348 | +@cython.cdivision(True) | |
349 | +@cython.wraparound(False) | |
350 | +cdef double bicubicInterpolate (double p[4][4], double x, double y) nogil: | |
351 | + cdef double arr[4] | |
352 | + arr[0] = cubicInterpolate(p[0], y) | |
353 | + arr[1] = cubicInterpolate(p[1], y) | |
354 | + arr[2] = cubicInterpolate(p[2], y) | |
355 | + arr[3] = cubicInterpolate(p[3], y) | |
356 | + return cubicInterpolate(arr, x) | |
357 | + | |
358 | + | |
359 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
360 | +@cython.cdivision(True) | |
361 | +@cython.wraparound(False) | |
362 | +cdef double tricubicInterpolate(image_t[:, :, :] V, double x, double y, double z) nogil: | |
363 | + # From http://www.paulinternet.nl/?page=bicubic | |
364 | + cdef double p[4][4][4] | |
365 | + | |
366 | + cdef int xi = <int>floor(x) | |
367 | + cdef int yi = <int>floor(y) | |
368 | + cdef int zi = <int>floor(z) | |
369 | + | |
370 | + cdef int i, j, k | |
371 | + | |
372 | + for i in xrange(4): | |
373 | + for j in xrange(4): | |
374 | + for k in xrange(4): | |
375 | + p[i][j][k] = _G(V, xi + i -1, yi + j -1, zi + k - 1) | |
376 | + | |
377 | + cdef double arr[4] | |
378 | + arr[0] = bicubicInterpolate(p[0], y-yi, z-zi) | |
379 | + arr[1] = bicubicInterpolate(p[1], y-yi, z-zi) | |
380 | + arr[2] = bicubicInterpolate(p[2], y-yi, z-zi) | |
381 | + arr[3] = bicubicInterpolate(p[3], y-yi, z-zi) | |
382 | + return cubicInterpolate(arr, x-xi) | |
383 | + | |
384 | + | |
385 | +def tricub_interpolate_py(image_t[:, :, :] V, double x, double y, double z): | |
386 | + return tricub_interpolate(V, x, y, z) | |
387 | + | |
388 | +def tricub_interpolate2_py(image_t[:, :, :] V, double x, double y, double z): | |
389 | + return tricubicInterpolate(V, x, y, z) | |
390 | + | |
391 | +def trilin_interpolate_py(image_t[:, :, :] V, double x, double y, double z): | |
392 | + return interpolate(V, x, y, z) | ... | ... |
... | ... | @@ -0,0 +1,379 @@ |
1 | +#http://en.wikipedia.org/wiki/Local_maximum_intensity_projection | |
2 | +import numpy as np | |
3 | +cimport numpy as np | |
4 | +cimport cython | |
5 | + | |
6 | +from libc.math cimport floor, ceil, sqrt, fabs | |
7 | +from cython.parallel import prange | |
8 | + | |
9 | +DTYPE = np.uint8 | |
10 | +ctypedef np.uint8_t DTYPE_t | |
11 | + | |
12 | +DTYPE16 = np.int16 | |
13 | +ctypedef np.int16_t DTYPE16_t | |
14 | + | |
15 | +DTYPEF32 = np.float32 | |
16 | +ctypedef np.float32_t DTYPEF32_t | |
17 | + | |
18 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
19 | +def lmip(np.ndarray[DTYPE16_t, ndim=3] image, int axis, DTYPE16_t tmin, | |
20 | + DTYPE16_t tmax, np.ndarray[DTYPE16_t, ndim=2] out): | |
21 | + cdef DTYPE16_t max | |
22 | + cdef int start | |
23 | + cdef int sz = image.shape[0] | |
24 | + cdef int sy = image.shape[1] | |
25 | + cdef int sx = image.shape[2] | |
26 | + | |
27 | + # AXIAL | |
28 | + if axis == 0: | |
29 | + for x in xrange(sx): | |
30 | + for y in xrange(sy): | |
31 | + max = image[0, y, x] | |
32 | + if max >= tmin and max <= tmax: | |
33 | + start = 1 | |
34 | + else: | |
35 | + start = 0 | |
36 | + for z in xrange(sz): | |
37 | + if image[z, y, x] > max: | |
38 | + max = image[z, y, x] | |
39 | + | |
40 | + elif image[z, y, x] < max and start: | |
41 | + break | |
42 | + | |
43 | + if image[z, y, x] >= tmin and image[z, y, x] <= tmax: | |
44 | + start = 1 | |
45 | + | |
46 | + out[y, x] = max | |
47 | + | |
48 | + #CORONAL | |
49 | + elif axis == 1: | |
50 | + for z in xrange(sz): | |
51 | + for x in xrange(sx): | |
52 | + max = image[z, 0, x] | |
53 | + if max >= tmin and max <= tmax: | |
54 | + start = 1 | |
55 | + else: | |
56 | + start = 0 | |
57 | + for y in xrange(sy): | |
58 | + if image[z, y, x] > max: | |
59 | + max = image[z, y, x] | |
60 | + | |
61 | + elif image[z, y, x] < max and start: | |
62 | + break | |
63 | + | |
64 | + if image[z, y, x] >= tmin and image[z, y, x] <= tmax: | |
65 | + start = 1 | |
66 | + | |
67 | + out[z, x] = max | |
68 | + | |
69 | + #CORONAL | |
70 | + elif axis == 2: | |
71 | + for z in xrange(sz): | |
72 | + for y in xrange(sy): | |
73 | + max = image[z, y, 0] | |
74 | + if max >= tmin and max <= tmax: | |
75 | + start = 1 | |
76 | + else: | |
77 | + start = 0 | |
78 | + for x in xrange(sx): | |
79 | + if image[z, y, x] > max: | |
80 | + max = image[z, y, x] | |
81 | + | |
82 | + elif image[z, y, x] < max and start: | |
83 | + break | |
84 | + | |
85 | + if image[z, y, x] >= tmin and image[z, y, x] <= tmax: | |
86 | + start = 1 | |
87 | + | |
88 | + out[z, y] = max | |
89 | + | |
90 | + | |
91 | +cdef DTYPE16_t get_colour(DTYPE16_t vl, DTYPE16_t wl, DTYPE16_t ww): | |
92 | + cdef DTYPE16_t out_colour | |
93 | + cdef DTYPE16_t min_value = wl - (ww / 2) | |
94 | + cdef DTYPE16_t max_value = wl + (ww / 2) | |
95 | + if vl < min_value: | |
96 | + out_colour = min_value | |
97 | + elif vl > max_value: | |
98 | + out_colour = max_value | |
99 | + else: | |
100 | + out_colour = vl | |
101 | + | |
102 | + return out_colour | |
103 | + | |
104 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
105 | +@cython.cdivision(True) | |
106 | +cdef float get_opacity(DTYPE16_t vl, DTYPE16_t wl, DTYPE16_t ww) nogil: | |
107 | + cdef float out_opacity | |
108 | + cdef DTYPE16_t min_value = wl - (ww / 2) | |
109 | + cdef DTYPE16_t max_value = wl + (ww / 2) | |
110 | + if vl < min_value: | |
111 | + out_opacity = 0.0 | |
112 | + elif vl > max_value: | |
113 | + out_opacity = 1.0 | |
114 | + else: | |
115 | + out_opacity = 1.0/(max_value - min_value) * (vl - min_value) | |
116 | + | |
117 | + return out_opacity | |
118 | + | |
119 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
120 | +@cython.cdivision(True) | |
121 | +cdef float get_opacity_f32(DTYPEF32_t vl, DTYPE16_t wl, DTYPE16_t ww) nogil: | |
122 | + cdef float out_opacity | |
123 | + cdef DTYPE16_t min_value = wl - (ww / 2) | |
124 | + cdef DTYPE16_t max_value = wl + (ww / 2) | |
125 | + if vl < min_value: | |
126 | + out_opacity = 0.0 | |
127 | + elif vl > max_value: | |
128 | + out_opacity = 1.0 | |
129 | + else: | |
130 | + out_opacity = 1.0/(max_value - min_value) * (vl - min_value) | |
131 | + | |
132 | + return out_opacity | |
133 | + | |
134 | + | |
135 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
136 | +@cython.cdivision(True) | |
137 | +def mida(np.ndarray[DTYPE16_t, ndim=3] image, int axis, DTYPE16_t wl, | |
138 | + DTYPE16_t ww, np.ndarray[DTYPE16_t, ndim=2] out): | |
139 | + cdef int sz = image.shape[0] | |
140 | + cdef int sy = image.shape[1] | |
141 | + cdef int sx = image.shape[2] | |
142 | + | |
143 | + cdef DTYPE16_t min = image.min() | |
144 | + cdef DTYPE16_t max = image.max() | |
145 | + cdef DTYPE16_t vl | |
146 | + | |
147 | + cdef DTYPE16_t min_value = wl - (ww / 2) | |
148 | + cdef DTYPE16_t max_value = wl + (ww / 2) | |
149 | + | |
150 | + cdef float fmax=0.0 | |
151 | + cdef float fpi | |
152 | + cdef float dl | |
153 | + cdef float bt | |
154 | + | |
155 | + cdef float alpha | |
156 | + cdef float alpha_p = 0.0 | |
157 | + cdef float colour | |
158 | + cdef float colour_p = 0 | |
159 | + | |
160 | + cdef int x, y, z | |
161 | + | |
162 | + # AXIAL | |
163 | + if axis == 0: | |
164 | + for x in prange(sx, nogil=True): | |
165 | + for y in xrange(sy): | |
166 | + fmax = 0.0 | |
167 | + alpha_p = 0.0 | |
168 | + colour_p = 0.0 | |
169 | + for z in xrange(sz): | |
170 | + vl = image[z, y, x] | |
171 | + fpi = 1.0/(max - min) * (vl - min) | |
172 | + if fpi > fmax: | |
173 | + dl = fpi - fmax | |
174 | + fmax = fpi | |
175 | + else: | |
176 | + dl = 0.0 | |
177 | + | |
178 | + bt = 1.0 - dl | |
179 | + | |
180 | + colour = fpi | |
181 | + alpha = get_opacity(vl, wl, ww) | |
182 | + colour = (bt * colour_p) + (1 - bt * alpha_p) * colour * alpha | |
183 | + alpha = (bt * alpha_p) + (1 - bt * alpha_p) * alpha | |
184 | + | |
185 | + colour_p = colour | |
186 | + alpha_p = alpha | |
187 | + | |
188 | + if alpha >= 1.0: | |
189 | + break | |
190 | + | |
191 | + | |
192 | + #out[y, x] = <DTYPE16_t>((max_value - min_value) * colour + min_value) | |
193 | + out[y, x] = <DTYPE16_t>((max - min) * colour + min) | |
194 | + | |
195 | + | |
196 | + #CORONAL | |
197 | + elif axis == 1: | |
198 | + for z in prange(sz, nogil=True): | |
199 | + for x in xrange(sx): | |
200 | + fmax = 0.0 | |
201 | + alpha_p = 0.0 | |
202 | + colour_p = 0.0 | |
203 | + for y in xrange(sy): | |
204 | + vl = image[z, y, x] | |
205 | + fpi = 1.0/(max - min) * (vl - min) | |
206 | + if fpi > fmax: | |
207 | + dl = fpi - fmax | |
208 | + fmax = fpi | |
209 | + else: | |
210 | + dl = 0.0 | |
211 | + | |
212 | + bt = 1.0 - dl | |
213 | + | |
214 | + colour = fpi | |
215 | + alpha = get_opacity(vl, wl, ww) | |
216 | + colour = (bt * colour_p) + (1 - bt * alpha_p) * colour * alpha | |
217 | + alpha = (bt * alpha_p) + (1 - bt * alpha_p) * alpha | |
218 | + | |
219 | + colour_p = colour | |
220 | + alpha_p = alpha | |
221 | + | |
222 | + if alpha >= 1.0: | |
223 | + break | |
224 | + | |
225 | + out[z, x] = <DTYPE16_t>((max - min) * colour + min) | |
226 | + | |
227 | + #AXIAL | |
228 | + elif axis == 2: | |
229 | + for z in prange(sz, nogil=True): | |
230 | + for y in xrange(sy): | |
231 | + fmax = 0.0 | |
232 | + alpha_p = 0.0 | |
233 | + colour_p = 0.0 | |
234 | + for x in xrange(sx): | |
235 | + vl = image[z, y, x] | |
236 | + fpi = 1.0/(max - min) * (vl - min) | |
237 | + if fpi > fmax: | |
238 | + dl = fpi - fmax | |
239 | + fmax = fpi | |
240 | + else: | |
241 | + dl = 0.0 | |
242 | + | |
243 | + bt = 1.0 - dl | |
244 | + | |
245 | + colour = fpi | |
246 | + alpha = get_opacity(vl, wl, ww) | |
247 | + colour = (bt * colour_p) + (1 - bt * alpha_p) * colour * alpha | |
248 | + alpha = (bt * alpha_p) + (1 - bt * alpha_p) * alpha | |
249 | + | |
250 | + colour_p = colour | |
251 | + alpha_p = alpha | |
252 | + | |
253 | + if alpha >= 1.0: | |
254 | + break | |
255 | + | |
256 | + out[z, y] = <DTYPE16_t>((max - min) * colour + min) | |
257 | + | |
258 | + | |
259 | + | |
260 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
261 | +@cython.cdivision(True) | |
262 | +cdef inline void finite_difference(DTYPE16_t[:, :, :] image, | |
263 | + int x, int y, int z, float h, float *g) nogil: | |
264 | + cdef int px, py, pz, fx, fy, fz | |
265 | + | |
266 | + cdef int sz = image.shape[0] | |
267 | + cdef int sy = image.shape[1] | |
268 | + cdef int sx = image.shape[2] | |
269 | + | |
270 | + cdef float gx, gy, gz | |
271 | + | |
272 | + if x == 0: | |
273 | + px = 0 | |
274 | + fx = 1 | |
275 | + elif x == sx - 1: | |
276 | + px = x - 1 | |
277 | + fx = x | |
278 | + else: | |
279 | + px = x - 1 | |
280 | + fx = x + 1 | |
281 | + | |
282 | + if y == 0: | |
283 | + py = 0 | |
284 | + fy = 1 | |
285 | + elif y == sy - 1: | |
286 | + py = y - 1 | |
287 | + fy = y | |
288 | + else: | |
289 | + py = y - 1 | |
290 | + fy = y + 1 | |
291 | + | |
292 | + if z == 0: | |
293 | + pz = 0 | |
294 | + fz = 1 | |
295 | + elif z == sz - 1: | |
296 | + pz = z - 1 | |
297 | + fz = z | |
298 | + else: | |
299 | + pz = z - 1 | |
300 | + fz = z + 1 | |
301 | + | |
302 | + gx = (image[z, y, fx] - image[z, y, px]) / (2*h) | |
303 | + gy = (image[z, fy, x] - image[z, py, x]) / (2*h) | |
304 | + gz = (image[fz, y, x] - image[pz, y, x]) / (2*h) | |
305 | + | |
306 | + g[0] = gx | |
307 | + g[1] = gy | |
308 | + g[2] = gz | |
309 | + | |
310 | + | |
311 | + | |
312 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
313 | +@cython.cdivision(True) | |
314 | +cdef inline float calc_fcm_itensity(DTYPE16_t[:, :, :] image, | |
315 | + int x, int y, int z, float n, float* dir) nogil: | |
316 | + cdef float g[3] | |
317 | + finite_difference(image, x, y, z, 1.0, g) | |
318 | + cdef float gm = sqrt(g[0]*g[0] + g[1]*g[1] + g[2]*g[2]) | |
319 | + cdef float d = g[0]*dir[0] + g[1]*dir[1] + g[2]*dir[2] | |
320 | + cdef float sf = (1.0 - fabs(d/gm))**n | |
321 | + #alpha = get_opacity_f32(gm, wl, ww) | |
322 | + cdef float vl = gm * sf | |
323 | + return vl | |
324 | + | |
325 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
326 | +@cython.cdivision(True) | |
327 | +def fast_countour_mip(np.ndarray[DTYPE16_t, ndim=3] image, | |
328 | + float n, | |
329 | + int axis, | |
330 | + DTYPE16_t wl, DTYPE16_t ww, | |
331 | + int tmip, | |
332 | + np.ndarray[DTYPE16_t, ndim=2] out): | |
333 | + cdef int sz = image.shape[0] | |
334 | + cdef int sy = image.shape[1] | |
335 | + cdef int sx = image.shape[2] | |
336 | + cdef float gm | |
337 | + cdef float alpha | |
338 | + cdef float sf | |
339 | + cdef float d | |
340 | + | |
341 | + cdef float* g | |
342 | + cdef float* dir = [ 0, 0, 0 ] | |
343 | + | |
344 | + cdef DTYPE16_t[:, :, :] vimage = image | |
345 | + cdef np.ndarray[DTYPE16_t, ndim=3] tmp = np.empty_like(image) | |
346 | + | |
347 | + cdef DTYPE16_t min = image.min() | |
348 | + cdef DTYPE16_t max = image.max() | |
349 | + cdef float fmin = <float>min | |
350 | + cdef float fmax = <float>max | |
351 | + cdef float vl | |
352 | + cdef DTYPE16_t V | |
353 | + | |
354 | + cdef int x, y, z | |
355 | + | |
356 | + if axis == 0: | |
357 | + dir[2] = 1.0 | |
358 | + elif axis == 1: | |
359 | + dir[1] = 1.0 | |
360 | + elif axis == 2: | |
361 | + dir[0] = 1.0 | |
362 | + | |
363 | + for z in prange(sz, nogil=True): | |
364 | + for y in range(sy): | |
365 | + for x in range(sx): | |
366 | + vl = calc_fcm_itensity(vimage, x, y, z, n, dir) | |
367 | + tmp[z, y, x] = <DTYPE16_t>vl | |
368 | + | |
369 | + cdef DTYPE16_t tmin = tmp.min() | |
370 | + cdef DTYPE16_t tmax = tmp.max() | |
371 | + | |
372 | + #tmp = ((max - min)/<float>(tmax - tmin)) * (tmp - tmin) + min | |
373 | + | |
374 | + if tmip == 0: | |
375 | + out[:] = tmp.max(axis) | |
376 | + elif tmip == 1: | |
377 | + lmip(tmp, axis, 700, 3033, out) | |
378 | + elif tmip == 2: | |
379 | + mida(tmp, axis, wl, ww, out) | ... | ... |
... | ... | @@ -0,0 +1,174 @@ |
1 | +import numpy as np | |
2 | +cimport numpy as np | |
3 | +cimport cython | |
4 | + | |
5 | +from .cy_my_types cimport image_t | |
6 | +from .interpolation cimport interpolate, tricub_interpolate, tricubicInterpolate, lanczos3, nearest_neighbour_interp | |
7 | + | |
8 | +from libc.math cimport floor, ceil, sqrt, fabs, round | |
9 | +from cython.parallel import prange | |
10 | + | |
11 | +ctypedef double (*interp_function)(image_t[:, :, :], double, double, double) nogil | |
12 | + | |
13 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
14 | +@cython.cdivision(True) | |
15 | +@cython.wraparound(False) | |
16 | +cdef void mul_mat4_vec4(double[:, :] M, | |
17 | + double* coord, | |
18 | + double* out) nogil: | |
19 | + | |
20 | + out[0] = coord[0] * M[0, 0] + coord[1] * M[0, 1] + coord[2] * M[0, 2] + coord[3] * M[0, 3] | |
21 | + out[1] = coord[0] * M[1, 0] + coord[1] * M[1, 1] + coord[2] * M[1, 2] + coord[3] * M[1, 3] | |
22 | + out[2] = coord[0] * M[2, 0] + coord[1] * M[2, 1] + coord[2] * M[2, 2] + coord[3] * M[2, 3] | |
23 | + out[3] = coord[0] * M[3, 0] + coord[1] * M[3, 1] + coord[2] * M[3, 2] + coord[3] * M[3, 3] | |
24 | + | |
25 | + | |
26 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
27 | +@cython.cdivision(True) | |
28 | +@cython.wraparound(False) | |
29 | +cdef image_t coord_transform(image_t[:, :, :] volume, double[:, :] M, int x, int y, int z, double sx, double sy, double sz, interp_function f_interp, image_t cval) nogil: | |
30 | + | |
31 | + cdef double coord[4] | |
32 | + coord[0] = z*sz | |
33 | + coord[1] = y*sy | |
34 | + coord[2] = x*sx | |
35 | + coord[3] = 1.0 | |
36 | + | |
37 | + cdef double _ncoord[4] | |
38 | + _ncoord[3] = 1 | |
39 | + # _ncoord[:] = [0.0, 0.0, 0.0, 1.0] | |
40 | + | |
41 | + cdef unsigned int dz, dy, dx | |
42 | + dz = volume.shape[0] | |
43 | + dy = volume.shape[1] | |
44 | + dx = volume.shape[2] | |
45 | + | |
46 | + | |
47 | + mul_mat4_vec4(M, coord, _ncoord) | |
48 | + | |
49 | + cdef double nz, ny, nx | |
50 | + nz = (_ncoord[0]/_ncoord[3])/sz | |
51 | + ny = (_ncoord[1]/_ncoord[3])/sy | |
52 | + nx = (_ncoord[2]/_ncoord[3])/sx | |
53 | + | |
54 | + cdef double v | |
55 | + | |
56 | + if 0 <= nz <= (dz-1) and 0 <= ny <= (dy-1) and 0 <= nx <= (dx-1): | |
57 | + return <image_t>f_interp(volume, nx, ny, nz) | |
58 | + # if minterpol == 0: | |
59 | + # return <image_t>nearest_neighbour_interp(volume, nx, ny, nz) | |
60 | + # elif minterpol == 1: | |
61 | + # return <image_t>interpolate(volume, nx, ny, nz) | |
62 | + # elif minterpol == 2: | |
63 | + # v = tricubicInterpolate(volume, nx, ny, nz) | |
64 | + # if (v < cval): | |
65 | + # v = cval | |
66 | + # return <image_t>v | |
67 | + # else: | |
68 | + # v = lanczos3(volume, nx, ny, nz) | |
69 | + # if (v < cval): | |
70 | + # v = cval | |
71 | + # return <image_t>v | |
72 | + else: | |
73 | + return cval | |
74 | + | |
75 | + | |
76 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
77 | +@cython.cdivision(True) | |
78 | +@cython.wraparound(False) | |
79 | +def apply_view_matrix_transform(image_t[:, :, :] volume, | |
80 | + spacing, | |
81 | + double[:, :] M, | |
82 | + unsigned int n, str orientation, | |
83 | + int minterpol, | |
84 | + image_t cval, | |
85 | + image_t[:, :, :] out): | |
86 | + | |
87 | + cdef int dz, dy, dx | |
88 | + cdef int z, y, x | |
89 | + dz = volume.shape[0] | |
90 | + dy = volume.shape[1] | |
91 | + dx = volume.shape[2] | |
92 | + | |
93 | + cdef unsigned int odz, ody, odx | |
94 | + odz = out.shape[0] | |
95 | + ody = out.shape[1] | |
96 | + odx = out.shape[2] | |
97 | + | |
98 | + cdef unsigned int count = 0 | |
99 | + | |
100 | + cdef double sx, sy, sz | |
101 | + sx = spacing[0] | |
102 | + sy = spacing[1] | |
103 | + sz = spacing[2] | |
104 | + | |
105 | + cdef interp_function f_interp | |
106 | + | |
107 | + if minterpol == 0: | |
108 | + f_interp = nearest_neighbour_interp | |
109 | + elif minterpol == 1: | |
110 | + f_interp = interpolate | |
111 | + elif minterpol == 2: | |
112 | + f_interp = tricubicInterpolate | |
113 | + else: | |
114 | + f_interp = lanczos3 | |
115 | + | |
116 | + if orientation == 'AXIAL': | |
117 | + for z in xrange(n, n+odz): | |
118 | + for y in prange(dy, nogil=True): | |
119 | + for x in xrange(dx): | |
120 | + out[count, y, x] = coord_transform(volume, M, x, y, z, sx, sy, sz, f_interp, cval) | |
121 | + count += 1 | |
122 | + | |
123 | + elif orientation == 'CORONAL': | |
124 | + for y in xrange(n, n+ody): | |
125 | + for z in prange(dz, nogil=True): | |
126 | + for x in xrange(dx): | |
127 | + out[z, count, x] = coord_transform(volume, M, x, y, z, sx, sy, sz, f_interp, cval) | |
128 | + count += 1 | |
129 | + | |
130 | + elif orientation == 'SAGITAL': | |
131 | + for x in xrange(n, n+odx): | |
132 | + for z in prange(dz, nogil=True): | |
133 | + for y in xrange(dy): | |
134 | + out[z, y, count] = coord_transform(volume, M, x, y, z, sx, sy, sz, f_interp, cval) | |
135 | + count += 1 | |
136 | + | |
137 | + | |
138 | +@cython.boundscheck(False) # turn of bounds-checking for entire function | |
139 | +@cython.cdivision(True) | |
140 | +@cython.wraparound(False) | |
141 | +def convolve_non_zero(image_t[:, :, :] volume, | |
142 | + image_t[:, :, :] kernel, | |
143 | + image_t cval): | |
144 | + cdef Py_ssize_t x, y, z, sx, sy, sz, kx, ky, kz, skx, sky, skz, i, j, k | |
145 | + cdef image_t v | |
146 | + | |
147 | + cdef image_t[:, :, :] out = np.zeros_like(volume) | |
148 | + | |
149 | + sz = volume.shape[0] | |
150 | + sy = volume.shape[1] | |
151 | + sx = volume.shape[2] | |
152 | + | |
153 | + skz = kernel.shape[0] | |
154 | + sky = kernel.shape[1] | |
155 | + skx = kernel.shape[2] | |
156 | + | |
157 | + for z in prange(sz, nogil=True): | |
158 | + for y in xrange(sy): | |
159 | + for x in xrange(sx): | |
160 | + if volume[z, y, x] != 0: | |
161 | + for k in xrange(skz): | |
162 | + kz = z - skz // 2 + k | |
163 | + for j in xrange(sky): | |
164 | + ky = y - sky // 2 + j | |
165 | + for i in xrange(skx): | |
166 | + kx = x - skx // 2 + i | |
167 | + | |
168 | + if 0 <= kz < sz and 0 <= ky < sy and 0 <= kx < sx: | |
169 | + v = volume[kz, ky, kx] | |
170 | + else: | |
171 | + v = cval | |
172 | + | |
173 | + out[z, y, x] += (v * kernel[k, j, i]) | |
174 | + return np.asarray(out) | ... | ... |
setup.py
... | ... | @@ -40,25 +40,25 @@ setup( |
40 | 40 | ext_modules=cythonize( |
41 | 41 | [ |
42 | 42 | Extension( |
43 | - "invesalius.data.mips", | |
44 | - ["invesalius/data/mips.pyx"], | |
43 | + "invesalius_cy.mips", | |
44 | + ["invesalius_cy/mips.pyx"], | |
45 | 45 | ), |
46 | 46 | Extension( |
47 | - "invesalius.data.interpolation", | |
48 | - ["invesalius/data/interpolation.pyx"], | |
47 | + "invesalius_cy.interpolation", | |
48 | + ["invesalius_cy/interpolation.pyx"], | |
49 | 49 | ), |
50 | 50 | Extension( |
51 | - "invesalius.data.transforms", | |
52 | - ["invesalius/data/transforms.pyx"], | |
51 | + "invesalius_cy.transforms", | |
52 | + ["invesalius_cy/transforms.pyx"], | |
53 | 53 | ), |
54 | 54 | Extension( |
55 | - "invesalius.data.floodfill", | |
56 | - ["invesalius/data/floodfill.pyx"], | |
55 | + "invesalius_cy.floodfill", | |
56 | + ["invesalius_cy/floodfill.pyx"], | |
57 | 57 | language="c++", |
58 | 58 | ), |
59 | 59 | Extension( |
60 | - "invesalius.data.cy_mesh", | |
61 | - ["invesalius/data/cy_mesh.pyx"], | |
60 | + "invesalius_cy.cy_mesh", | |
61 | + ["invesalius_cy/cy_mesh.pyx"], | |
62 | 62 | language="c++", |
63 | 63 | ), |
64 | 64 | ] | ... | ... |