void local_histogram(double* H, unsigned int clamp, PyArrayIterObject* iter, const unsigned int* size) { PyArrayObject *block, *im = iter->ao; PyArrayIterObject* block_iter; unsigned int i, left, right, center, halfsize, dim, offset=0; npy_intp block_dims[3]; UPDATE_ITERATOR_COORDS(iter); /* Compute block corners */ for (i=0; i<3; i++) { center = iter->coordinates[i]; halfsize = size[i]/2; dim = PyArray_DIM(im, i); /* Left handside corner */ if (center<halfsize) left = 0; else left = center-halfsize; /* Right handside corner (plus one)*/ right = center+halfsize+1; if (right>dim) right = dim; /* Block properties */ offset += left*PyArray_STRIDE(im, i); block_dims[i] = right-left; } /* Create the block as a vew and the block iterator */ block = (PyArrayObject*)PyArray_New(&PyArray_Type, 3, block_dims, PyArray_TYPE(im), PyArray_STRIDES(im), (void*)(PyArray_DATA(im)+offset), PyArray_ITEMSIZE(im), NPY_BEHAVED, NULL); block_iter = (PyArrayIterObject*)PyArray_IterNew((PyObject*)block); /* Compute block histogram */ histogram(H, clamp, block_iter); /* Free memory */ Py_XDECREF(block_iter); Py_XDECREF(block); return; }
/* Resample a 3d image submitted to an affine transformation. Tvox is the voxel transformation from the image to the destination grid. */ void cubic_spline_resample3d(PyArrayObject* im_resampled, const PyArrayObject* im, const double* Tvox, int cast_integer, int mode_x, int mode_y, int mode_z) { double i1; PyObject* py_i1; PyArrayObject* im_spline_coeff; PyArrayIterObject* imIter = (PyArrayIterObject*)PyArray_IterNew((PyObject*)im_resampled); unsigned int x, y, z; unsigned dimX = PyArray_DIM(im, 0); unsigned dimY = PyArray_DIM(im, 1); unsigned dimZ = PyArray_DIM(im, 2); npy_intp dims[3] = {dimX, dimY, dimZ}; double Tx, Ty, Tz; /* Compute the spline coefficient image */ im_spline_coeff = (PyArrayObject*)PyArray_SimpleNew(3, dims, NPY_DOUBLE); cubic_spline_transform(im_spline_coeff, im); /* Force iterator coordinates to be updated */ UPDATE_ITERATOR_COORDS(imIter); /* Resampling loop */ while(imIter->index < imIter->size) { x = imIter->coordinates[0]; y = imIter->coordinates[1]; z = imIter->coordinates[2]; _apply_affine_transform(&Tx, &Ty, &Tz, Tvox, x, y, z); i1 = cubic_spline_sample3d(Tx, Ty, Tz, im_spline_coeff, mode_x, mode_y, mode_z); if (cast_integer) i1 = ROUND(i1); /* Copy interpolated value into numpy array */ py_i1 = PyFloat_FromDouble(i1); PyArray_SETITEM(im_resampled, PyArray_ITER_DATA(imIter), py_i1); Py_DECREF(py_i1); /* Increment iterator */ PyArray_ITER_NEXT(imIter); } /* Free memory */ Py_DECREF(imIter); Py_DECREF(im_spline_coeff); return; }
void joint_histogram(double* H, unsigned int clampI, unsigned int clampJ, PyArrayIterObject* iterI, const PyArrayObject* imJ_padded, const double* Tvox, int affine, int interp) { const signed short* J=(signed short*)imJ_padded->data; size_t dimJX=imJ_padded->dimensions[0]-2; size_t dimJY=imJ_padded->dimensions[1]-2; size_t dimJZ=imJ_padded->dimensions[2]-2; signed short Jnn[8]; double W[8]; signed short *bufI, *bufJnn; double *bufW; signed short i, j; size_t off; size_t u2 = imJ_padded->dimensions[2]; size_t u3 = u2+1; size_t u4 = imJ_padded->dimensions[1]*u2; size_t u5 = u4+1; size_t u6 = u4+u2; size_t u7 = u6+1; double wx, wy, wz, wxwy, wxwz, wywz; double W0, W2, W3, W4; size_t x, y, z; int nn, nx, ny, nz; double Tx, Ty, Tz; double *bufTvox = (double*)Tvox; void (*interpolate)(unsigned int, double*, unsigned int, const signed short*, const double*, int, void*); void* interp_params = NULL; rk_state rng; /* Reset the source image iterator */ PyArray_ITER_RESET(iterI); /* Make sure the iterator the iterator will update coordinate values */ UPDATE_ITERATOR_COORDS(iterI); /* Set interpolation method */ if (interp==0) interpolate = &_pv_interpolation; else if (interp>0) interpolate = &_tri_interpolation; else { /* interp < 0 */ interpolate = &_rand_interpolation; rk_seed(-interp, &rng); interp_params = (void*)(&rng); } /* Re-initialize joint histogram */ memset((void*)H, 0, clampI*clampJ*sizeof(double)); /* Looop over source voxels */ while(iterI->index < iterI->size) { /* Source voxel intensity */ bufI = (signed short*)PyArray_ITER_DATA(iterI); i = bufI[0]; /* Compute the transformed grid coordinates of current voxel */ if (affine) { /* Get voxel coordinates and apply transformation on-the-fly*/ x = iterI->coordinates[0]; y = iterI->coordinates[1]; z = iterI->coordinates[2]; _affine_transform(&Tx, &Ty, &Tz, Tvox, x, y, z); } else /* Use precomputed transformed coordinates */ bufTvox = _precomputed_transform(&Tx, &Ty, &Tz, (const double*)bufTvox); /* Test whether the current voxel is below the intensity threshold, or the transformed point is completly outside the reference grid */ if ((i>=0) && (Tx>-1) && (Tx<dimJX) && (Ty>-1) && (Ty<dimJY) && (Tz>-1) && (Tz<dimJZ)) { /* Nearest neighbor (floor coordinates in the padded image, hence +1). Notice that using the floor function doubles excetution time. FIXME: see if we can replace this with assembler instructions. */ nx = FLOOR(Tx) + 1; ny = FLOOR(Ty) + 1; nz = FLOOR(Tz) + 1; /* The convention for neighbor indexing is as follows: * * Floor slice Ceil slice * * 2----6 3----7 y * | | | | ^ * | | | | | * 0----4 1----5 ---> x */ /*** Trilinear interpolation weights. Note: wx = nnx + 1 - Tx, where nnx is the location in the NON-PADDED grid */ wx = nx - Tx; wy = ny - Ty; wz = nz - Tz; wxwy = wx*wy; wxwz = wx*wz; wywz = wy*wz; /*** Prepare buffers */ bufJnn = Jnn; bufW = W; /*** Initialize neighbor list */ off = nx*u4 + ny*u2 + nz; nn = 0; /*** Neighbor 0: (0,0,0) */ W0 = wxwy*wz; APPEND_NEIGHBOR(off, W0); /*** Neighbor 1: (0,0,1) */ APPEND_NEIGHBOR(off+1, wxwy-W0); /*** Neighbor 2: (0,1,0) */ W2 = wxwz-W0; APPEND_NEIGHBOR(off+u2, W2); /*** Neightbor 3: (0,1,1) */ W3 = wx-wxwy-W2; APPEND_NEIGHBOR(off+u3, W3); /*** Neighbor 4: (1,0,0) */ W4 = wywz-W0; APPEND_NEIGHBOR(off+u4, W4); /*** Neighbor 5: (1,0,1) */ APPEND_NEIGHBOR(off+u5, wy-wxwy-W4); /*** Neighbor 6: (1,1,0) */ APPEND_NEIGHBOR(off+u6, wz-wxwz-W4); /*** Neighbor 7: (1,1,1) */ APPEND_NEIGHBOR(off+u7, 1-W3-wy-wz+wywz); /* Update the joint histogram using the desired interpolation technique */ interpolate(i, H, clampJ, Jnn, W, nn, interp_params); } /* End of IF TRANSFORMS INSIDE */ /* Update source index */ PyArray_ITER_NEXT(iterI); } /* End of loop over voxels */ return; }