11 #ifndef STACKPROCESSMORPHOLOGY_HPP
12 #define STACKPROCESSMORPHOLOGY_HPP
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"));
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");
43 if(!checkState().store(STORE_NON_EMPTY | STORE_NON_LABEL))
45 Stack* stack = currentStack();
48 bool res = run(store, work, parm(
"Threshold").toFloat(), parm(
"Multiplier").toFloat(),
49 parm(
"Adapt Factor").toFloat(), parm(
"Fill Value").toUInt());
57 bool run(
Store* input,
Store* output,
float threshold,
float multiplier,
58 float factor,
uint fillValue);
78 setName(
"Stack/Morphology/Dilate");
79 setDesc(
"Morphological dilation (max filter) on stack");
80 setIcon(QIcon(
":/images/Dilate.png"));
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());
91 if(!checkState().store(STORE_NON_EMPTY))
93 Stack* s = currentStack();
96 bool res = run(s, input, output, parm(
"X Radius").toUInt(), parm(
"Y Radius").toUInt(), parm(
"Z Radius").toUInt(),
105 uint yradius,
uint zradius,
bool auto_resize =
true,
bool roundNhbd =
false);
125 setName(
"Stack/Morphology/Erode");
126 setDesc(
"Morphological erosion on stack");
127 setIcon(QIcon(
":/images/Erode.png"));
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());
138 if(!checkState().store(STORE_NON_EMPTY))
140 Stack* s = currentStack();
143 bool res = run(s, input, output, parm(
"X Radius").toUInt(), parm(
"Y Radius").toUInt(), parm(
"Z Radius").toUInt(),
152 uint yradius,
uint zradius,
bool auto_resize =
true,
bool roundNhbd =
false);
170 setName(
"Stack/Morphology/Closing");
171 setDesc(
"Morphological closure (i.e. dilatation followed erosion) on stack");
172 setIcon(QIcon(
":/images/Closing.png"));
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());
182 if(!checkState().store(STORE_NON_EMPTY))
184 Stack* s = currentStack();
187 bool res = run(s, input, output, parm(
"X Radius").toUInt(), parm(
"Y Radius").toUInt(),
188 parm(
"Z Radius").toUInt(),
stringToBool(parm(
"Round Nhbd")));
196 uint xradius,
uint yradius,
uint zradius,
bool roundNhbd);
215 setName(
"Stack/Morphology/Opening");
216 setDesc(
"Morphological opening (i.e. erosion followed dilatation) on stack");
217 setIcon(QIcon(
":/images/Opening.png"));
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());
227 if(!checkState().store(STORE_NON_EMPTY))
229 Stack* s = currentStack();
232 bool res = run(s, input, output, parm(
"X Radius").toUInt(), parm(
"Y Radius").toUInt(),
233 parm(
"Z Radius").toUInt(),
stringToBool(parm(
"Round Nhbd")));
241 uint yradius,
uint zradius,
bool roundNhbd);
250 setName(
"Stack/Morphology/Fill Holes");
251 setDesc(
"Fill holes in stack.\n"
252 "Use after Edge Detect.");
253 setIcon(QIcon(
":/images/FillHoles.png"));
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");
264 if(!checkState().store(STORE_NON_EMPTY | STORE_NON_LABEL))
266 Stack* s = currentStack();
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());
280 int xradius,
int yradius,
int threshold,
int depth,
int fillValue);
298 setName(
"Stack/Morphology/Open by label");
299 setDesc(
"Morphological opening on a labeled stack");
300 setIcon(QIcon(
":/images/Opening.png"));
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());
310 if(!checkState().store(STORE_NON_EMPTY | STORE_LABEL))
312 Stack* s = currentStack();
315 bool res = run(s, input, output,
316 parm(
"X Radius").toUInt(), parm(
"X Radius").toUInt(), parm(
"X Radius").toUInt(),
stringToBool(parm(
"Round Nhbd")));
324 uint xradius,
uint yradius,
uint zradius,
bool roundNhbd);
344 setName(
"Stack/Morphology/Close by label");
345 setDesc(
"Morphological closure on a labeled stack");
346 setIcon(QIcon(
":/images/Closing.png"));
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());
356 if(!checkState().store(STORE_NON_EMPTY | STORE_LABEL))
358 Stack* s = currentStack();
361 bool res = run(s, input, output,
362 parm(
"X Radius").toUInt(), parm(
"Y Radius").toUInt(), parm(
"Z Radius").toUInt(),
stringToBool(parm(
"Round Nhbd")));
370 uint xradius,
uint yradius,
uint zradius,
bool roundNhbd);
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"));
399 addParm(
"Mode",
"Mode",
"Normal", QStringList() <<
"Normal" <<
"Invert" <<
"Combine");
400 addParm(
"Threshold",
"Threshold",
"0");
405 if(!checkState().store(STORE_NON_EMPTY))
407 Stack* stack = currentStack();
410 bool res = run(stack, input, output, parm(
"Mode"), parm(
"Threshold").toUInt());
418 const QString& mode,
uint threshold);
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"));
442 addParm(
"Invert",
"Invert",
"No",booleanChoice());
443 addParm(
"Threshold",
"Threshold",
"1");
448 if(!checkState().store(STORE_NON_EMPTY))
450 Stack* stack = currentStack();
453 bool res = run(stack, input, output, parm(
"Invert").toUInt(),
stringToBool(parm(
"Threshold")));
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"));
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");
489 Stack* stack = currentStack();
492 bool res = run(stack, input, output, parm(
"Distance").toDouble(), parm(
"Points").toInt(),
493 stringToBool(parm(
"Mask")), parm(
"Fill Value").toInt(), parm(
"Axes"));
500 bool run(
Stack* stack,
const Store* input,
Store* output,
double distance,
int points,
501 bool mask =
false,
int fillValue = 65535, QString axes =
"u");