Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support 3D segmentation with TrackMate-MorphoLibJ. #1

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
9 changes: 6 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<groupId>org.scijava</groupId>
<artifactId>pom-scijava</artifactId>
<version>37.0.0</version>
<relativePath />
</parent>

<groupId>sc.fiji</groupId>
Expand Down Expand Up @@ -84,7 +83,7 @@
<!-- NB: Deploy releases to the SciJava Maven repository. -->
<releaseProfiles>sign,deploy-to-scijava</releaseProfiles>

<TrackMate.version>7.10.2</TrackMate.version>
<TrackMate.version>8.0.0-SNAPSHOT</TrackMate.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -118,7 +117,11 @@
<groupId>org.scijava</groupId>
<artifactId>scijava-common</artifactId>
</dependency>

<dependency>
<groupId>net.imglib2</groupId>
<artifactId>imglib2-mesh</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- Other dependencies -->
<dependency>
<groupId>fr.inra.ijpb</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
Expand All @@ -33,6 +33,7 @@
import ij.ImageStack;
import ij.plugin.Duplicator;
import inra.ijpb.binary.BinaryImages;
import inra.ijpb.label.LabelImages;
import inra.ijpb.morphology.MinimaAndMaxima3D;
import inra.ijpb.watershed.Watershed;
import net.imagej.ImgPlus;
Expand Down Expand Up @@ -64,16 +65,24 @@ public class MorphoLibJDetector< T extends RealType< T > & NativeType< T > > imp

private final boolean simplify;

private final double smoothingScale;

private final boolean removeLargestObject;

