-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13 from mastodon-sc/compute-ellipsoid-for-segment…
…ation-2 Add an example that demonstrates how to compute the ellipsoid parameters for a given segmentation result.
- Loading branch information
Showing
8 changed files
with
201 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
134 changes: 134 additions & 0 deletions
134
src/test/java/org/mastodon/mamut/fitting/demo/ComputeMeanAndVarianceDemo.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package org.mastodon.mamut.fitting.demo; | ||
|
||
import net.imglib2.Cursor; | ||
import net.imglib2.img.Img; | ||
import net.imglib2.img.array.ArrayImgs; | ||
import net.imglib2.loops.LoopBuilder; | ||
import net.imglib2.type.numeric.real.FloatType; | ||
import net.imglib2.util.LinAlgHelpers; | ||
|
||
import org.mastodon.mamut.fitting.util.DemoUtils; | ||
import org.mastodon.mamut.fitting.util.MultiVariantNormalDistributionRenderer; | ||
import org.mastodon.mamut.model.Model; | ||
|
||
import java.util.Arrays; | ||
|
||
/** | ||
* Computing the mean position and covariance matrix for a given segmented | ||
* region of an image is an easy way to get good ellipsoid parameters for | ||
* that segment. | ||
* <p> | ||
* Here is an example of how to do that. | ||
*/ | ||
public class ComputeMeanAndVarianceDemo | ||
{ | ||
|
||
public static void main( String[] args ) | ||
{ | ||
double[] center = { 40, 50, 60 }; | ||
double[][] givenCovariance = { | ||
{ 400, 20, -10 }, | ||
{ 20, 200, 30 }, | ||
{ -10, 30, 100 } | ||
}; | ||
|
||
long[] dimensions = { 100, 100, 100 }; | ||
int background = 0; | ||
int pixelValue = 1; | ||
Img< FloatType > image = generateExampleImage( center, givenCovariance, dimensions, background, pixelValue ); | ||
double[] mean = computeMean( image, pixelValue ); | ||
double[][] computedCovariance = computeCovariance( image, mean, pixelValue ); | ||
|
||
System.out.println( "Given center: " + Arrays.toString( center ) ); | ||
System.out.println( "Computed mean: " + Arrays.toString( mean ) ); | ||
System.out.println( "Given covariance: " + Arrays.deepToString( givenCovariance ) ); | ||
System.out.println( "Computed covariance: " + Arrays.deepToString( computedCovariance ) ); | ||
|
||
Model model = new Model(); | ||
model.getGraph().addVertex().init( 0, mean, computedCovariance ); | ||
DemoUtils.showBdvWindow( DemoUtils.wrapAsAppModel( image, model ) ); | ||
} | ||
|
||
/** | ||
* Returns an example image with a single ellipsoid. | ||
* | ||
* @param center center of the ellipsoid | ||
* @param cov covariance matrix of the ellipsoid | ||
* @param dimensions dimensions of the image | ||
* @param background value of the background | ||
* @param pixelValue value of the ellipsoid | ||
*/ | ||
private static Img< FloatType > generateExampleImage( | ||
final double[] center, final double[][] cov, final long[] dimensions, final int background, final int pixelValue | ||
) | ||
{ | ||
Img< FloatType > image = ArrayImgs.floats( dimensions ); | ||
MultiVariantNormalDistributionRenderer.renderMultivariateNormalDistribution( center, cov, image ); | ||
LoopBuilder.setImages( image ).forEachPixel( pixel -> { | ||
if ( pixel.get() > 500 ) | ||
pixel.set( pixelValue ); | ||
else | ||
pixel.set( background ); | ||
} ); | ||
return image; | ||
} | ||
|
||
/** | ||
* Computes the mean position of the pixels whose value equals the given {@code pixelValue}. | ||
* | ||
* @param image the image | ||
* @param pixelValue the pixel value | ||
* @return the mean position | ||
*/ | ||
private static double[] computeMean( final Img< FloatType > image, final int pixelValue ) | ||
{ | ||
Cursor< FloatType > cursor = image.cursor(); | ||
double[] sum = new double[ 3 ]; | ||
double[] position = new double[ 3 ]; | ||
long counter = 0; | ||
while ( cursor.hasNext() ) | ||
if ( cursor.next().get() == pixelValue ) | ||
{ | ||
cursor.localize( position ); | ||
LinAlgHelpers.add( sum, position, sum ); | ||
counter++; | ||
} | ||
LinAlgHelpers.scale( sum, 1. / counter, sum ); | ||
return sum; | ||
} | ||
|
||
/** | ||
* Computes the covariance matrix of the pixels whose value equals the given {@code pixelValue}. | ||
* | ||
* @param image the image | ||
* @param mean the mean position | ||
* @param pixelValue the pixel value | ||
*/ | ||
private static double[][] computeCovariance( final Img< FloatType > image, final double[] mean, final int pixelValue ) | ||
{ | ||
Cursor< FloatType > cursor = image.cursor(); | ||
long counter = 0; | ||
double[] position = new double[ 3 ]; | ||
double[][] covariance = new double[ 3 ][ 3 ]; | ||
cursor.reset(); | ||
while ( cursor.hasNext() ) | ||
if ( cursor.next().get() == pixelValue ) | ||
{ | ||
cursor.localize( position ); | ||
LinAlgHelpers.subtract( position, mean, position ); | ||
for ( int i = 0; i < 3; i++ ) | ||
for ( int j = 0; j < 3; j++ ) | ||
covariance[ i ][ j ] += position[ i ] * position[ j ]; | ||
counter++; | ||
} | ||
scale( covariance, 5. / counter ); // I don't know why the factor 5 is needed. But it works. | ||
return covariance; | ||
} | ||
|
||
private static void scale( final double[][] covariance, final double factor ) | ||
{ | ||
for ( int i = 0; i < 3; i++ ) | ||
for ( int j = 0; j < 3; j++ ) | ||
covariance[ i ][ j ] *= factor; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
src/test/java/org/mastodon/mamut/fitting/util/DemoUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package org.mastodon.mamut.fitting.util; | ||
|
||
import ij.ImagePlus; | ||
import net.imagej.ImgPlus; | ||
import net.imagej.axis.Axes; | ||
import net.imagej.axis.AxisType; | ||
import net.imglib2.img.Img; | ||
import net.imglib2.img.display.imagej.ImgToVirtualStack; | ||
import net.imglib2.type.numeric.RealType; | ||
import net.imglib2.type.numeric.real.FloatType; | ||
import org.mastodon.mamut.ProjectModel; | ||
import org.mastodon.mamut.fitting.MinimalProjectModel; | ||
import org.mastodon.mamut.model.Link; | ||
import org.mastodon.mamut.model.Model; | ||
import org.mastodon.mamut.model.Spot; | ||
import org.mastodon.mamut.views.bdv.MamutViewBdv; | ||
import org.mastodon.model.DefaultSelectionModel; | ||
import org.mastodon.model.SelectionModel; | ||
import org.mastodon.views.bdv.SharedBigDataViewerData; | ||
|
||
import javax.annotation.Nonnull; | ||
import java.util.Objects; | ||
|
||
public class DemoUtils | ||
{ | ||
private DemoUtils() | ||
{ | ||
// prevent from instantiation | ||
} | ||
|
||
public static ProjectModel wrapAsAppModel( final Img< FloatType > image, final Model model ) | ||
{ | ||
final SharedBigDataViewerData sharedBigDataViewerData = asSharedBdvDataXyz( image ); | ||
return ProjectModel.create( null, model, sharedBigDataViewerData, null ); | ||
} | ||
|
||
public static MinimalProjectModel wrapAsMinimalModel( final Img< FloatType > image, final Model model ) | ||
{ | ||
SharedBigDataViewerData sharedBDVData = DemoUtils.asSharedBdvDataXyz( image ); | ||
SelectionModel< Spot, Link > selectionModel = new DefaultSelectionModel<>( model.getGraph(), model.getGraphIdBimap() ); | ||
return new MinimalProjectModel( model, sharedBDVData, selectionModel ); | ||
} | ||
|
||
public static SharedBigDataViewerData asSharedBdvDataXyz( final Img< FloatType > image1 ) | ||
{ | ||
final ImagePlus image = ImgToVirtualStack.wrap( new ImgPlus<>( image1, "image", new AxisType[] { Axes.X, Axes.Y, Axes.Z } ) ); | ||
return Objects.requireNonNull( SharedBigDataViewerData.fromImagePlus( image ) ); | ||
} | ||
|
||
public static < T extends RealType< T > > void showBdvWindow( @Nonnull final ProjectModel appModel ) | ||
{ | ||
appModel.getWindowManager().createView( MamutViewBdv.class ); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters