diff --git a/TrakEM2_/pom.xml b/TrakEM2_/pom.xml
index 73abdd8dd..c22ec7ff5 100644
--- a/TrakEM2_/pom.xml
+++ b/TrakEM2_/pom.xml
@@ -80,11 +80,6 @@
mpicbg_
${mpicbg.version}
-
- sc.fiji
- VectorString
- 1.0-SNAPSHOT
-
sc.fiji
Simple_Neurite_Tracer
@@ -115,11 +110,6 @@
Lasso_and_Blow_Tool
2.0.0-SNAPSHOT
-
- sc.fiji
- fiji-lib
- 2.0.0-SNAPSHOT
-
sc.fiji
Fiji_Plugins
@@ -135,6 +125,15 @@
bUnwarpJ_
2.6
+
+ sc.fiji
+ fiji-lib
+
+
+ sc.fiji
+ VectorString
+ 1.0-SNAPSHOT
+
diff --git a/TrakEM2_/src/main/java/mpicbg/trakem2/align/ElasticLayerAlignment.java b/TrakEM2_/src/main/java/mpicbg/trakem2/align/ElasticLayerAlignment.java
index a307e05ea..dbd65a870 100644
--- a/TrakEM2_/src/main/java/mpicbg/trakem2/align/ElasticLayerAlignment.java
+++ b/TrakEM2_/src/main/java/mpicbg/trakem2/align/ElasticLayerAlignment.java
@@ -20,7 +20,11 @@
import ij.IJ;
import ij.ImagePlus;
import ij.gui.GenericDialog;
+import ij.gui.Roi;
+import ij.process.Blitter;
+import ij.process.ColorProcessor;
import ij.process.FloatProcessor;
+import ij.process.ImageProcessor;
import ini.trakem2.Project;
import ini.trakem2.display.Layer;
import ini.trakem2.display.LayerSet;
@@ -33,13 +37,27 @@
import java.awt.Rectangle;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
+import net.imglib2.Cursor;
+import net.imglib2.IterableInterval;
+import net.imglib2.RealPoint;
+import net.imglib2.collection.KDTree;
+import net.imglib2.collection.RealPointSampleList;
+import net.imglib2.exception.ImgLibException;
+import net.imglib2.img.imageplus.ImagePlusImg;
+import net.imglib2.img.imageplus.ImagePlusImgFactory;
+import net.imglib2.neighborsearch.NearestNeighborSearch;
+import net.imglib2.neighborsearch.NearestNeighborSearchOnKDTree;
+import net.imglib2.type.Type;
+import net.imglib2.type.numeric.ARGBType;
import mpicbg.ij.blockmatching.BlockMatching;
+import mpicbg.ij.util.Util;
import mpicbg.imagefeatures.Feature;
import mpicbg.imagefeatures.FloatArray2DSIFT;
import mpicbg.models.AbstractModel;
@@ -60,7 +78,10 @@
import mpicbg.models.TranslationModel2D;
import mpicbg.models.Vertex;
import mpicbg.trakem2.transform.MovingLeastSquaresTransform2;
+import mpicbg.trakem2.util.Downsampler;
import mpicbg.trakem2.util.Triple;
+import mpicbg.util.ColorStream;
+import mpicbg.util.Timer;
/**
* @author Stephan Saalfeld
@@ -72,6 +93,7 @@ final static public class Param extends AbstractLayerAlignmentParam implements S
private static final long serialVersionUID = 3366971916160734613L;
public boolean isAligned = false;
+ public boolean isTestParams = false;
public float layerScale = 0.1f;
public float minR = 0.6f;
@@ -93,7 +115,7 @@ final static public class Param extends AbstractLayerAlignmentParam implements S
public int maxIterationsSpringMesh = 1000;
public int maxPlateauwidthSpringMesh = 200;
public boolean useLegacyOptimizer = true;
-
+
public boolean setup( final Rectangle box )
{
/* Block Matching */
@@ -126,6 +148,7 @@ public boolean setup( final Rectangle box )
gdBlockMatching.addMessage( "Miscellaneous:" );
gdBlockMatching.addCheckbox( "layers_are_pre-aligned", isAligned );
gdBlockMatching.addNumericField( "test_maximally :", maxNumNeighbors, 0, 6, "layers" );
+ gdBlockMatching.addCheckbox( "Test_parameters", isTestParams );
gdBlockMatching.showDialog();
@@ -146,70 +169,73 @@ public boolean setup( final Rectangle box )
maxLocalTrust = ( float )gdBlockMatching.getNextNumber();
isAligned = gdBlockMatching.getNextBoolean();
maxNumNeighbors = ( int )gdBlockMatching.getNextNumber();
+ isTestParams = gdBlockMatching.getNextBoolean();
+ if (!isTestParams){
+ if ( !isAligned )
+ {
+ if ( !setupSIFT( "Elastically align layers: " ) )
+ return false;
+
+ /* Geometric filters */
+
+ final GenericDialog gd = new GenericDialog( "Elastically align layers: Geometric filters" );
+
+ gd.addNumericField( "maximal_alignment_error :", maxEpsilon, 2, 6, "px" );
+ gd.addNumericField( "minimal_inlier_ratio :", minInlierRatio, 2 );
+ gd.addNumericField( "minimal_number_of_inliers :", minNumInliers, 0 );
+ gd.addChoice( "approximate_transformation :", Param.modelStrings, Param.modelStrings[ expectedModelIndex ] );
+ gd.addCheckbox( "ignore constant background", rejectIdentity );
+ gd.addNumericField( "tolerance :", identityTolerance, 2, 6, "px" );
+ gd.addNumericField( "give_up_after :", maxNumFailures, 0, 6, "failures" );
+
+ gd.showDialog();
+
+ if ( gd.wasCanceled() )
+ return false;
+
+ maxEpsilon = ( float )gd.getNextNumber();
+ minInlierRatio = ( float )gd.getNextNumber();
+ minNumInliers = ( int )gd.getNextNumber();
+ expectedModelIndex = gd.getNextChoiceIndex();
+ rejectIdentity = gd.getNextBoolean();
+ identityTolerance = ( float )gd.getNextNumber();
+ maxNumFailures = ( int )gd.getNextNumber();
+ }
- if ( !isAligned )
- {
- if ( !setupSIFT( "Elastically align layers: " ) )
- return false;
-
- /* Geometric filters */
+
+ /* Optimization */
+
+ final GenericDialog gdOptimize = new GenericDialog( "Elastically align layers: Optimization" );
- final GenericDialog gd = new GenericDialog( "Elastically align layers: Geometric filters" );
+ gdOptimize.addMessage( "Approximate Optimizer:" );
+ gdOptimize.addChoice( "approximate_transformation :", Param.modelStrings, Param.modelStrings[ desiredModelIndex ] );
+ gdOptimize.addNumericField( "maximal_iterations :", maxIterationsOptimize, 0 );
+ gdOptimize.addNumericField( "maximal_plateauwidth :", maxPlateauwidthOptimize, 0 );
- gd.addNumericField( "maximal_alignment_error :", maxEpsilon, 2, 6, "px" );
- gd.addNumericField( "minimal_inlier_ratio :", minInlierRatio, 2 );
- gd.addNumericField( "minimal_number_of_inliers :", minNumInliers, 0 );
- gd.addChoice( "approximate_transformation :", Param.modelStrings, Param.modelStrings[ expectedModelIndex ] );
- gd.addCheckbox( "ignore constant background", rejectIdentity );
- gd.addNumericField( "tolerance :", identityTolerance, 2, 6, "px" );
- gd.addNumericField( "give_up_after :", maxNumFailures, 0, 6, "failures" );
+ gdOptimize.addMessage( "Spring Mesh:" );
+ gdOptimize.addNumericField( "stiffness :", stiffnessSpringMesh, 2 );
+ gdOptimize.addNumericField( "maximal_stretch :", maxStretchSpringMesh, 2, 6, "px" );
+ gdOptimize.addNumericField( "maximal_iterations :", maxIterationsSpringMesh, 0 );
+ gdOptimize.addNumericField( "maximal_plateauwidth :", maxPlateauwidthSpringMesh, 0 );
+ gdOptimize.addCheckbox( "use_legacy_optimizer :", useLegacyOptimizer );
- gd.showDialog();
+ gdOptimize.showDialog();
- if ( gd.wasCanceled() )
+ if ( gdOptimize.wasCanceled() )
return false;
- maxEpsilon = ( float )gd.getNextNumber();
- minInlierRatio = ( float )gd.getNextNumber();
- minNumInliers = ( int )gd.getNextNumber();
- expectedModelIndex = gd.getNextChoiceIndex();
- rejectIdentity = gd.getNextBoolean();
- identityTolerance = ( float )gd.getNextNumber();
- maxNumFailures = ( int )gd.getNextNumber();
+ desiredModelIndex = gdOptimize.getNextChoiceIndex();
+ maxIterationsOptimize = ( int )gdOptimize.getNextNumber();
+ maxPlateauwidthOptimize = ( int )gdOptimize.getNextNumber();
+
+ stiffnessSpringMesh = ( float )gdOptimize.getNextNumber();
+ maxStretchSpringMesh = ( float )gdOptimize.getNextNumber();
+ maxIterationsSpringMesh = ( int )gdOptimize.getNextNumber();
+ maxPlateauwidthSpringMesh = ( int )gdOptimize.getNextNumber();
+ useLegacyOptimizer = gdOptimize.getNextBoolean();
}
-
- /* Optimization */
- final GenericDialog gdOptimize = new GenericDialog( "Elastically align layers: Optimization" );
-
- gdOptimize.addMessage( "Approximate Optimizer:" );
- gdOptimize.addChoice( "approximate_transformation :", Param.modelStrings, Param.modelStrings[ desiredModelIndex ] );
- gdOptimize.addNumericField( "maximal_iterations :", maxIterationsOptimize, 0 );
- gdOptimize.addNumericField( "maximal_plateauwidth :", maxPlateauwidthOptimize, 0 );
-
- gdOptimize.addMessage( "Spring Mesh:" );
- gdOptimize.addNumericField( "stiffness :", stiffnessSpringMesh, 2 );
- gdOptimize.addNumericField( "maximal_stretch :", maxStretchSpringMesh, 2, 6, "px" );
- gdOptimize.addNumericField( "maximal_iterations :", maxIterationsSpringMesh, 0 );
- gdOptimize.addNumericField( "maximal_plateauwidth :", maxPlateauwidthSpringMesh, 0 );
- gdOptimize.addCheckbox( "use_legacy_optimizer :", useLegacyOptimizer );
-
- gdOptimize.showDialog();
-
- if ( gdOptimize.wasCanceled() )
- return false;
-
- desiredModelIndex = gdOptimize.getNextChoiceIndex();
- maxIterationsOptimize = ( int )gdOptimize.getNextNumber();
- maxPlateauwidthOptimize = ( int )gdOptimize.getNextNumber();
-
- stiffnessSpringMesh = ( float )gdOptimize.getNextNumber();
- maxStretchSpringMesh = ( float )gdOptimize.getNextNumber();
- maxIterationsSpringMesh = ( int )gdOptimize.getNextNumber();
- maxPlateauwidthSpringMesh = ( int )gdOptimize.getNextNumber();
- useLegacyOptimizer = gdOptimize.getNextBoolean();
-
return true;
}
@@ -231,6 +257,7 @@ public Param(
final int expectedModelIndex,
final float identityTolerance,
final boolean isAligned,
+ final boolean isTestParams,
final float maxEpsilon,
final int maxIterationsOptimize,
final int maxNumFailures,
@@ -288,6 +315,7 @@ public Param(
visualize );
this.isAligned = isAligned;
+ this.isTestParams = isTestParams;
this.blockRadius = blockRadius;
this.dampSpringMesh = dampSpringMesh;
this.layerScale = layerScale;
@@ -327,6 +355,7 @@ public Param clone()
expectedModelIndex,
identityTolerance,
isAligned,
+ isTestParams,
maxEpsilon,
maxIterationsOptimize,
maxNumFailures,
@@ -361,6 +390,7 @@ public Param clone()
}
final static Param p = new Param();
+ protected final static int minGridSize = 8; // for test parameters
final static private String layerName( final Layer layer )
@@ -682,8 +712,10 @@ public void run()
final float localRegionSigma = param.layerScale * param.localRegionSigma;
final float maxLocalEpsilon = param.layerScale * param.maxLocalEpsilon;
- final AbstractModel< ? > localSmoothnessFilterModel = Util.createModel( param.localModelIndex );
+ final AbstractModel< ? > localSmoothnessFilterModel = mpicbg.trakem2.align.Util.createModel( param.localModelIndex );
+ ImagePlus impTable = null; // for test parameters
+ ColorProcessor ipTable = null; // for test parameters
for ( final Triple< Integer, Integer, AbstractModel< ? > > pair : pairs )
{
@@ -743,7 +775,7 @@ public void run()
mpicbg.trakem2.align.Util.imageToFloatAndMask( img1, ip1, ip1Mask );
mpicbg.trakem2.align.Util.imageToFloatAndMask( img2, ip2, ip2Mask );
- final float springConstant = 1.0f / ( pair.b - pair.a );
+ final float springConstant = 1.0f / ( pair.b - pair.a );
if ( layer1Fixed )
initMeshes.fixTile( t1 );
@@ -904,145 +936,315 @@ public void run()
}
Utils.log( pair.a + " <> " + pair.b + " spring constant = " + springConstant );
- }
- }
+
+
+
+
+ /* If testing parameters is true, display*/
+ if (param.isTestParams){
+ Utils.log("Test parameters");
+
+ int w = box.width;
+ int h = box.height;
+ while ( w > param.resolutionSpringMesh * minGridSize )
+ {
+ w /= 2;
+ h /= 2;
+ }
+
+ // create the table
+ if (ipTable == null){
+ ipTable = initTestParamTable(layerRange.size(), w, h);
+ impTable = new ImagePlus( "Block Matching Results", ipTable );
+ impTable.show();
+ }
+
+ // copy the original images in the table
+ if (pair.a == 0 && pair.b == 1) { // put 0th image in
+ copyLayers2Table( ipTable, (int) pair.a, (ColorProcessor) ip1.convertToRGB(), w, h);
+ }
+ if (pair.a == 0) { // a remains 0 and b loops from 1 to range
+ copyLayers2Table( ipTable, (int) pair.b, (ColorProcessor) ip2.convertToRGB(), w, h);
+ }
+
+ // fill the space
+ final SpringMesh mesh = new SpringMesh( param.resolutionSpringMesh, img1.getWidth(null), img1.getHeight(null), 1, 1000, 0.9f );
+ final Collection< Vertex > vertices = mesh.getVertices();
+ final RealPointSampleList< ARGBType > maskSamples = new RealPointSampleList< ARGBType >( 2 );
+ for ( final Vertex vertex : vertices )
+ maskSamples.add( new RealPoint( vertex.getL() ), new ARGBType( 0xffffffff ) );
+// maskSamples.add( new RealPoint( vertex.getL() ), new ARGBType( ColorStream.next() ) );
+ /* translate relative to bounding box */
+
+ // show results for the pair
+ display( img1, param, pm12, maskSamples, impTable, ipTable, w, h, pair.a, pair.b );
+ display( img1, param, pm21, maskSamples, impTable, ipTable, w, h, pair.b, pair.a );
+
+ }
+ } // if not fixed layers
+ } // for
- /* pre-align by optimizing a piecewise linear model */
- initMeshes.optimize(
- param.maxEpsilon * param.layerScale,
- param.maxIterationsSpringMesh,
- param.maxPlateauwidthSpringMesh );
- for ( int i = 0; i < layerRange.size(); ++i )
- meshes.get( i ).init( tiles.get( i ).getModel() );
-
- /* optimize the meshes */
- try
- {
- final long t0 = System.currentTimeMillis();
- Utils.log( "Optimizing spring meshes..." );
-
- if ( param.useLegacyOptimizer )
+ /* If not testing parameters, apply transform */
+ if (!param.isTestParams) {
+ /* pre-align by optimizing a piecewise linear model */
+ initMeshes.optimize(
+ param.maxEpsilon * param.layerScale,
+ param.maxIterationsSpringMesh,
+ param.maxPlateauwidthSpringMesh );
+ for ( int i = 0; i < layerRange.size(); ++i )
+ meshes.get( i ).init( tiles.get( i ).getModel() );
+
+ /* optimize the meshes */
+ try
{
- Utils.log( " ...using legacy optimizer...");
- SpringMesh.optimizeMeshes2(
- meshes,
- param.maxEpsilon * param.layerScale,
- param.maxIterationsSpringMesh,
- param.maxPlateauwidthSpringMesh,
- param.visualize );
+ final long t0 = System.currentTimeMillis();
+ Utils.log( "Optimizing spring meshes..." );
+
+ if ( param.useLegacyOptimizer )
+ {
+ Utils.log( " ...using legacy optimizer...");
+ SpringMesh.optimizeMeshes2(
+ meshes,
+ param.maxEpsilon * param.layerScale,
+ param.maxIterationsSpringMesh,
+ param.maxPlateauwidthSpringMesh,
+ param.visualize );
+ }
+ else
+ {
+ SpringMesh.optimizeMeshes(
+ meshes,
+ param.maxEpsilon * param.layerScale,
+ param.maxIterationsSpringMesh,
+ param.maxPlateauwidthSpringMesh,
+ param.visualize );
+ }
+
+ Utils.log("Done optimizing spring meshes. Took " + (System.currentTimeMillis() - t0) + " ms");
+
}
- else
+ catch ( final NotEnoughDataPointsException e )
{
- SpringMesh.optimizeMeshes(
- meshes,
- param.maxEpsilon * param.layerScale,
- param.maxIterationsSpringMesh,
- param.maxPlateauwidthSpringMesh,
- param.visualize );
+ Utils.log( "There were not enough data points to get the spring mesh optimizing." );
+ e.printStackTrace();
+ return;
}
-
- Utils.log("Done optimizing spring meshes. Took " + (System.currentTimeMillis() - t0) + " ms");
- }
- catch ( final NotEnoughDataPointsException e )
- {
- Utils.log( "There were not enough data points to get the spring mesh optimizing." );
- e.printStackTrace();
- return;
- }
-
- /* translate relative to bounding box */
- for ( final SpringMesh mesh : meshes )
- {
- for ( final PointMatch pm : mesh.getVA().keySet() )
+ /* translate relative to bounding box */
+ for ( final SpringMesh mesh : meshes )
{
- final Point p1 = pm.getP1();
- final Point p2 = pm.getP2();
- final float[] l = p1.getL();
- final float[] w = p2.getW();
- l[ 0 ] = l[ 0 ] / param.layerScale + box.x;
- l[ 1 ] = l[ 1 ] / param.layerScale + box.y;
- w[ 0 ] = w[ 0 ] / param.layerScale + box.x;
- w[ 1 ] = w[ 1 ] / param.layerScale + box.y;
+ for ( final PointMatch pm : mesh.getVA().keySet() )
+ {
+ final Point p1 = pm.getP1();
+ final Point p2 = pm.getP2();
+ final float[] l = p1.getL();
+ final float[] w = p2.getW();
+ l[ 0 ] = l[ 0 ] / param.layerScale + box.x;
+ l[ 1 ] = l[ 1 ] / param.layerScale + box.y;
+ w[ 0 ] = w[ 0 ] / param.layerScale + box.x;
+ w[ 1 ] = w[ 1 ] / param.layerScale + box.y;
+ }
}
- }
-
- /* free memory */
- project.getLoader().releaseAll();
-
- final Layer first = layerRange.get( 0 );
- final List< Layer > layers = first.getParent().getLayers();
-
- /* transfer layer transform into patch transforms and append to patches */
- if ( propagateTransformBefore || propagateTransformAfter )
- {
+
+ /* free memory */
+ project.getLoader().releaseAll();
+
+ final Layer first = layerRange.get( 0 );
+ final List< Layer > layers = first.getParent().getLayers();
+
+ /* transfer layer transform into patch transforms and append to patches */
+ if ( propagateTransformBefore || propagateTransformAfter )
+ {
+ if ( propagateTransformBefore )
+ {
+ final MovingLeastSquaresTransform2 mlt = makeMLST2( meshes.get( 0 ).getVA().keySet() );
+ final int firstLayerIndex = first.getParent().getLayerIndex( first.getId() );
+ for ( int i = 0; i < firstLayerIndex; ++i )
+ applyTransformToLayer( layers.get( i ), mlt, filter );
+ }
+ if ( propagateTransformAfter )
+ {
+ final Layer last = layerRange.get( layerRange.size() - 1 );
+ final MovingLeastSquaresTransform2 mlt = makeMLST2( meshes.get( meshes.size() - 1 ).getVA().keySet() );
+ final int lastLayerIndex = last.getParent().getLayerIndex( last.getId() );
+ for ( int i = lastLayerIndex + 1; i < layers.size(); ++i )
+ applyTransformToLayer( layers.get( i ), mlt, filter );
+ }
+ }
+ for ( int l = 0; l < layerRange.size(); ++l )
+ {
+ IJ.showStatus( "Applying transformation to patches ..." );
+ IJ.showProgress( 0, layerRange.size() );
+
+ final Layer layer = layerRange.get( l );
+
+ final MovingLeastSquaresTransform2 mlt = new MovingLeastSquaresTransform2();
+ mlt.setModel( AffineModel2D.class );
+ mlt.setAlpha( 2.0f );
+ mlt.setMatches( meshes.get( l ).getVA().keySet() );
+
+ applyTransformToLayer( layer, mlt, filter );
+
+ if ( Thread.interrupted() )
+ {
+ Utils.log( "Interrupted during applying transformations to patches. No all patches have been updated. Re-generate mipmaps manually." );
+ }
+
+ IJ.showProgress( l + 1, layerRange.size() );
+ }
+
+ /* update patch mipmaps */
+ final int firstLayerIndex;
+ final int lastLayerIndex;
+
if ( propagateTransformBefore )
+ firstLayerIndex = 0;
+ else
{
- final MovingLeastSquaresTransform2 mlt = makeMLST2( meshes.get( 0 ).getVA().keySet() );
- final int firstLayerIndex = first.getParent().getLayerIndex( first.getId() );
- for ( int i = 0; i < firstLayerIndex; ++i )
- applyTransformToLayer( layers.get( i ), mlt, filter );
+ firstLayerIndex = first.getParent().getLayerIndex( first.getId() );
}
if ( propagateTransformAfter )
+ lastLayerIndex = layers.size() - 1;
+ else
{
final Layer last = layerRange.get( layerRange.size() - 1 );
- final MovingLeastSquaresTransform2 mlt = makeMLST2( meshes.get( meshes.size() - 1 ).getVA().keySet() );
- final int lastLayerIndex = last.getParent().getLayerIndex( last.getId() );
- for ( int i = lastLayerIndex + 1; i < layers.size(); ++i )
- applyTransformToLayer( layers.get( i ), mlt, filter );
+ lastLayerIndex = last.getParent().getLayerIndex( last.getId() );
+ }
+
+ for ( int i = firstLayerIndex; i <= lastLayerIndex; ++i )
+ {
+ final Layer layer = layers.get( i );
+ if ( !( emptyLayers.contains( layer ) || fixedLayers.contains( layer ) ) )
+ {
+ for ( final Patch patch : AlignmentUtils.filterPatches( layer, filter ) )
+ patch.updateMipMaps();
+ }
}
}
- for ( int l = 0; l < layerRange.size(); ++l )
+
+
+ Utils.log( "Done." );
+ }
+
+ // from TestParameters.run()
+ protected ColorProcessor initTestParamTable(int nLayers, int w, int h){
+
+ // final ImagePlus impTable;
+ final ColorProcessor ipTable;
+
+ ipTable = new ColorProcessor( w * nLayers + w, h * nLayers + h );
+
+ final ColorProcessor ipScale = new ColorProcessor( w, h );
+ final Color c = IJ.getInstance().getForeground();
+ ipScale.setColor( Color.WHITE );
+ ipScale.fill();
+ ipScale.setColor( c );
+ mpicbg.ij.util.Util.colorCircle( ipScale );
+
+ ipTable.copyBits( ipScale, 0, 0, Blitter.COPY );
+
+ //impTable.show();
+
+ return ipTable;
+ }
+
+ protected void copyLayers2Table(ColorProcessor ipTable, int i, ColorProcessor ip, int w, int h) {
+ ip = (ColorProcessor)mpicbg.ij.util.Filter.createDownsampled(ip, (float) w / ip.getWidth(), 0.5f, 0.5f);
+ ipTable.copyBits( ip, i * w + w, 0, Blitter.COPY );
+ ipTable.copyBits( ip, 0, i * h + h, Blitter.COPY );
+ }
+
+
+ protected void display(
+ final Image img1,
+ final Param param,
+ final ArrayList< PointMatch > pm12,
+ final RealPointSampleList< ARGBType > maskSamples,
+ final ImagePlus impTable,
+ final ColorProcessor ipTable, final int w, final int h, final int i, final int j )
+ {
+
+ if ( pm12.size() > 0 )
{
- IJ.showStatus( "Applying transformation to patches ..." );
- IJ.showProgress( 0, layerRange.size() );
+ final ImagePlusImgFactory< ARGBType > factory = new ImagePlusImgFactory< ARGBType >();
- final Layer layer = layerRange.get( l );
+ final KDTree< ARGBType > kdtreeMatches = new KDTree< ARGBType >( matches2ColorSamples( pm12, param ) );
+ final KDTree< ARGBType > kdtreeMask = new KDTree< ARGBType >( maskSamples );
- final MovingLeastSquaresTransform2 mlt = new MovingLeastSquaresTransform2();
- mlt.setModel( AffineModel2D.class );
- mlt.setAlpha( 2.0f );
- mlt.setMatches( meshes.get( l ).getVA().keySet() );
+ /* nearest neighbor */
+ final ImagePlusImg< ARGBType, ? > img = factory.create( new long[]{ img1.getWidth(null), img1.getHeight(null) }, new ARGBType() );
+ drawNearestNeighbor(
+ img,
+ new NearestNeighborSearchOnKDTree< ARGBType >( kdtreeMatches ),
+ new NearestNeighborSearchOnKDTree< ARGBType >( kdtreeMask ) );
- applyTransformToLayer( layer, mlt, filter );
-
- if ( Thread.interrupted() )
+ final ImagePlus impVis;
+ ColorProcessor ipVis;
+ try
{
- Utils.log( "Interrupted during applying transformations to patches. No all patches have been updated. Re-generate mipmaps manually." );
+ impVis = img.getImagePlus();
+ ipVis = ( ColorProcessor )impVis.getProcessor();
+ ipVis = (ColorProcessor)mpicbg.ij.util.Filter.createDownsampled(ipVis, (float)w / img.getWidth(), 0.5f, 0.5f);
+ ipTable.copyBits( ipVis, i * w + w, j * h + h, Blitter.COPY );
+ impTable.updateAndDraw();
+ }
+ catch ( final ImgLibException e )
+ {
+ IJ.log( "ImgLib2 Exception, vectors could not be painted." );
+ e.printStackTrace();
}
-
- IJ.showProgress( l + 1, layerRange.size() );
}
-
- /* update patch mipmaps */
- final int firstLayerIndex;
- final int lastLayerIndex;
-
- if ( propagateTransformBefore )
- firstLayerIndex = 0;
else
{
- firstLayerIndex = first.getParent().getLayerIndex( first.getId() );
+ final Roi roi = new Roi( i * w + w, j * h + h, w, h );
+ final Color c = IJ.getInstance().getForeground();
+ ipTable.setColor( Color.WHITE );
+ ipTable.fill( roi );
+ ipTable.setColor( c );
}
- if ( propagateTransformAfter )
- lastLayerIndex = layers.size() - 1;
- else
+ }
+
+
+
+ // a copy from the AbstractBlockMatching
+ final static protected RealPointSampleList< ARGBType > matches2ColorSamples(
+ final Iterable< PointMatch > matches,
+ final Param param)
+ {
+ final RealPointSampleList< ARGBType > samples = new RealPointSampleList< ARGBType >( 2 );
+ for ( final PointMatch match : matches )
{
- final Layer last = layerRange.get( layerRange.size() - 1 );
- lastLayerIndex = last.getParent().getLayerIndex( last.getId() );
+ final float[] p = match.getP1().getL();
+ final float[] q = match.getP2().getW();
+ final float dx = ( q[ 0 ] - p[ 0 ] ) / param.searchRadius;
+ final float dy = ( q[ 1 ] - p[ 1 ] ) / param.searchRadius;
+
+ final int rgb = Util.colorVector( dx, dy );
+
+ samples.add( new RealPoint( p ), new ARGBType( rgb ) );
}
-
- for ( int i = firstLayerIndex; i <= lastLayerIndex; ++i )
+ return samples;
+ }
+ // a copy from the AbstractBlockMatching
+ final static protected < T extends Type< T > > long drawNearestNeighbor(
+ final IterableInterval< T > target,
+ final NearestNeighborSearch< T > nnSearchSamples,
+ final NearestNeighborSearch< T > nnSearchMask )
+ {
+ final Timer timer = new Timer();
+ timer.start();
+ final Cursor< T > c = target.localizingCursor();
+ while ( c.hasNext() )
{
- final Layer layer = layers.get( i );
- if ( !( emptyLayers.contains( layer ) || fixedLayers.contains( layer ) ) )
- {
- for ( final Patch patch : AlignmentUtils.filterPatches( layer, filter ) )
- patch.updateMipMaps();
- }
+ c.fwd();
+ nnSearchSamples.search( c );
+ nnSearchMask.search( c );
+ if ( nnSearchSamples.getSquareDistance() <= nnSearchMask.getSquareDistance() )
+ c.get().set( nnSearchSamples.getSampler().get() );
+ else
+ c.get().set( nnSearchMask.getSampler().get() );
}
-
- Utils.log( "Done." );
+ return timer.stop();
}
final static protected MovingLeastSquaresTransform2 makeMLST2( final Set< PointMatch > matches ) throws Exception