public MorphoLibJDetector(
final ImgPlus< T > img,
final Interval interval,
final double tolerance,
final Connectivity connectivity,
final boolean simplify )
final boolean removeLargestObject,
final boolean simplify,
final double smoothingScale )
{
this.img = img;
this.tolerance = tolerance;
this.connectivity = connectivity;
this.removeLargestObject = removeLargestObject;
this.smoothingScale = smoothingScale;
this.interval = DetectionUtils.squeeze( interval );
this.simplify = simplify;
this.baseErrorMessage = BASE_ERROR_MESSAGE;
Expand Down Expand Up @@ -109,11 +118,19 @@ public boolean process()
final ImageStack labeledMinima = BinaryImages.componentsLabeling( regionalMinima, conn, 32 );
final ImageStack resultStack = Watershed.computeWatershed( imposedMinima, labeledMinima, conn, dams );

if ( removeLargestObject )
LabelImages.removeLargestLabel( resultStack );

final ImagePlus resultImage = new ImagePlus( "watershed", resultStack );
final Img< T > labelImage = ImageJFunctions.wrap( resultImage );
final double[] calibration = TMUtils.getSpatialCalibration( img );

final LabelImageDetector< T > lbldetector = new LabelImageDetector<>( labelImage, interval, calibration, simplify );
final LabelImageDetector< T > lbldetector = new LabelImageDetector<>(
labelImage,
interval,
calibration,
simplify,
smoothingScale );
if ( !lbldetector.checkInput() || !lbldetector.process() )
{
errorMessage = baseErrorMessage + lbldetector.getErrorMessage();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
Expand All @@ -23,9 +23,11 @@

import static fiji.plugin.trackmate.detection.DetectorKeys.KEY_TARGET_CHANNEL;
import static fiji.plugin.trackmate.detection.ThresholdDetectorFactory.KEY_SIMPLIFY_CONTOURS;
import static fiji.plugin.trackmate.detection.ThresholdDetectorFactory.KEY_SMOOTHING_SCALE;
import static fiji.plugin.trackmate.gui.Fonts.BIG_FONT;
import static fiji.plugin.trackmate.gui.Fonts.SMALL_FONT;
import static fiji.plugin.trackmate.morpholibj.MorphoLibJDetectorFactory.KEY_CONNECTIVITY;
import static fiji.plugin.trackmate.morpholibj.MorphoLibJDetectorFactory.KEY_REMOVE_LARGEST_OBJECT;
import static fiji.plugin.trackmate.morpholibj.MorphoLibJDetectorFactory.KEY_TOLERANCE;

import java.awt.Dimension;
Expand Down Expand Up @@ -55,6 +57,7 @@
import fiji.plugin.trackmate.detection.SpotDetectorFactoryBase;
import fiji.plugin.trackmate.gui.GuiUtils;
import fiji.plugin.trackmate.gui.components.ConfigurationPanel;
import fiji.plugin.trackmate.gui.components.PanelSmoothContour;
import fiji.plugin.trackmate.util.DetectionPreview;

public class MorphoLibJDetectorConfigurationPanel extends ConfigurationPanel
Expand All @@ -72,12 +75,18 @@ public class MorphoLibJDetectorConfigurationPanel extends ConfigurationPanel

private final JFormattedTextField ftfTolerance;

private final JComboBox< Connectivity > cmbboxConnectivity;

private final JCheckBox chkboxRemoveLargest;

private final JCheckBox chkboxSimplify;
private final PanelSmoothContour smoothingPanel;

private final JComboBox< Connectivity > cmbboxConnectivity;

public MorphoLibJDetectorConfigurationPanel( final Settings settings, final Model model )
{
int gridy = 0;

final GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.columnWidths = new int[] { 144, 0, 32 };
gridBagLayout.rowHeights = new int[] { 0, 84, 0, 27, 0, 0, 0 };
Expand All @@ -93,41 +102,46 @@ public MorphoLibJDetectorConfigurationPanel( final Settings settings, final Mode
gbcLblDetector.insets = new Insets( 5, 5, 5, 0 );
gbcLblDetector.fill = GridBagConstraints.HORIZONTAL;
gbcLblDetector.gridx = 0;
gbcLblDetector.gridy = 0;
gbcLblDetector.gridy = gridy;
add( lblDetector, gbcLblDetector );

/*
* Help text.
*/

gridy++;

final GridBagConstraints gbcLblHelptext = new GridBagConstraints();
gbcLblHelptext.anchor = GridBagConstraints.NORTH;
gbcLblHelptext.fill = GridBagConstraints.BOTH;
gbcLblHelptext.gridwidth = 3;
gbcLblHelptext.insets = new Insets( 5, 5, 5, 5 );
gbcLblHelptext.gridx = 0;
gbcLblHelptext.gridy = 1;
gbcLblHelptext.gridy = gridy;
add( GuiUtils.textInScrollPanel( GuiUtils.infoDisplay( MorphoLibJDetectorFactory.INFO_TEXT ) ), gbcLblHelptext );

/*
* Channel selector.
*/


gridy++;

final JLabel lblSegmentInChannel = new JLabel( "Segment in channel:" );
lblSegmentInChannel.setFont( SMALL_FONT );
final GridBagConstraints gbcLblSegmentInChannel = new GridBagConstraints();
gbcLblSegmentInChannel.anchor = GridBagConstraints.EAST;
gbcLblSegmentInChannel.insets = new Insets( 5, 5, 5, 5 );
gbcLblSegmentInChannel.gridx = 0;
gbcLblSegmentInChannel.gridy = 2;
gbcLblSegmentInChannel.gridy = gridy;
add( lblSegmentInChannel, gbcLblSegmentInChannel );

sliderChannel = new JSlider();
final GridBagConstraints gbcSliderChannel = new GridBagConstraints();
gbcSliderChannel.fill = GridBagConstraints.HORIZONTAL;
gbcSliderChannel.insets = new Insets( 5, 5, 5, 5 );
gbcSliderChannel.gridx = 1;
gbcSliderChannel.gridy = 2;
gbcSliderChannel.gridy = gridy;
add( sliderChannel, gbcSliderChannel );

final JLabel labelChannel = new JLabel( "1" );
Expand All @@ -136,7 +150,7 @@ public MorphoLibJDetectorConfigurationPanel( final Settings settings, final Mode
final GridBagConstraints gbcLabelChannel = new GridBagConstraints();
gbcLabelChannel.insets = new Insets( 5, 5, 5, 0 );
gbcLabelChannel.gridx = 2;
gbcLabelChannel.gridy = 2;
gbcLabelChannel.gridy = gridy;
add( labelChannel, gbcLabelChannel );

sliderChannel.addChangeListener( l -> labelChannel.setText( "" + sliderChannel.getValue() ) );
Expand All @@ -145,13 +159,15 @@ public MorphoLibJDetectorConfigurationPanel( final Settings settings, final Mode
* Tolerance
*/

gridy++;

final JLabel lblTolerance = new JLabel( "Tolerance:" );
lblTolerance.setFont( SMALL_FONT );
final GridBagConstraints gbcLblTolerance = new GridBagConstraints();
gbcLblTolerance.anchor = GridBagConstraints.EAST;
gbcLblTolerance.insets = new Insets( 5, 5, 5, 5 );
gbcLblTolerance.gridx = 0;
gbcLblTolerance.gridy = 3;
gbcLblTolerance.gridy = gridy;
add( lblTolerance, gbcLblTolerance );

ftfTolerance = new JFormattedTextField( THRESHOLD_FORMAT );
Expand All @@ -161,22 +177,24 @@ public MorphoLibJDetectorConfigurationPanel( final Settings settings, final Mode
final GridBagConstraints gbcTolerance = new GridBagConstraints();
gbcTolerance.gridwidth = 2;
gbcTolerance.fill = GridBagConstraints.HORIZONTAL;
gbcTolerance.insets = new Insets( 5, 5, 5, 0 );
gbcTolerance.insets = new Insets( 5, 5, 5, 5 );
gbcTolerance.gridx = 1;
gbcTolerance.gridy = 3;
gbcTolerance.gridy = gridy;
add( ftfTolerance, gbcTolerance );

/*
* Connectivity.
*/

gridy++;

final JLabel lblConnectivity = new JLabel( "Connectivity:" );
lblConnectivity.setFont( new Font( "Arial", Font.PLAIN, 10 ) );
final GridBagConstraints gbcLblConnectivity = new GridBagConstraints();
gbcLblConnectivity.anchor = GridBagConstraints.EAST;
gbcLblConnectivity.insets = new Insets( 0, 5, 5, 5 );
gbcLblConnectivity.gridx = 0;
gbcLblConnectivity.gridy = 4;
gbcLblConnectivity.gridy = gridy;
add( lblConnectivity, gbcLblConnectivity );

this.cmbboxConnectivity = new JComboBox<>( new Vector<>( Arrays.asList( Connectivity.values() ) ) );
Expand All @@ -187,41 +205,84 @@ public MorphoLibJDetectorConfigurationPanel( final Settings settings, final Mode
gbcCmbboxConnectivity.insets = new Insets( 0, 5, 5, 0 );
gbcCmbboxConnectivity.fill = GridBagConstraints.HORIZONTAL;
gbcCmbboxConnectivity.gridx = 1;
gbcCmbboxConnectivity.gridy = 4;
gbcCmbboxConnectivity.gridy = gridy;
add( cmbboxConnectivity, gbcCmbboxConnectivity );

/*
* Remove largest object.
*/

gridy++;

final JLabel lblRemoveLargest = new JLabel( "Remove largest object:" );
lblRemoveLargest.setFont( SMALL_FONT );
final GridBagConstraints gbcLblRemoveLargest = new GridBagConstraints();
gbcLblRemoveLargest.anchor = GridBagConstraints.EAST;
gbcLblRemoveLargest.insets = new Insets( 0, 5, 5, 5 );
gbcLblRemoveLargest.gridx = 0;
gbcLblRemoveLargest.gridy = gridy;
add( lblRemoveLargest, gbcLblRemoveLargest );

this.chkboxRemoveLargest = new JCheckBox();
final GridBagConstraints gbcChkboxRemoveLargest = new GridBagConstraints();
gbcChkboxRemoveLargest.anchor = GridBagConstraints.WEST;
gbcChkboxRemoveLargest.insets = new Insets( 0, 5, 5, 5 );
gbcChkboxRemoveLargest.gridx = 1;
gbcChkboxRemoveLargest.gridy = gridy;
add( chkboxRemoveLargest, gbcChkboxRemoveLargest );

/*
* Simplify.
*/

gridy++;

final JLabel lblSimplify = new JLabel( "Simplify contours:" );
lblSimplify.setFont( SMALL_FONT );
final GridBagConstraints gbcLblSimplify = new GridBagConstraints();
gbcLblSimplify.anchor = GridBagConstraints.EAST;
gbcLblSimplify.insets = new Insets( 0, 5, 5, 5 );
gbcLblSimplify.gridx = 0;
gbcLblSimplify.gridy = 5;
gbcLblSimplify.gridy = gridy;
add( lblSimplify, gbcLblSimplify );

this.chkboxSimplify = new JCheckBox();
final GridBagConstraints gbcChkboxSimplify = new GridBagConstraints();
gbcChkboxSimplify.anchor = GridBagConstraints.WEST;
gbcChkboxSimplify.insets = new Insets( 0, 5, 5, 5 );
gbcChkboxSimplify.gridx = 1;
gbcChkboxSimplify.gridy = 5;
gbcChkboxSimplify.gridy = gridy;
add( chkboxSimplify, gbcChkboxSimplify );

/*
* Smoothing scale.
*/

gridy++;

smoothingPanel = new PanelSmoothContour( -1., model.getSpaceUnits() );
smoothingPanel.setFont( SMALL_FONT );
final GridBagConstraints gbcSmoothingPanel = new GridBagConstraints();
gbcSmoothingPanel.gridwidth = 3;
gbcSmoothingPanel.fill = GridBagConstraints.HORIZONTAL;
gbcSmoothingPanel.insets = new Insets( 0, 5, 5, 5 );
gbcSmoothingPanel.gridx = 0;
gbcSmoothingPanel.gridy = gridy;
add( smoothingPanel, gbcSmoothingPanel );

/*
* Logger.
*/

gridy++;

final GridBagConstraints gbcBtnPreview = new GridBagConstraints();
gbcBtnPreview.fill = GridBagConstraints.HORIZONTAL;
gbcBtnPreview.gridwidth = 3;
gbcBtnPreview.fill = GridBagConstraints.BOTH;
gbcBtnPreview.insets = new Insets( 5, 5, 5, 5 );
gbcBtnPreview.gridx = 0;
gbcBtnPreview.gridy = 6;
gbcBtnPreview.gridy = gridy;

final DetectionPreview detectionPreview = DetectionPreview.create()
.model( model )
Expand Down Expand Up @@ -283,9 +344,15 @@ public Map< String, Object > getSettings()
final Connectivity connectivity = ( Connectivity ) cmbboxConnectivity.getSelectedItem();
settings.put( KEY_CONNECTIVITY, connectivity.getConnectivity() );

final boolean removeLargestObject = chkboxRemoveLargest.isSelected();
settings.put( KEY_REMOVE_LARGEST_OBJECT, removeLargestObject );

final boolean simplify = chkboxSimplify.isSelected();
settings.put( KEY_SIMPLIFY_CONTOURS, simplify );

final double scale = smoothingPanel.getScale();
settings.put( KEY_SMOOTHING_SCALE, scale );

return settings;
}

Expand All @@ -295,7 +362,11 @@ public void setSettings( final Map< String, Object > settings )
sliderChannel.setValue( ( Integer ) settings.get( KEY_TARGET_CHANNEL ) );
ftfTolerance.setValue( settings.get( KEY_TOLERANCE ) );
cmbboxConnectivity.setSelectedItem( Connectivity.valueFor( ( int ) settings.get( KEY_CONNECTIVITY ) ) );
chkboxRemoveLargest.setSelected( ( boolean ) settings.get( KEY_REMOVE_LARGEST_OBJECT ) );
chkboxSimplify.setSelected( ( boolean ) settings.get( KEY_SIMPLIFY_CONTOURS ) );
final Object scaleObj = settings.get( KEY_SMOOTHING_SCALE );
final double scale = scaleObj == null ? -1. : ( ( Number ) scaleObj ).doubleValue();
smoothingPanel.setScale( scale );
}

@Override
Expand Down
Loading
Loading