Developer documentation
Version 3.0.3-105-gd3941f44
reslice.h
Go to the documentation of this file.
1/* Copyright (c) 2008-2022 the MRtrix3 contributors.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 *
7 * Covered Software is provided under this License on an "as is"
8 * basis, without warranty of any kind, either expressed, implied, or
9 * statutory, including, without limitation, warranties that the
10 * Covered Software is free of defects, merchantable, fit for a
11 * particular purpose or non-infringing.
12 * See the Mozilla Public License v. 2.0 for more details.
13 *
14 * For more details, see http://www.mrtrix.org/.
15 */
16
17#ifndef __adapter_reslice_h__
18#define __adapter_reslice_h__
19
20#include <type_traits>
21
22#include "image.h"
23#include "transform.h"
24#include "types.h"
25#include "interp/base.h"
26#include "interp/nearest.h"
27
28namespace MR
29{
30 namespace Adapter
31 {
32
33
34
35 namespace
36 {
37 // Partial specialisation for boolean value_type in order to avoid compiler
38 // warning regarding use of multiplication when assigning to a boolean
39 template <typename value_type>
41 inline normalise (const default_type sum, const default_type norm)
42 {
43 return ((sum*norm) >= 0.5) ? true : false;
44 }
45
46 // Partial specialisation to invoke round-to-nearest when taking an average of integers
47 template <typename value_type>
49 inline normalise (const default_type sum, const default_type norm)
50 {
51 return value_type(std::round (sum*norm));
52 }
53
54 template <typename value_type>
56 inline normalise (const default_type sum, const default_type norm)
57 {
58 return (sum * norm);
59 }
60 }
61
62
63
64 extern const transform_type NoTransform;
65 extern const vector<uint32_t> AutoOverSample;
66
68 // @{
69
71
109 template <template <class ImageType> class Interpolator, class ImageType>
110 class Reslice :
111 public ImageBase<Reslice<Interpolator,ImageType>,typename ImageType::value_type>
113 public:
114
115 using value_type = typename ImageType::value_type;
116
117
118 template <class HeaderType>
119 Reslice (const ImageType& original,
120 const HeaderType& reference,
121 const transform_type& transform = NoTransform,
122 const vector<uint32_t>& oversample = AutoOverSample,
123 const value_type value_when_out_of_bounds = Interp::Base<ImageType>::default_out_of_bounds_value()) :
124 interp (original, value_when_out_of_bounds),
125 x { 0, 0, 0 },
126 dim { reference.size(0), reference.size(1), reference.size(2) },
127 vox { reference.spacing(0), reference.spacing(1), reference.spacing(2) },
128 transform_ (reference.transform()),
129 direct_transform (Transform(original).scanner2voxel * transform * Transform(reference).voxel2scanner) {
130 using namespace Eigen;
131 assert (ndim() >= 3);
132
133 const bool is_nearest = std::is_same<typename Interp::Nearest<ImageType>, decltype(interp)>::value;
134
135 if (oversample.size()) { // oversample explicitly set
136 assert (oversample.size() == 3);
137 if (oversample[0] < 1 || oversample[1] < 1 || oversample[2] < 1)
138 throw Exception ("oversample factors must be greater than zero");
139 if (is_nearest && (oversample[0] != 1 || oversample[1] != 1 || oversample[2] != 1)) {
140 WARN("oversampling factors ignored for nearest neighbour interpolation");
141 OS[0] = OS[1] = OS[2] = 1;
142 }
143 else {
144 OS[0] = oversample[0]; OS[1] = oversample[1]; OS[2] = oversample[2];
145 }
146 }
147 else { // oversample is default
148 if (is_nearest) {
149 OS[0] = OS[1] = OS[2] = 1;
150 }
151 else {
152 Vector3d y = direct_transform * Vector3d (0.0, 0.0, 0.0);
153 Vector3d x0 = direct_transform * Vector3d (1.0, 0.0, 0.0);
154 OS[0] = std::ceil ((1.0-std::numeric_limits<default_type>::epsilon()) * (y-x0).norm());
155 x0 = direct_transform * Vector3d (0.0, 1.0, 0.0);
156 OS[1] = std::ceil ((1.0-std::numeric_limits<default_type>::epsilon()) * (y-x0).norm());
157 x0 = direct_transform * Vector3d (0.0, 0.0, 1.0);
158 OS[2] = std::ceil ((1.0-std::numeric_limits<default_type>::epsilon()) * (y-x0).norm());
159 }
160 }
161
162 if (OS[0] * OS[1] * OS[2] > 1) {
163 INFO ("using oversampling factors [ " + str (OS[0]) + " " + str (OS[1]) + " " + str (OS[2]) + " ]");
164 oversampling = true;
165 norm = 1.0;
166 for (size_t i = 0; i < 3; ++i) {
167 inc[i] = 1.0/default_type (OS[i]);
168 from[i] = 0.5* (inc[i]-1.0);
169 norm *= OS[i];
170 }
171 norm = 1.0 / norm;
172 }
173 else oversampling = false;
174 }
175
176
177 size_t ndim () const { return interp.ndim(); }
178 bool valid () const { return interp.valid(); }
179 int size (size_t axis) const { return axis < 3 ? dim[axis]: interp.size (axis); }
180 default_type spacing (size_t axis) const { return axis < 3 ? vox[axis] : interp.spacing (axis); }
181 const transform_type& transform () const { return transform_; }
182 const std::string& name () const { return interp.name(); }
183
184 ssize_t stride (size_t axis) const {
185 return interp.stride (axis);
186 }
187
188 void reset () {
189 x[0] = x[1] = x[2] = 0;
190 for (size_t n = 3; n < interp.ndim(); ++n)
191 interp.index(n) = 0;
192 }
193
194 value_type value () {
195 using namespace Eigen;
196 if (oversampling) {
197 Vector3d d (x[0]+from[0], x[1]+from[1], x[2]+from[2]);
198 default_type sum (0.0);
199 Vector3d s;
200 for (uint32_t z = 0; z < OS[2]; ++z) {
201 s[2] = d[2] + z*inc[2];
202 for (uint32_t y = 0; y < OS[1]; ++y) {
203 s[1] = d[1] + y*inc[1];
204 for (uint32_t x = 0; x < OS[0]; ++x) {
205 s[0] = d[0] + x*inc[0];
206 if (interp.voxel (direct_transform * s))
207 sum += interp.value();
208 }
209 }
210 }
211 return normalise<value_type> (sum, norm);
212 }
213 interp.voxel (direct_transform * Vector3d (x[0], x[1], x[2]));
214 return interp.value();
215 }
216
217 ssize_t get_index (size_t axis) const { return axis < 3 ? x[axis] : interp.index(axis); }
218 void move_index (size_t axis, ssize_t increment) {
219 if (axis < 3) x[axis] += increment;
220 else interp.index(axis) += increment;
221 }
222
223 private:
224 Interpolator<ImageType> interp;
225 ssize_t x[3];
226 const ssize_t dim[3];
227 const default_type vox[3];
228 bool oversampling;
229 uint32_t OS[3];
230 default_type from[3], inc[3];
231 default_type norm;
232 const transform_type transform_, direct_transform;
233
234 };
235
237
238 }
239}
240
241#endif
242
243
244
245
an Image providing interpolated values from another Image
Definition: reslice.h:112
This class defines the interface for classes that perform image interpolation.
Definition: base.h:70
#define WARN(msg)
Definition: exception.h:73
#define INFO(msg)
Definition: exception.h:74
constexpr I ceil(const T x)
template function with cast to different type
Definition: math.h:86
constexpr I round(const T x)
Definition: math.h:64
VectorType::Scalar value(const VectorType &coefs, typename VectorType::Scalar cos_elevation, typename VectorType::Scalar cos_azimuth, typename VectorType::Scalar sin_azimuth, int lmax)
Definition: SH.h:233
const vector< uint32_t > AutoOverSample
const transform_type NoTransform
MR::default_type value_type
Definition: typedefs.h:33
Definition: base.h:24
double default_type
the default type used throughout MRtrix
Definition: types.h:228
std::string str(const T &value, int precision=0)
Definition: mrtrix.h:247
Eigen::Transform< default_type, 3, Eigen::AffineCompact > transform_type
the type for the affine transform of an image:
Definition: types.h:234
int axis
#define MEMALIGN(...)
Definition: types.h:185