20 #ifndef MIRTK_ImageToInterpolationCoefficients_H 21 #define MIRTK_ImageToInterpolationCoefficients_H 23 #include "mirtk/Math.h" 24 #include "mirtk/Voxel.h" 25 #include "mirtk/GenericImage.h" 26 #include "mirtk/Parallel.h" 27 #include "mirtk/Stream.h" 28 #include "mirtk/Queue.h" 35 template <
class TData,
class TReal>
36 TData InitialAntiCausalCoefficient(TData c[],
int n, TReal z)
39 return ((z / (z * z - TReal(1))) * (z * c[n - 2] + c[n - 1]));
43 template <
class TData,
class TReal>
44 TData InitialCausalCoefficient(TData c[],
int n, TReal z, TReal tol)
49 if (tol > 0) m =
static_cast<int>(ceil(log(tol) / log(abs(z))));
55 for (
int i = 1; i < m; ++i) {
61 const TReal iz = TReal(1) / z;
63 TReal z2n = pow(z, TReal(n - 1));
64 sum = c[0] + z2n * c[n - 1];
66 for (
int i = 1; i <= n - 2; ++i) {
67 sum += (zn + z2n) * c[i];
71 sum /= (TReal(1) - zn * zn);
77 template <
class TData,
class TReal>
78 void ConvertToInterpolationCoefficients(TData *c,
int n,
const TReal *z,
int npoles, TReal tol)
83 TReal lambda = TReal(1);
84 for (
int k = 0; k < npoles; ++k) {
85 lambda *= (TReal(1) - z[k]) * (TReal(1) - TReal(1) / z[k]);
88 for (
int i = 0; i < n; ++i) c[i] *= lambda;
90 for (
int k = 0; k < npoles; ++k) {
92 c[0] = InitialCausalCoefficient(c, n, z[k], tol);
94 for (
int i = 1; i < n; ++i) c[i] += z[k] * c[i - 1];
96 c[n - 1] = InitialAntiCausalCoefficient(c, n, z[k]);
98 for (
int i = n - 2; i >= 0; --i) c[i] = z[k] * (c[i + 1] - c[i]);
103 template <
class TData,
class TReal>
104 struct ConvertToInterpolationCoefficientsBase
106 ConvertToInterpolationCoefficientsBase(GenericImage<TData> &image,
const TReal *z,
int npoles)
108 _image(image), _z(z), _npoles(npoles)
111 void Process(TData *data,
int n)
const 113 ConvertToInterpolationCoefficients(data, n, _z, _npoles, static_cast<TReal>(DBL_EPSILON));
117 GenericImage<TData> &_image;
123 template <
class TData,
class TReal>
124 struct ConvertToInterpolationCoefficientsXFunc :
public ConvertToInterpolationCoefficientsBase<TData, TReal>
126 ConvertToInterpolationCoefficientsXFunc(GenericImage<TData> &image,
const TReal *z,
int npoles)
128 ConvertToInterpolationCoefficientsBase<TData, TReal>(image, z, npoles)
131 void operator()(
const blocked_range3d<int> &re)
const 133 TData *data =
new TData[this->_image.X()];
134 for (
int l = re.pages().begin(); l != re.pages().end(); ++l)
135 for (
int k = re.rows ().begin(); k != re.rows ().end(); ++k)
136 for (
int j = re.cols ().begin(); j != re.cols ().end(); ++j) {
137 for (
int i = 0; i < this->_image.X(); ++i) {
138 data[i] = this->_image(i, j, k, l);
140 this->Process(data, this->_image.X());
141 for (
int i = 0; i < this->_image.X(); ++i) {
142 this->_image(i, j, k, l) = data[i];
148 void operator()(
int l = -1)
150 int L = this->_image.T();
151 if (0 <= l && l < this->_image.T()) L = l+1;
153 blocked_range3d<int> re(l, L, 0, this->_image.Z(), 0, this->_image.Y());
157 void operator()(
int k,
int l)
159 blocked_range3d<int> re(l, l+1, k, k+1, 0, this->_image.Y());
165 template <
class TData,
class TReal>
166 struct ConvertToInterpolationCoefficientsYFunc :
public ConvertToInterpolationCoefficientsBase<TData, TReal>
168 ConvertToInterpolationCoefficientsYFunc(GenericImage<TData> &image,
const TReal *z,
int npoles)
170 ConvertToInterpolationCoefficientsBase<TData, TReal>(image, z, npoles)
173 void operator()(
const blocked_range3d<int> &re)
const 175 TData *data =
new TData[this->_image.Y()];
176 for (
int l = re.pages().begin(); l != re.pages().end(); ++l)
177 for (
int k = re.rows ().begin(); k != re.rows ().end(); ++k)
178 for (
int i = re.cols ().begin(); i != re.cols ().end(); ++i) {
179 for (
int j = 0; j < this->_image.Y(); ++j) {
180 data[j] = this->_image(i, j, k, l);
182 this->Process(data, this->_image.Y());
183 for (
int j = 0; j < this->_image.Y(); ++j) {
184 this->_image(i, j, k, l) = data[j];
190 void operator()(
int l = -1)
192 int L = this->_image.T();
193 if (0 <= l && l < this->_image.T()) L = l+1;
195 blocked_range3d<int> re(l, L, 0, this->_image.Z(), 0, this->_image.X());
199 void operator()(
int k,
int l)
201 blocked_range3d<int> re(l, l+1, k, k+1, 0, this->_image.X());
207 template <
class TData,
class TReal>
208 struct ConvertToInterpolationCoefficientsZFunc :
public ConvertToInterpolationCoefficientsBase<TData, TReal>
210 ConvertToInterpolationCoefficientsZFunc(GenericImage<TData> &image,
const TReal *z,
int npoles)
212 ConvertToInterpolationCoefficientsBase<TData, TReal>(image, z, npoles)
215 void operator()(
const blocked_range3d<int> &re)
const 217 TData *data =
new TData[this->_image.Z()];
218 for (
int l = re.pages().begin(); l != re.pages().end(); ++l)
219 for (
int j = re.rows ().begin(); j != re.rows ().end(); ++j)
220 for (
int i = re.cols ().begin(); i != re.cols ().end(); ++i) {
221 for (
int k = 0; k < this->_image.Z(); ++k) {
222 data[k] = this->_image(i, j, k, l);
224 this->Process(data, this->_image.Z());
225 for (
int k = 0; k < this->_image.Z(); ++k) {
226 this->_image(i, j, k, l) = data[k];
232 void operator()(
int l = -1)
234 int L = this->_image.T();
235 if (0 <= l && l < this->_image.T()) L = l+1;
237 blocked_range3d<int> re(l, L, 0, this->_image.Y(), 0, this->_image.X());
243 template <
class TData,
class TReal>
244 struct ConvertToInterpolationCoefficientsTFunc :
public ConvertToInterpolationCoefficientsBase<TData, TReal>
246 ConvertToInterpolationCoefficientsTFunc(GenericImage<TData> &image,
const TReal *z,
int npoles)
248 ConvertToInterpolationCoefficientsBase<TData, TReal>(image, z, npoles)
251 void operator()(
const blocked_range3d<int> &re)
const 253 TData *data =
new TData[this->_image.T()];
254 for (
int k = re.pages().begin(); k != re.pages().end(); ++k)
255 for (
int j = re.rows ().begin(); j != re.rows ().end(); ++j)
256 for (
int i = re.cols ().begin(); i != re.cols ().end(); ++i) {
257 for (
int l = 0; l < this->_image.T(); ++l) {
258 data[l] = this->_image(i, j, k, l);
260 this->Process(data, this->_image.T());
261 for (
int l = 0; l < this->_image.T(); ++l) {
262 this->_image(i, j, k, l) = data[l];
270 blocked_range3d<int> re(0, this->_image.Z(), 0, this->_image.Y(), 0, this->_image.X());
276 template <
class TData,
class TReal>
277 void ConvertToInterpolationCoefficientsX(GenericImage<TData> &image,
const TReal *z,
int npoles)
279 ConvertToInterpolationCoefficientsXFunc<TData, TReal> convert(image, z, npoles);
284 template <
class TData,
class TReal>
285 void ConvertToInterpolationCoefficientsY(GenericImage<TData> &image,
const TReal *z,
int npoles)
287 ConvertToInterpolationCoefficientsYFunc<TData, TReal> convert(image, z, npoles);
292 template <
class TData,
class TReal>
293 void ConvertToInterpolationCoefficientsZ(GenericImage<TData> &image,
const TReal *z,
int npoles)
295 ConvertToInterpolationCoefficientsZFunc<TData, TReal> convert(image, z, npoles);
300 template <
class TData,
class TReal>
301 void ConvertToInterpolationCoefficientsT(GenericImage<TData> &image,
const TReal *z,
int npoles)
303 ConvertToInterpolationCoefficientsTFunc<TData, TReal> convert(image, z, npoles);
308 template <
class TData,
class TReal>
309 void ConvertToInterpolationCoefficients(GenericImage<TData> &image,
const TReal *z,
int npoles)
311 ConvertToInterpolationCoefficientsX(image, z, npoles);
312 ConvertToInterpolationCoefficientsY(image, z, npoles);
313 ConvertToInterpolationCoefficientsZ(image, z, npoles);
314 if (image.TSize() != .0 && image.T() > 1) {
315 ConvertToInterpolationCoefficientsT(image, z, npoles);
320 template <
class TData,
class TReal>
321 void ConvertToInterpolationCoefficientsX(GenericImage<TData> &image,
int l,
const TReal *z,
int npoles)
323 ConvertToInterpolationCoefficientsXFunc<TData, TReal> convert(image, z, npoles);
328 template <
class TData,
class TReal>
329 void ConvertToInterpolationCoefficientsY(GenericImage<TData> &image,
int l,
const TReal *z,
int npoles)
331 ConvertToInterpolationCoefficientsYFunc<TData, TReal> convert(image, z, npoles);
336 template <
class TData,
class TReal>
337 void ConvertToInterpolationCoefficientsZ(GenericImage<TData> &image,
int l,
const TReal *z,
int npoles)
339 ConvertToInterpolationCoefficientsZFunc<TData, TReal> convert(image, z, npoles);
344 template <
class TData,
class TReal>
345 void ConvertToInterpolationCoefficients(GenericImage<TData> &image,
int l,
const TReal *z,
int npoles)
347 ConvertToInterpolationCoefficientsX(image, l, z, npoles);
348 ConvertToInterpolationCoefficientsY(image, l, z, npoles);
349 ConvertToInterpolationCoefficientsZ(image, l, z, npoles);
353 template <
class TData,
class TReal>
354 void ConvertToInterpolationCoefficientsX(GenericImage<TData> &image,
int k,
int l,
const TReal *z,
int npoles)
356 ConvertToInterpolationCoefficientsXFunc<TData, TReal> convert(image, z, npoles);
361 template <
class TData,
class TReal>
362 void ConvertToInterpolationCoefficientsY(GenericImage<TData> &image,
int k,
int l,
const TReal *z,
int npoles)
364 ConvertToInterpolationCoefficientsYFunc<TData, TReal> convert(image, z, npoles);
369 template <
class TData,
class TReal>
370 void ConvertToInterpolationCoefficients(GenericImage<TData> &image,
int k,
int l,
const TReal *z,
int npoles)
372 ConvertToInterpolationCoefficientsX(image, k, l, z, npoles);
373 ConvertToInterpolationCoefficientsY(image, k, l, z, npoles);
378 template <
class TReal>
384 pole[0] = TReal(sqrt(8.0) - 3.0);
388 pole[0] = TReal(sqrt(3.0) - 2.0);
392 pole[0] = TReal(sqrt(664.0 - sqrt(438976.0)) + sqrt(304.0) - 19.0);
393 pole[1] = TReal(sqrt(664.0 + sqrt(438976.0)) - sqrt(304.0) - 19.0);
397 pole[0] = TReal(sqrt(135.0 / 2.0 - sqrt(17745.0 / 4.0)) + sqrt(105.0 / 4.0) - 13.0 / 2.0);
398 pole[1] = TReal(sqrt(135.0 / 2.0 + sqrt(17745.0 / 4.0)) - sqrt(105.0 / 4.0) - 13.0 / 2.0);
401 cerr <<
"SplinePoles: Unsupported spline degree: " << degree << endl;
408 template <
class TData>
411 typename voxel_info<TData>::ScalarType poles[2];
414 ConvertToInterpolationCoefficients(image, k, l, poles, npoles);
419 template <
class TData>
422 typename voxel_info<TData>::ScalarType poles[2];
425 ConvertToInterpolationCoefficients(image, l, poles, npoles);
430 template <
class TData>
433 typename voxel_info<TData>::ScalarType poles[2];
436 ConvertToInterpolationCoefficients(image, poles, npoles);
441 template <
class TData>
449 template <
class TData>
457 template <
class TData>
460 int idx, nbr, i, j, k, l;
461 Queue<int> active, next;
471 for (
int gen = 0; gen < 3; ++gen) {
472 while (!active.empty()) {
473 idx = active.front();
477 TData value = voxel_cast<TData>(0);
479 for (
int nl = l - 1; nl <= l + 1; ++nl)
480 for (
int nk = k - 1; nk <= k + 1; ++nk)
481 for (
int nj = j - 1; nj <= j + 1; ++nj)
482 for (
int ni = i - 1; ni <= i + 1; ++ni) {
484 if (nbr != idx && image.
IsInside(nbr)) {
493 value /=
static_cast<float>(count);
494 image.
Put(idx, value);
498 if (next.empty())
break;
506 #endif // MIRTK_ImageToInterpolationCoefficients_H bool IsBackground(int) const
Whether voxel is within background without index-out-of-bounds check.
void SplinePoles(int degree, TReal pole[2], int &npoles)
Recover spline poles from a lookup table.
int VoxelToIndex(int, int, int=0, int=0) const
Function to convert pixel to index.
const ImageAttributes & Attributes() const
Gets the image attributes.
void Put(int, VoxelType)
Function for pixel put access.
void FillBackgroundBeforeConversionToSplineCoefficients(GenericImage< TData > &image)
Fill background by front propagation of foreground.
bool IsInside(int) const
Whether voxel index is within finite image domain.
bool IsNextToForeground(int) const
Whether at least one neighboring voxel is inside the finite foreground region.
int NumberOfVoxels() const
Returns the total number of voxels.
void ConvertToSplineCoefficients(int degree, GenericImage< TData > &image, int k, int l)
Convert 2D floating point scalar or vector image to spline coefficients.
void ConvertToCubicBSplineCoefficients(GenericImage< TData > &image, int l)
Convert 3D floating point scalar or vector image to cubic spline coefficients.
void IndexToVoxel(int, int &, int &) const
Function to convert index to pixel coordinates.
void parallel_for(const Range &range, const Body &body)
parallel_for dummy template function which executes the body serially