Developer documentation
Version 3.0.3-105-gd3941f44
noise_estimator.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 __dwi_noise_estimator_h__
18#define __dwi_noise_estimator_h__
19
20#include "image.h"
21#include "dwi/gradient.h"
22#include "math/least_squares.h"
23#include "math/SH.h"
25
26
27namespace MR {
28 namespace DWI {
29
30 namespace {
31
32 template <class InputImageType, class OutputImageType, class MatrixType>
33 class NoiseEstimatorFunctor { MEMALIGN(NoiseEstimatorFunctor<InputImageType,OutputImageType,MatrixType>)
34 public:
35
36 NoiseEstimatorFunctor (const MatrixType& SH2amp_mapping, int axis, InputImageType& dwi, OutputImageType& noise) :
37 dwi (dwi),
38 noise (noise),
39 H (SH2amp_mapping * Math::pinv (SH2amp_mapping)),
40 S (H.cols(), dwi.size (axis)),
41 R (S.cols(), S.rows()),
42 leverage (H.rows()),
43 axis (axis) {
44 for (ssize_t n = 0; n < leverage.size(); ++n)
45 leverage[n] = H(n,n) < 1.0 ? 1.0 / std::sqrt (1.0 - H(n,n)) : 1.0;
46 }
47
48 void operator () (const Iterator& pos) {
49 assign_pos_of (pos).to (dwi, noise);
50 for (auto l = Loop (axis) (dwi); l; ++l)
51 for (auto l2 = Loop (3) (dwi); l2; ++l2)
52 S(dwi.index(3), dwi.index(axis)) = dwi.value();
53
54 R.noalias() = H.selfadjointView<Eigen::Lower>() * S - S;
55
56 for (auto l = Loop (axis) (noise); l; ++l) {
57 R.col (noise.index (axis)).array() *= leverage.array();
58 noise.value() = scale_estimator (R.col (noise.index (axis)));
59 }
60 }
61
62 protected:
63 InputImageType dwi;
64 OutputImageType noise;
65 Eigen::MatrixXd H, S, R;
66 Eigen::VectorXd leverage;
67 Math::Sn_scale_estimator<default_type> scale_estimator;
68 int axis;
69 };
70 }
71
72
73
74
75 template <class InputImageType, class OutputImageType, class MatrixType>
76 inline void estimate_noise (InputImageType& dwi, OutputImageType& noise, const MatrixType& SH2amp_mapping) {
77 auto loop = ThreadedLoop ("estimating noise level", dwi, 0, 3);
78 NoiseEstimatorFunctor<InputImageType,OutputImageType,MatrixType> functor (SH2amp_mapping, loop.inner_axes[0], dwi, noise);
79 loop.run_outer (functor);
80 }
81
82
83 }
84}
85
86#endif
87
FORCE_INLINE LoopAlongAxes Loop()
Definition: loop.h:419
Eigen::Matrix< typename MatrixType::Scalar, Eigen::Dynamic, Eigen::Dynamic > pinv(const MatrixType &M)
return Moore-Penrose pseudo-inverse of M
Definition: least_squares.h:39
void estimate_noise(InputImageType &dwi, OutputImageType &noise, const MatrixType &SH2amp_mapping)
Definition: base.h:24
ThreadedLoopRunOuter< decltype(Loop(vector< size_t >()))> ThreadedLoop(const HeaderType &source, const vector< size_t > &outer_axes, const vector< size_t > &inner_axes)
Multi-threaded loop object.
InputImageType dwi
Eigen::MatrixXd S
Eigen::MatrixXd R
Eigen::VectorXd leverage
OutputImageType noise
int axis
Eigen::MatrixXd H
Math::Sn_scale_estimator< default_type > scale_estimator
#define MEMALIGN(...)
Definition: types.h:185
std::remove_reference< Functor >::type & functor
Definition: thread.h:215