Developer documentation
Version 3.0.3-105-gd3941f44
mask_clean.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 __filter_mask_clean_h__
18#define __filter_mask_clean_h__
19
20#include "progressbar.h"
21#include "memory.h"
22#include "image.h"
23#include "image_helpers.h"
24#include "algo/copy.h"
25#include "algo/loop.h"
26#include "filter/base.h"
27#include "filter/erode.h"
29#include "filter/dilate.h"
30
31
32
33namespace MR
34{
35 namespace Filter
36 {
37
42
56 class MaskClean : public Base { MEMALIGN(MaskClean)
57
58 public:
59 template <class HeaderType>
60 MaskClean (const HeaderType& in) :
61 Base (in),
62 scale (2)
63 {
64 check_3D_nonunity (in);
66 }
67
68 template <class HeaderType>
69 MaskClean (const HeaderType& in, const std::string& message) :
70 Base (in, message),
71 scale (2)
72 {
73 check_3D_nonunity (in);
75 }
76
77 template <class InputImageType, class OutputImageType>
78 void operator() (InputImageType& input, OutputImageType& output)
79 {
80
81 std::unique_ptr<ProgressBar> progress (message.size() ? new ProgressBar (message) : nullptr);
82
83 if (progress)
84 ++(*progress);
85
86 auto temp_in = Image<bool>::scratch (input, "temporary input mask");
87 for (auto l = Loop (0,3) (input, temp_in); l; ++l)
88 temp_in.value() = input.value();
89
90 auto temp_out = Image<bool>::scratch (input, "temporary output mask");
91
92 single_pass(temp_in, temp_out);
93
94 if (progress)
95 ++(*progress);
96
97 // Perform extra passes until converged.
98 while (differ(temp_in, temp_out)) {
99
100 for (auto l = Loop (0,3) (temp_out, temp_in); l; ++l)
101 temp_in.value() = temp_out.value();
102
103 single_pass(temp_in, temp_out);
104
105 if (progress)
106 ++(*progress);
107
108 }
109
110 for (auto l = Loop (0,3) (temp_out, output); l; ++l)
111 output.value() = temp_out.value();
112
113 }
114
115
116 void set_scale (unsigned int scales)
117 {
118 scale = scales;
119 }
120
121
122 protected:
123
124 // Single pass over all scales + retaining the largest connected component to clean up remains.
125 template <class InputImageType, class OutputImageType>
126 void single_pass (InputImageType& input, OutputImageType& output)
127 {
128 auto temp_image = Image<bool>::scratch (input, "temporary mask");
129 for (auto l = Loop (0,3) (input, temp_image); l; ++l)
130 temp_image.value() = input.value();
131
132 for (unsigned int s = scale; s > 0; --s)
133 single_scale(temp_image, temp_image, s);
134
135 ConnectedComponents connected_filter (temp_image);
136 connected_filter.set_largest_only (true);
137 connected_filter (temp_image, temp_image);
138
139 for (auto l = Loop (0,3) (temp_image, output); l; ++l)
140 output.value() = temp_image.value();
141 }
142
143 // Core operation for a single specific scale s.
144 template <class InputImageType, class OutputImageType>
145 void single_scale (InputImageType& input, OutputImageType& output, const int ss)
146 {
147 auto del_image = Image<bool>::scratch (input, "deletion mask");
148 Erode erosion_filter (input);
149 erosion_filter.set_npass(ss);
150 erosion_filter (input, del_image);
151
152 auto largest_image = Image<bool>::scratch (input, "largest component");
153 ConnectedComponents connected_filter (del_image);
154 connected_filter.set_largest_only (true);
155 connected_filter (del_image, largest_image);
156
157 for (auto l = Loop (0,3) (del_image, largest_image); l; ++l)
158 if (largest_image.value())
159 del_image.value() = 0;
160
161 Dilate dilation_filter (del_image);
162 dilation_filter.set_npass(ss+1);
163 dilation_filter (del_image, del_image);
164
165 for (auto l = Loop (0,3) (input, largest_image, del_image); l; ++l)
166 largest_image.value() = del_image.value() ? 0 : input.value();
167
168 for (auto l = Loop (0,3) (largest_image, output); l; ++l)
169 output.value() = largest_image.value();
170 }
171
172 template <class InputImageType, class OutputImageType>
173 bool differ (InputImageType& ima, OutputImageType& imb)
174 {
175 for (auto l = Loop (0,3) (ima, imb); l; ++l)
176 if (ima.value() != imb.value())
177 return true;
178
179 return false;
180 }
181
182 unsigned int scale;
183 };
185 }
186}
187
188
189
190
191#endif
static constexpr uint8_t Bit
Definition: datatype.h:142
std::string message
Definition: base.h:66
a filter to dilate a mask
Definition: dilate.h:49
a filter to erode a mask
Definition: erode.h:49
a filter to clean up masks typically output by DWIBrainMask filter
Definition: mask_clean.h:56
void single_pass(InputImageType &input, OutputImageType &output)
Definition: mask_clean.h:126
bool differ(InputImageType &ima, OutputImageType &imb)
Definition: mask_clean.h:173
unsigned int scale
Definition: mask_clean.h:182
void single_scale(InputImageType &input, OutputImageType &output, const int ss)
Definition: mask_clean.h:145
DataType datatype_
the type of the data as stored on file
Definition: header.h:370
static Image scratch(const Header &template_header, const std::string &label="scratch image")
Definition: image.h:195
implements a progress meter to provide feedback to the user
Definition: progressbar.h:58
FORCE_INLINE LoopAlongAxes Loop()
Definition: loop.h:419
Definition: base.h:24