@@ -43,10 +43,19 @@ function run(obj, frame)
4343
4444 % setup display
4545 obj.Viewer = frame ;
46- createFigure(obj );
46+
47+ % choose dialog accoding to image dimension
48+ nd = ndims(currentImage(obj .Viewer ));
49+ if nd == 2
50+ createFigure2d(obj );
51+ elseif nd == 3
52+ createFigure3d(obj );
53+ else
54+ error(' Can process only dimensions 2 and 3' );
55+ end
4756 end
4857
49- function tab = computeFeatures (obj )
58+ function tab = computeFeatures2d (obj )
5059 % compute the selected features on the current image and return table
5160
5261 % get current image
@@ -97,7 +106,7 @@ function run(obj, frame)
97106 tab = [tab Table(shapeFactor , {' ShapeFactor' })];
98107 end
99108
100- % process inertia -based features
109+ % process moment -based features
101110 if centroidFlag || ellipseFlag || ellipseElongFlag
102111 elli = imEquivalentEllipse(imgData , spacing , origin , labels );
103112
@@ -157,14 +166,98 @@ function run(obj, frame)
157166
158167 tab.Name = [img .Name ' -features' ];
159168 end
169+
170+ function tab = computeFeatures3d(obj )
171+ % Compute the selected 3D features on the current image and return Table.
172+
173+ % get current image
174+ img = currentImage(obj .Viewer );
175+
176+ % identify features to compute
177+ volumeFlag = get(obj .Handles .VolumeCheckBox , ' Value' );
178+ surfaceAreaFlag = get(obj .Handles .SurfaceAreaCheckBox , ' Value' );
179+ meanBreadthFlag = get(obj .Handles .MeanBreadthCheckBox , ' Value' );
180+ eulerFlag = get(obj .Handles .EulerNumberCheckBox , ' Value' );
181+ sphericityFlag = get(obj .Handles .SphericityCheckBox , ' Value' );
182+
183+ centroidFlag = get(obj .Handles .CentroidCheckBox , ' Value' );
184+ ellipsoidFlag = get(obj .Handles .EllipsoidCheckBox , ' Value' );
185+ ellipsoidShapeFlag = get(obj .Handles .EllipsoidShapeCheckBox , ' Value' );
186+
187+ boundingBoxFlag = get(obj .Handles .BoundingBoxCheckBox , ' Value' );
188+ % convexVolumeFlag = get(obj.Handles.ConvexVolumeCheckBox, 'Value');
189+ convexityFlag = get(obj .Handles .ConvexityCheckBox , ' Value' );
190+
191+
192+ % retrieve image data
193+ imgData = permute(img .Data , [2 1 3 ]);
194+ spacing = img .Spacing ;
195+ origin = img .Origin ;
196+
197+ % initialize empty table
198+ labels = imFindLabels(imgData );
199+ tab = Table(labels , {' Label' });
200+
201+ % process global size features
202+ if volumeFlag || sphericityFlag
203+ volList = imVolume(imgData , labels , spacing );
204+ tab = [tab Table(volList , {' Volume' })];
205+ end
206+ if surfaceAreaFlag || sphericityFlag
207+ surfList = imSurfaceArea(imgData , labels , spacing );
208+ tab = [tab Table(surfList , {' SurfaceArea' })];
209+ end
210+ if meanBreadthFlag
211+ mbList = imMeanBreadth(imgData , labels , spacing );
212+ tab = [tab Table(mbList , {' MeanBreadth' })];
213+ end
214+ if eulerFlag
215+ tab = [tab Table(imEuler3d(imgData ), {' EulerNumber' })];
216+ end
217+ if sphericityFlag
218+ shapeFactor = 36 * pi * volList .^ 2 ./ surfList .^ 3 ;
219+ tab = [tab Table(shapeFactor , {' Sphericity' })];
220+ end
221+
222+ if boundingBoxFlag
223+ boxes = imBoundingBox(imgData , spacing , origin , labels );
224+ colNames = {' XMin' , ' XMax' , ' YMin' , ' YMax' , ' ZMin' , ' ZMax' };
225+ tab = [tab Table(boxes , colNames )];
226+ end
227+
228+ % process moment-based features
229+ if centroidFlag || ellipsoidFlag || ellipsoidShapeFlag
230+ elli = imEquivalentEllipsoid(imgData , spacing , origin , labels );
231+
232+ if centroidFlag || ellipsoidFlag
233+ tab = [tab Table(elli(: ,1 : 3 ), {' CentroidX' , ' CentroidY' , ' CentroidZ' })];
234+ end
235+ if ellipsoidFlag
236+ tab = [tab Table(elli(: ,4 : 6 ), {' SemiAxis1' , ' SemiAxis2' , ' SemiAxis3' })];
237+ tab = [tab Table(elli(: ,7 : 9 ), {' Phi' , ' Theta' , ' Psi' })];
238+ end
239+ if ellipsoidShapeFlag
240+ elongs = [elli(: ,4 ) ./ elli(: ,6 ), elli(: ,4 ) ./ elli(: ,5 ), elli(: ,5 ) ./ elli(: ,6 )] ;
241+ tab = [tab Table(elongs , {' R1/R3' , ' R1/R2' , ' R2/R3' })];
242+ end
243+ end
244+
245+ if convexityFlag
246+ convexityList = imConvexity(imgData , labels );
247+ tab = [tab Table(convexityList , {' Convexity' })];
248+ end
249+
250+ tab.Name = [img .Name ' -features' ];
251+ end
160252end
161253
162254methods
163- function hf = createFigure(obj )
164- % creates the figure
255+
256+ function hf = createFigure2d(obj )
257+ % creates the figure for 2D images.
165258
166259 hf = figure(...
167- ' Name' , ' Analysis Particles ' , ...
260+ ' Name' , ' Analyze Regions 2D ' , ...
168261 ' NumberTitle' , ' off' , ...
169262 ' MenuBar' , ' none' , ...
170263 ' Toolbar' , ' none' , ...
@@ -176,18 +269,18 @@ function run(obj, frame)
176269
177270 obj.Handles.Figure = hf ;
178271 gui = obj .Viewer .Gui ;
179-
272+
180273 % the list of images for choosing the overlay
181274 imageNames = getImageNames(gui .App );
182275
183-
276+
184277 % vertical layout, containing main panel and buttons panel
185278 vb = uix .VBox(' Parent' , hf , ' Spacing' , 5 , ' Padding' , 5 );
186279
187280 mainPanel = uix .VBox(' Parent' , vb );
188-
281+
189282 featuresPanel = uix .Grid(' Parent' , mainPanel );
190-
283+
191284
192285 % First column
193286
@@ -240,7 +333,7 @@ function run(obj, frame)
240333 ' Style' , ' Checkbox' , ...
241334 ' Parent' , featuresPanel , ...
242335 ' Visible' , ' Off' );
243-
336+
244337
245338 % Second column
246339
@@ -262,7 +355,7 @@ function run(obj, frame)
262355 ' Parent' , featuresPanel , ...
263356 ' String' , ' Ellipse Elongation' , ...
264357 ' Value' , 1 );
265-
358+
266359
267360 % Feret diameters
268361 uicontrol(...
@@ -281,19 +374,19 @@ function run(obj, frame)
281374 ' Parent' , featuresPanel , ...
282375 ' String' , ' Oriented Box' , ...
283376 ' Value' , 1 );
284-
377+
285378 obj.Handles.BoxElongationCheckBox = uicontrol(...
286379 ' Style' , ' Checkbox' , ...
287380 ' Parent' , featuresPanel , ...
288381 ' String' , ' Box Elongation' , ...
289382 ' Value' , 1 );
290383
291- obj.Handles.TortuosityCheckBox = uicontrol(...
384+ obj.Handles.TortuosityCheckBox = uicontrol(...
292385 ' Style' , ' Checkbox' , ...
293386 ' Parent' , featuresPanel , ...
294387 ' String' , ' Tortuosity' );
295388
296-
389+
297390 % use same widths for all columns
298391 set(featuresPanel , ' Widths' , [-1 - 1 ]);
299392 set(featuresPanel , ' Heights' , [20 20 20 20 20 20 20 20 20 ]);
@@ -304,7 +397,7 @@ function run(obj, frame)
304397 ' Overlay:' , obj .OverlayTypeValues );
305398 set(obj .Handles .OverlayTypePopup , ' Value' , 2 );
306399
307- % add combo box for choosing the image to overlay
400+ % add combo box for choosing the image to overlay
308401 obj.Handles.OverlayImagePopup = addComboBoxLine(gui , mainPanel , ...
309402 ' Image to overlay:' , imageNames );
310403
@@ -327,15 +420,126 @@ function run(obj, frame)
327420
328421 set(vb , ' Heights' , [-1 40 ] );
329422 end
330- end
423+
424+ function hf = createFigure3d(obj )
425+ % creates the figure for 3D images.
426+
427+ hf = figure(...
428+ ' Name' , ' Analyze Regions 3D' , ...
429+ ' NumberTitle' , ' off' , ...
430+ ' MenuBar' , ' none' , ...
431+ ' Toolbar' , ' none' , ...
432+ ' CloseRequestFcn' , @obj .closeFigure );
433+ set(hf , ' units' , ' pixels' );
434+ pos = get(hf , ' Position' );
435+ pos(3 : 4 ) = [250 300 ];
436+ set(hf , ' Position' , pos );
437+
438+ obj.Handles.Figure = hf ;
439+
440+ % vertical layout, containing main panel and buttons panel
441+ vb = uix .VBox(' Parent' , hf , ' Spacing' , 5 , ' Padding' , 5 );
442+
443+ mainPanel = uix .VBox(' Parent' , vb );
444+
445+ featuresPanel = uix .Grid(' Parent' , mainPanel );
446+
447+
448+ % First column
449+
450+ % global morphometry
451+ obj.Handles.VolumeCheckBox = uicontrol(...
452+ ' Style' , ' Checkbox' , ...
453+ ' Parent' , featuresPanel , ...
454+ ' String' , ' Volume' , ...
455+ ' Value' , 1 );
456+ obj.Handles.SurfaceAreaCheckBox = uicontrol(...
457+ ' Style' , ' Checkbox' , ...
458+ ' Parent' , featuresPanel , ...
459+ ' String' , ' Surface Area' , ...
460+ ' Value' , 1 );
461+ obj.Handles.MeanBreadthCheckBox = uicontrol(...
462+ ' Style' , ' Checkbox' , ...
463+ ' Parent' , featuresPanel , ...
464+ ' String' , ' Mean Breadth' , ...
465+ ' Value' , 0 );
466+ obj.Handles.EulerNumberCheckBox = uicontrol(...
467+ ' Style' , ' Checkbox' , ...
468+ ' Parent' , featuresPanel , ...
469+ ' String' , ' Euler Number' , ...
470+ ' Value' , 0 );
471+ obj.Handles.SphericityCheckBox = uicontrol(...
472+ ' Style' , ' Checkbox' , ...
473+ ' Parent' , featuresPanel , ...
474+ ' String' , ' Sphericity' , ...
475+ ' Value' , 0 );
476+
477+
478+ % Second column
479+
480+ % inertia-based parameters
481+ obj.Handles.BoundingBoxCheckBox = uicontrol(...
482+ ' Style' , ' Checkbox' , ...
483+ ' Parent' , featuresPanel , ...
484+ ' String' , ' Bounding Box' , ...
485+ ' Value' , 1 );
486+
487+ % moment-based parameters
488+ obj.Handles.CentroidCheckBox = uicontrol(...
489+ ' Style' , ' Checkbox' , ...
490+ ' Parent' , featuresPanel , ...
491+ ' String' , ' Centroid' , ...
492+ ' Value' , 1 );
493+
494+ obj.Handles.EllipsoidCheckBox = uicontrol(...
495+ ' Style' , ' Checkbox' , ...
496+ ' Parent' , featuresPanel , ...
497+ ' String' , ' Equivalent Ellipsoid' , ...
498+ ' Value' , 1 );
499+
500+ obj.Handles.EllipsoidShapeCheckBox = uicontrol(...
501+ ' Style' , ' Checkbox' , ...
502+ ' Parent' , featuresPanel , ...
503+ ' String' , ' Ellipsoid Shapes' , ...
504+ ' Value' , 0 );
505+
506+ % convexity
507+ obj.Handles.ConvexityCheckBox = uicontrol(...
508+ ' Style' , ' Checkbox' , ...
509+ ' Parent' , featuresPanel , ...
510+ ' String' , ' Convexity' , ...
511+ ' Value' , 0 );
512+
513+
514+ % use same widths for all columns
515+ set(featuresPanel , ' Widths' , [-1 - 1 ]);
516+ set(featuresPanel , ' Heights' , [20 20 20 20 20 ]);
517+
518+
519+ % setup layout for all widgets but control panel
520+ set(mainPanel , ' Heights' , - 1 );
521+ % set(mainPanel, 'Heights', [-1 35 35] );
522+
523+ % button for control panel
524+ buttonsPanel = uix .HButtonBox(' Parent' , vb , ' Padding' , 5 );
525+ uicontrol(' Parent' , buttonsPanel , ...
526+ ' String' , ' OK' , ...
527+ ' Callback' , @obj .onButtonOK3d );
528+ uicontrol(' Parent' , buttonsPanel , ...
529+ ' String' , ' Cancel' , ...
530+ ' Callback' , @obj .onButtonCancel );
531+
532+ set(vb , ' Heights' , [-1 40 ] );
533+ end
534+ end
331535
332536
333537%% Control buttons Callback
334538methods
335539 function onButtonOK(obj , varargin )
336540
337541 % compute morphological features
338- tab = computeFeatures (obj );
542+ tab = computeFeatures2d (obj );
339543
340544 % extract type of overlay
341545 overlayTypeIndex = get(obj .Handles .OverlayTypePopup , ' Value' );
@@ -348,7 +552,7 @@ function onButtonOK(obj, varargin)
348552 docToOverlay = getDocument(gui .App , imageName );
349553
350554 closeFigure(obj );
351-
555+
352556 % display data table in its own window
353557 createTableFrame(obj .Viewer .Gui , tab );
354558
@@ -380,17 +584,28 @@ function onButtonOK(obj, varargin)
380584 ' Style' , {{' color' , ' g' }});
381585 addShape(docToOverlay , shape );
382586 end
383-
587+
384588 otherwise
385589 error([' Unable to process overlay type: ' overlayType ]);
386590 end
387-
591+
388592 % update all the views referenced by the document with overlay
389593 viewList = getViews(docToOverlay );
390594 for i = 1 : length(viewList )
391595 updateDisplay(viewList{i });
392596 end
393-
597+
598+ end
599+
600+ function onButtonOK3d(obj , varargin )
601+
602+ % compute morphological features
603+ tab = computeFeatures3d(obj );
604+
605+ closeFigure(obj );
606+
607+ % display data table in its own window
608+ createTableFrame(obj .Viewer .Gui , tab );
394609 end
395610
396611 function onButtonCancel(obj , varargin )
0 commit comments