MorphoGraphX  2.0-1-227
StackProcessMorphology.hpp
Go to the documentation of this file.
1 //
2 // This file is part of MorphoGraphX - http://www.MorphoGraphX.org
3 // Copyright (C) 2012-2015 Richard S. Smith and collaborators.
4 //
5 // If you use MorphoGraphX in your work, please cite:
6 // http://dx.doi.org/10.7554/eLife.05864
7 //
8 // MorphoGraphX is free software, and is licensed under under the terms of the
9 // GNU General (GPL) Public License version 2.0, http://www.gnu.org/licenses.
10 //
11 #ifndef STACKPROCESSMORPHOLOGY_HPP
12 #define STACKPROCESSMORPHOLOGY_HPP
13 
14 #include <Process.hpp>
15 
16 namespace mgx
17 {
20 
25  class mgxBase_EXPORT EdgeDetectProcess : public Process
26  {
27  public:
28  EdgeDetectProcess(const Process& process) : Process(process)
29  {
30  setName("Stack/Morphology/Edge Detect");
31  setDesc("Do a multipass edge detection in Z direction.\n"
32  "Stack is turned into a mask (0 or fill value)");
33  setIcon(QIcon(":/images/EdgeDetect.png"));
34 
35  addParm("Threshold","Values of signal that should not belong to surface.","10000.0");
36  addParm("Multiplier","Multiplicative factor for the threshold.","2.0");
37  addParm("Adapt Factor","Adaptative factor for threshold.","0.3");
38  addParm("Fill Value","Value to fill the mask with.","30000");
39  }
40 
41  bool run()
42  {
43  if(!checkState().store(STORE_NON_EMPTY | STORE_NON_LABEL))
44  return false;
45  Stack* stack = currentStack();
46  Store* store = stack->currentStore();
47  Store* work = stack->work();
48  bool res = run(store, work, parm("Threshold").toFloat(), parm("Multiplier").toFloat(),
49  parm("Adapt Factor").toFloat(), parm("Fill Value").toUInt());
50  if(res) {
51  store->hide();
52  work->show();
53  }
54  return res;
55  }
56 
57  bool run(Store* input, Store* output, float threshold, float multiplier,
58  float factor, uint fillValue);
59 
60  };
61 
73  class mgxBase_EXPORT DilateStack : public Process
74  {
75  public:
76  DilateStack(const Process& process) : Process(process)
77  {
78  setName("Stack/Morphology/Dilate");
79  setDesc("Morphological dilation (max filter) on stack");
80  setIcon(QIcon(":/images/Dilate.png"));
81 
82  addParm("X Radius","X Radius","1");
83  addParm("Y Radius","Y Radius","1");
84  addParm("Z Radius","Z Radius","1");
85  addParm("Auto-Resize","Auto-Resize","No",booleanChoice());
86  addParm("Round Nhbd","Use a round (Ellipsoidal) neighborhood","No",booleanChoice());
87  }
88 
89  bool run()
90  {
91  if(!checkState().store(STORE_NON_EMPTY))
92  return false;
93  Stack* s = currentStack();
94  Store* input = s->currentStore();
95  Store* output = s->work();
96  bool res = run(s, input, output, parm("X Radius").toUInt(), parm("Y Radius").toUInt(), parm("Z Radius").toUInt(),
97  stringToBool(parm("Auto-Resize")), stringToBool(parm("Round Nhbd")));
98  if(res) {
99  input->hide();
100  output->show();
101  }
102  return res;
103  }
104  bool run(Stack* stack, const Store* input, Store* output, uint xradius,
105  uint yradius, uint zradius, bool auto_resize = true, bool roundNhbd = false);
106 
107  };
108 
120  class mgxBase_EXPORT ErodeStack : public Process
121  {
122  public:
123  ErodeStack(const Process& process) : Process(process)
124  {
125  setName("Stack/Morphology/Erode");
126  setDesc("Morphological erosion on stack");
127  setIcon(QIcon(":/images/Erode.png"));
128 
129  addParm("X Radius","X Radius","1");
130  addParm("Y Radius","Y Radius","1");
131  addParm("Z Radius","Z Radius","1");
132  addParm("Auto-Resize","Auto-Resize","No",booleanChoice());
133  addParm("Round Nhbd","Use a round (Ellipsoidal) neighborhood","No",booleanChoice());
134  }
135 
136  bool run()
137  {
138  if(!checkState().store(STORE_NON_EMPTY))
139  return false;
140  Stack* s = currentStack();
141  Store* input = s->currentStore();
142  Store* output = s->work();
143  bool res = run(s, input, output, parm("X Radius").toUInt(), parm("Y Radius").toUInt(), parm("Z Radius").toUInt(),
144  stringToBool(parm("Auto-Resize")), stringToBool(parm("Round Nhbd")));
145  if(res) {
146  input->hide();
147  output->show();
148  }
149  return res;
150  }
151  bool run(Stack* stack, const Store* input, Store* output, uint xradius,
152  uint yradius, uint zradius, bool auto_resize = true, bool roundNhbd = false);
153 
154  };
155 
165  class mgxBase_EXPORT ClosingStack : public Process
166  {
167  public:
168  ClosingStack(const Process& process) : Process(process)
169  {
170  setName("Stack/Morphology/Closing");
171  setDesc("Morphological closure (i.e. dilatation followed erosion) on stack");
172  setIcon(QIcon(":/images/Closing.png"));
173 
174  addParm("X Radius","X Radius","1");
175  addParm("Y Radius","Y Radius","1");
176  addParm("Z Radius","Z Radius","1");
177  addParm("Round Nhbd","Use a round (Ellipsoidal) neighborhood","No",booleanChoice());
178  }
179 
180  bool run()
181  {
182  if(!checkState().store(STORE_NON_EMPTY))
183  return false;
184  Stack* s = currentStack();
185  Store* input = s->currentStore();
186  Store* output = s->work();
187  bool res = run(s, input, output, parm("X Radius").toUInt(), parm("Y Radius").toUInt(),
188  parm("Z Radius").toUInt(), stringToBool(parm("Round Nhbd")));
189  if(res) {
190  input->hide();
191  output->show();
192  }
193  return res;
194  }
195  bool run(Stack* stack, const Store* input, Store* output,
196  uint xradius, uint yradius, uint zradius, bool roundNhbd);
197 
198  };
199 
210  class mgxBase_EXPORT OpeningStack : public Process
211  {
212  public:
213  OpeningStack(const Process& process) : Process(process)
214  {
215  setName("Stack/Morphology/Opening");
216  setDesc("Morphological opening (i.e. erosion followed dilatation) on stack");
217  setIcon(QIcon(":/images/Opening.png"));
218 
219  addParm("X Radius","X Radius","5");
220  addParm("Y Radius","Y Radius","5");
221  addParm("Z Radius","Z Radius","5");
222  addParm("Round Nhbd","Use a round (Ellipsoidal) neighborhood","No",booleanChoice());
223  }
224 
225  bool run()
226  {
227  if(!checkState().store(STORE_NON_EMPTY))
228  return false;
229  Stack* s = currentStack();
230  Store* input = s->currentStore();
231  Store* output = s->work();
232  bool res = run(s, input, output, parm("X Radius").toUInt(), parm("Y Radius").toUInt(),
233  parm("Z Radius").toUInt(), stringToBool(parm("Round Nhbd")));
234  if(res) {
235  input->hide();
236  output->show();
237  }
238  return res;
239  }
240  bool run(Stack* stack, const Store* input, Store* output, uint xradius,
241  uint yradius, uint zradius, bool roundNhbd);
242 
243  };
244 
245  class mgxBase_EXPORT FillHolesProcess : public Process
246  {
247  public:
248  FillHolesProcess(const Process& process) : Process(process)
249  {
250  setName("Stack/Morphology/Fill Holes");
251  setDesc("Fill holes in stack.\n"
252  "Use after Edge Detect.");
253  setIcon(QIcon(":/images/FillHoles.png"));
254 
255  addParm("X Radius","X Radius of hole","10");
256  addParm("Y Radius","Y Radius of hole","10");
257  addParm("Threshold","Minimal signal value to fill the hole.","10000");
258  addParm("Depth","Depth, when set it uses closest pixel at least this much higher within the radius.","0");
259  addParm("Fill Value","Filling value. Usually same as Edge Detect.","30000");
260  }
261 
262  bool run()
263  {
264  if(!checkState().store(STORE_NON_EMPTY | STORE_NON_LABEL))
265  return false;
266  Stack* s = currentStack();
267  Store* input = s->currentStore();
268  Store* output = s->work();
269  bool res = run(input->data(), output->data(), Point3i(s->size()), parm("X Radius").toInt(), parm("Y Radius").toInt(),
270  parm("Threshold").toInt(), parm("Depth").toInt(), parm("Fill Value").toInt());
271  if(res) {
272  output->copyMetaData(input);
273  output->changed();
274  input->hide();
275  output->show();
276  }
277  return res;
278  }
279  bool run(const HVecUS &input, HVecUS &output, const Point3i &size,
280  int xradius, int yradius, int threshold, int depth, int fillValue);
281 
282  };
283 
293  class mgxBase_EXPORT OpenStackLabel : public Process
294  {
295  public:
296  OpenStackLabel(const Process& process) : Process(process)
297  {
298  setName("Stack/Morphology/Open by label");
299  setDesc("Morphological opening on a labeled stack");
300  setIcon(QIcon(":/images/Opening.png"));
301 
302  addParm("X Radius","X Radius","1");
303  addParm("Y Radius","Y Radius","1");
304  addParm("Z Radius","Z Radius","1");
305  addParm("Round Nhbd","Use a round (Ellipsoidal) neighborhood","No",booleanChoice());
306  }
307 
308  bool run()
309  {
310  if(!checkState().store(STORE_NON_EMPTY | STORE_LABEL))
311  return false;
312  Stack* s = currentStack();
313  Store* input = s->currentStore();
314  Store* output = s->work();
315  bool res = run(s, input, output,
316  parm("X Radius").toUInt(), parm("X Radius").toUInt(), parm("X Radius").toUInt(), stringToBool(parm("Round Nhbd")));
317  if(res) {
318  input->hide();
319  output->show();
320  }
321  return res;
322  }
323  bool run(Stack* stack, const Store* input, Store* output,
324  uint xradius, uint yradius, uint zradius, bool roundNhbd);
325 
326  };
327 
339  class mgxBase_EXPORT CloseStackLabel : public Process
340  {
341  public:
342  CloseStackLabel(const Process& process) : Process(process)
343  {
344  setName("Stack/Morphology/Close by label");
345  setDesc("Morphological closure on a labeled stack");
346  setIcon(QIcon(":/images/Closing.png"));
347 
348  addParm("X Radius","X Radius","1");
349  addParm("Y Radius","Y Radius","1");
350  addParm("Z Radius","Z Radius","1");
351  addParm("Round Nhbd","Use a round (Ellipsoidal) neighborhood","No",booleanChoice()); // 3
352  }
353 
354  bool run()
355  {
356  if(!checkState().store(STORE_NON_EMPTY | STORE_LABEL))
357  return false;
358  Stack* s = currentStack();
359  Store* input = s->currentStore();
360  Store* output = s->work();
361  bool res = run(s, input, output,
362  parm("X Radius").toUInt(), parm("Y Radius").toUInt(), parm("Z Radius").toUInt(), stringToBool(parm("Round Nhbd")));
363  if(res) {
364  input->hide();
365  output->show();
366  }
367  return res;
368  }
369  bool run(Stack* stack, const Store* input, Store* output,
370  uint xradius, uint yradius, uint zradius, bool roundNhbd);
371 
372  };
373 
390  class mgxBase_EXPORT ApplyMaskToStack : public Process
391  {
392  public:
393  ApplyMaskToStack(const Process& process) : Process(process)
394  {
395  setName("Stack/Morphology/Apply Mask to Stack");
396  setDesc("Apply the work mask to the main replacing work");
397  setIcon(QIcon(":/images/Mask.png"));
398 
399  addParm("Mode","Mode","Normal", QStringList() << "Normal" << "Invert" << "Combine");
400  addParm("Threshold","Threshold","0");
401  }
402 
403  bool run()
404  {
405  if(!checkState().store(STORE_NON_EMPTY))
406  return false;
407  Stack* stack = currentStack();
408  Store* input = stack->main();
409  Store* output = stack->work();
410  bool res = run(stack, input, output, parm("Mode"), parm("Threshold").toUInt());
411  if(res) {
412  input->hide();
413  output->show();
414  }
415  return res;
416  }
417  bool run(Stack* stack, const Store* input, Store* output,
418  const QString& mode, uint threshold);
419 
420  };
421 
433  class mgxBase_EXPORT ApplyMaskLabels : public Process
434  {
435  public:
436  ApplyMaskLabels(const Process& process) : Process(process)
437  {
438  setName("Stack/Morphology/Apply Mask to Labels");
439  setDesc("Apply mask in work stack to labels in main stack, replacing work");
440  setIcon(QIcon(":/images/MaskLabels.png"));
441 
442  addParm("Invert","Invert","No",booleanChoice());
443  addParm("Threshold","Threshold","1");
444  }
445 
446  bool run()
447  {
448  if(!checkState().store(STORE_NON_EMPTY))
449  return false;
450  Stack* stack = currentStack();
451  Store* input = stack->main();
452  Store* output = stack->work();
453  bool res = run(stack, input, output, parm("Invert").toUInt(), stringToBool(parm("Threshold")));
454  if(res) {
455  input->hide();
456  output->show();
457  output->setLabels(true);
458  }
459  return res;
460  }
461  bool run(Stack* stack, const Store* input, Store* output, bool invert, uint threshold);
462 
463  };
464 
471  class mgxBase_EXPORT TrimStackToBezier : public Process
472  {
473  public:
474  TrimStackToBezier(const Process& process) : Process(process)
475  {
476  setName("Stack/Morphology/Trim Stack to Bezier");
477  setDesc("Trim a stack by deleting all voxels over a specified distance from a Bezier");
478  setIcon(QIcon(":/images/ClipStack.png"));
479 
480  addParm("Distance", "Distance from Bezier to keep voxels in um", "20.0");
481  addParm("Points", "Points along the Bezier for distance calculation", "50");
482  addParm("Mask", "Create a mask instead", "No", booleanChoice());
483  addParm("Fill Value", "Voxel value for filling when creating mask", "65535");
484  addParm("Axes", "Axes to use to generate test points", "u", QStringList() << "u" << "v" << "uv");
485  }
486 
487  bool run()
488  {
489  Stack* stack = currentStack();
490  Store* input = stack->main();
491  Store* output = stack->work();
492  bool res = run(stack, input, output, parm("Distance").toDouble(), parm("Points").toInt(),
493  stringToBool(parm("Mask")), parm("Fill Value").toInt(), parm("Axes"));
494  if(res) {
495  input->hide();
496  output->show();
497  }
498  return res;
499  }
500  bool run(Stack* stack, const Store* input, Store* output, double distance, int points,
501  bool mask = false, int fillValue = 65535, QString axes = "u");
502 
503  };
505 }
506 
507 #endif
mgx::uint
unsigned int uint
Definition: Geometry.hpp:41
mgx::ApplyMaskToStack::ApplyMaskToStack
ApplyMaskToStack(const Process &process)
Definition: StackProcessMorphology.hpp:393
Process.hpp
mgx::ClosingStack
Definition: StackProcessMorphology.hpp:165
mgx::EdgeDetectProcess::EdgeDetectProcess
EdgeDetectProcess(const Process &process)
Definition: StackProcessMorphology.hpp:28
mgx::Stack::size
Point3u size() const
Returns the size, in voxels, of the stores.
Definition: Stack.hpp:133
mgx::DilateStack::run
bool run()
Runs the process.
Definition: StackProcessMorphology.hpp:89
mgx::FillHolesProcess::run
bool run()
Runs the process.
Definition: StackProcessMorphology.hpp:262
mgx::ApplyMaskLabels::run
bool run()
Runs the process.
Definition: StackProcessMorphology.hpp:446
mgx::DilateStack::DilateStack
DilateStack(const Process &process)
Definition: StackProcessMorphology.hpp:76
mgx::Stack::work
const Store * work() const
Access the work store.
Definition: Stack.hpp:101
mgx::ErodeStack
Definition: StackProcessMorphology.hpp:120
mgx::TrimStackToBezier::run
bool run()
Runs the process.
Definition: StackProcessMorphology.hpp:487
mgx::OpeningStack
Definition: StackProcessMorphology.hpp:210
mgx::ApplyMaskToStack
Definition: StackProcessMorphology.hpp:390
mgx::FillHolesProcess::FillHolesProcess
FillHolesProcess(const Process &process)
Definition: StackProcessMorphology.hpp:248
mgx::Stack::currentStore
const Store * currentStore() const
Returns the current store.
Definition: Stack.hpp:120
mgx::HVecUS
thrust::host_vector< ushort > HVecUS
Definition: CudaExport.hpp:23
mgx::Stack::main
const Store * main() const
Access the main store.
Definition: Stack.hpp:82
mgx::Stack
Definition: Stack.hpp:33
mgx::FillHolesProcess
Definition: StackProcessMorphology.hpp:245
mgx
Distributed matrix library.
Definition: Assert.hpp:26
mgx::TrimStackToBezier::TrimStackToBezier
TrimStackToBezier(const Process &process)
Definition: StackProcessMorphology.hpp:474
mgx::Store::hide
void hide()
Ask the user interface to hide this store.
Definition: Store.hpp:167
mgx::ApplyMaskLabels
Definition: StackProcessMorphology.hpp:433
mgx::CloseStackLabel::CloseStackLabel
CloseStackLabel(const Process &process)
Definition: StackProcessMorphology.hpp:342
mgx::Process
Definition: Process.hpp:219
mgx::DilateStack
Definition: StackProcessMorphology.hpp:73
mgx::stringToBool
mgx_EXPORT bool stringToBool(const QString &string)
Helper function converting a string into a boolean.
mgx::ClosingStack::run
bool run()
Runs the process.
Definition: StackProcessMorphology.hpp:180
mgx::TrimStackToBezier
Definition: StackProcessMorphology.hpp:471
mgx::Store::copyMetaData
void copyMetaData(const Store *other)
Copy the metadata from another store.
mgx::Store::show
void show()
Ask the user interface to show this store.
Definition: Store.hpp:162
mgx::OpenStackLabel
Definition: StackProcessMorphology.hpp:293
mgx::EdgeDetectProcess
Definition: StackProcessMorphology.hpp:25
mgx::Store::changed
void changed()
A process that changes the 3D data needs to call this method.
mgx::Store::setLabels
void setLabels(bool val)
Change the interpretation of the volume as labels.
Definition: Store.hpp:75
mgx::Vector< 3, int >
mgx::OpeningStack::OpeningStack
OpeningStack(const Process &process)
Definition: StackProcessMorphology.hpp:213
mgx::CloseStackLabel::run
bool run()
Runs the process.
Definition: StackProcessMorphology.hpp:354
mgx::ClosingStack::ClosingStack
ClosingStack(const Process &process)
Definition: StackProcessMorphology.hpp:168
mgx::OpenStackLabel::OpenStackLabel
OpenStackLabel(const Process &process)
Definition: StackProcessMorphology.hpp:296
mgx::ErodeStack::ErodeStack
ErodeStack(const Process &process)
Definition: StackProcessMorphology.hpp:123
mgx::CloseStackLabel
Definition: StackProcessMorphology.hpp:339
mgx::OpenStackLabel::run
bool run()
Runs the process.
Definition: StackProcessMorphology.hpp:308
mgx::Store::data
HVecUS & data()
Actual 3D data store linearly in a host vector.
Definition: Store.hpp:58
mgx::ErodeStack::run
bool run()
Runs the process.
Definition: StackProcessMorphology.hpp:136
mgx::ApplyMaskToStack::run
bool run()
Runs the process.
Definition: StackProcessMorphology.hpp:403
mgx::ApplyMaskLabels::ApplyMaskLabels
ApplyMaskLabels(const Process &process)
Definition: StackProcessMorphology.hpp:436
mgx::EdgeDetectProcess::run
bool run()
Runs the process.
Definition: StackProcessMorphology.hpp:41
mgx::Store
Definition: Store.hpp:33
mgx::OpeningStack::run
bool run()
Runs the process.
Definition: StackProcessMorphology.hpp:225