use of mpicbg.models.PointMatch in project TrakEM2 by trakem2.
the class StitchingTEM method optimizeTileConfiguration.
/**
* Optimize tile configuration by removing bad matches
*
* @param tiles complete list of tiles
* @param fixed_tiles list of fixed tiles
* @param param phase correlation parameters
*/
public static void optimizeTileConfiguration(final ArrayList<AbstractAffineTile2D<?>> tiles, final ArrayList<AbstractAffineTile2D<?>> fixed_tiles, final PhaseCorrelationParam param) {
// Run optimization
if (fixed_tiles.isEmpty())
fixed_tiles.add(tiles.get(0));
// with default parameters
boolean proceed = true;
while (proceed) {
Align.optimizeTileConfiguration(new Align.ParamOptimize(), tiles, fixed_tiles);
/* get all transfer errors */
final ErrorStatistic e = new ErrorStatistic(tiles.size() + 1);
for (final AbstractAffineTile2D<?> t : tiles) t.update();
for (final AbstractAffineTile2D<?> t : tiles) {
for (final PointMatch p : t.getMatches()) {
e.add(p.getDistance());
}
}
/* remove the worst if there is one */
if (e.max > param.mean_factor * e.mean) {
A: for (final AbstractAffineTile2D<?> t : tiles) {
for (final PointMatch p : t.getMatches()) {
if (p.getDistance() >= e.max) {
final Tile<?> o = t.findConnectedTile(p);
t.removeConnectedTile(o);
o.removeConnectedTile(t);
// Utils.log2( "Removing bad match from configuration, error = " + e.max );
break A;
}
}
}
} else
proceed = false;
}
}
use of mpicbg.models.PointMatch in project TrakEM2 by trakem2.
the class AlignTask method alignGraphs.
private static final boolean alignGraphs(final Align.Param p, final Layer layer1, final Layer layer2, final Iterable<Tile<?>> graph1, final Iterable<Tile<?>> graph2) {
final Align.Param cp = p.clone();
final Selection selection1 = new Selection(null);
for (final Tile<?> tile : graph1) selection1.add(((AbstractAffineTile2D<?>) tile).getPatch());
final Rectangle graph1Box = selection1.getBox();
final Selection selection2 = new Selection(null);
for (final Tile<?> tile : graph2) selection2.add(((AbstractAffineTile2D<?>) tile).getPatch());
final Rectangle graph2Box = selection2.getBox();
final int maxLength = Math.max(Math.max(Math.max(graph1Box.width, graph1Box.height), graph2Box.width), graph2Box.height);
// final double scale = ( double )cp.sift.maxOctaveSize / maxLength;
/* rather ad hoc but we cannot just scale this to maxOctaveSize */
cp.sift.maxOctaveSize = Math.min(maxLength, 2 * p.sift.maxOctaveSize);
/* make sure that, despite rounding issues from scale, it is >= image size */
final double scale = (double) (cp.sift.maxOctaveSize - 1) / maxLength;
// cp.maxEpsilon *= scale;
final FloatArray2DSIFT sift = new FloatArray2DSIFT(cp.sift);
final SIFT ijSIFT = new SIFT(sift);
final ArrayList<Feature> features1 = new ArrayList<Feature>();
final ArrayList<Feature> features2 = new ArrayList<Feature>();
final ArrayList<PointMatch> candidates = new ArrayList<PointMatch>();
final ArrayList<PointMatch> inliers = new ArrayList<PointMatch>();
long s = System.currentTimeMillis();
ijSIFT.extractFeatures(layer1.getProject().getLoader().getFlatImage(layer1, graph1Box, scale, 0xffffffff, ImagePlus.GRAY8, Patch.class, selection1.getSelected(Patch.class), false, Color.GRAY).getProcessor(), features1);
Utils.log(features1.size() + " features extracted for graphs in layer \"" + layer1.getTitle() + "\" (took " + (System.currentTimeMillis() - s) + " ms).");
ijSIFT.extractFeatures(layer2.getProject().getLoader().getFlatImage(layer2, graph2Box, scale, 0xffffffff, ImagePlus.GRAY8, Patch.class, selection2.getSelected(Patch.class), false, Color.GRAY).getProcessor(), features2);
Utils.log(features2.size() + " features extracted for graphs in layer \"" + layer1.getTitle() + "\" (took " + (System.currentTimeMillis() - s) + " ms).");
boolean modelFound = false;
if (features1.size() > 0 && features2.size() > 0) {
s = System.currentTimeMillis();
FeatureTransform.matchFeatures(features1, features2, candidates, cp.rod);
final AbstractAffineModel2D<?> model;
switch(cp.expectedModelIndex) {
case 0:
model = new TranslationModel2D();
break;
case 1:
model = new RigidModel2D();
break;
case 2:
model = new SimilarityModel2D();
break;
case 3:
model = new AffineModel2D();
break;
default:
return false;
}
boolean again = false;
try {
do {
again = false;
modelFound = model.filterRansac(candidates, inliers, 1000, cp.maxEpsilon, cp.minInlierRatio, cp.minNumInliers, 3);
if (modelFound && cp.rejectIdentity) {
final ArrayList<Point> points = new ArrayList<Point>();
PointMatch.sourcePoints(inliers, points);
if (Transforms.isIdentity(model, points, cp.identityTolerance)) {
IJ.log("Identity transform for " + inliers.size() + " matches rejected.");
candidates.removeAll(inliers);
inliers.clear();
again = true;
}
}
} while (again);
} catch (final NotEnoughDataPointsException e) {
modelFound = false;
}
if (modelFound) {
Utils.log("Model found for graphs in layer \"" + layer1.getTitle() + "\" and \"" + layer2.getTitle() + "\":\n correspondences " + inliers.size() + " of " + candidates.size() + "\n average residual error " + (model.getCost() / scale) + " px\n took " + (System.currentTimeMillis() - s) + " ms");
final AffineTransform b = new AffineTransform();
b.translate(graph2Box.x, graph2Box.y);
b.scale(1.0f / scale, 1.0f / scale);
b.concatenate(model.createAffine());
b.scale(scale, scale);
b.translate(-graph1Box.x, -graph1Box.y);
for (final Displayable d : selection1.getSelected(Patch.class)) d.getAffineTransform().preConcatenate(b);
/* assign patch affine transformation to the tile model */
for (final Tile<?> t : graph1) ((AbstractAffineTile2D<?>) t).initModel();
Display.repaint(layer1);
} else
IJ.log("No model found for graphs in layer \"" + layer1.getTitle() + "\" and \"" + layer2.getTitle() + "\":\n correspondence candidates " + candidates.size() + "\n took " + (System.currentTimeMillis() - s) + " ms");
}
return modelFound;
}
use of mpicbg.models.PointMatch in project TrakEM2 by trakem2.
the class ElasticLayerAlignment method exec.
/**
* @param param
* @param layerRange
* @param fixedLayers
* @param emptyLayers
* @param box
* @param filter
* @param useTps true if using TPS transforms, otherwise MLS
* @throws Exception
*/
@SuppressWarnings("deprecation")
public final void exec(final Param param, final Project project, final List<Layer> layerRange, final Set<Layer> fixedLayers, final Set<Layer> emptyLayers, final Rectangle box, final boolean propagateTransformBefore, final boolean propagateTransformAfter, final Filter<Patch> filter) throws Exception {
final ExecutorService service = ExecutorProvider.getExecutorService(1.0f);
/* create tiles and models for all layers */
final ArrayList<Tile<?>> tiles = new ArrayList<Tile<?>>();
for (int i = 0; i < layerRange.size(); ++i) {
switch(param.desiredModelIndex) {
case 0:
tiles.add(new Tile<TranslationModel2D>(new TranslationModel2D()));
break;
case 1:
tiles.add(new Tile<RigidModel2D>(new RigidModel2D()));
break;
case 2:
tiles.add(new Tile<SimilarityModel2D>(new SimilarityModel2D()));
break;
case 3:
tiles.add(new Tile<AffineModel2D>(new AffineModel2D()));
break;
case 4:
tiles.add(new Tile<HomographyModel2D>(new HomographyModel2D()));
break;
default:
return;
}
}
/* collect all pairs of slices for which a model could be found */
final ArrayList<Triple<Integer, Integer, AbstractModel<?>>> pairs = new ArrayList<Triple<Integer, Integer, AbstractModel<?>>>();
if (!param.isAligned) {
preAlignStack(param, project, layerRange, box, filter, pairs);
} else {
for (int i = 0; i < layerRange.size(); ++i) {
final int range = Math.min(layerRange.size(), i + param.maxNumNeighbors + 1);
for (int j = i + 1; j < range; ++j) {
pairs.add(new Triple<Integer, Integer, AbstractModel<?>>(i, j, new TranslationModel2D()));
}
}
}
/* Elastic alignment */
/* Initialization */
final TileConfiguration initMeshes = new TileConfiguration();
final int meshWidth = (int) Math.ceil(box.width * param.layerScale);
final int meshHeight = (int) Math.ceil(box.height * param.layerScale);
final ArrayList<SpringMesh> meshes = new ArrayList<SpringMesh>(layerRange.size());
for (int i = 0; i < layerRange.size(); ++i) {
meshes.add(new SpringMesh(param.resolutionSpringMesh, meshWidth, meshHeight, param.stiffnessSpringMesh, param.maxStretchSpringMesh * param.layerScale, param.dampSpringMesh));
}
// final int blockRadius = Math.max( 32, meshWidth / p.resolutionSpringMesh / 2 );
final int blockRadius = Math.max(16, mpicbg.util.Util.roundPos(param.layerScale * param.blockRadius));
Utils.log("effective block radius = " + blockRadius);
final ArrayList<Future<BlockMatchPairCallable.BlockMatchResults>> futures = new ArrayList<Future<BlockMatchPairCallable.BlockMatchResults>>(pairs.size());
for (final Triple<Integer, Integer, AbstractModel<?>> pair : pairs) {
/* free memory */
project.getLoader().releaseAll();
final SpringMesh m1 = meshes.get(pair.a);
final SpringMesh m2 = meshes.get(pair.b);
final ArrayList<Vertex> v1 = m1.getVertices();
final ArrayList<Vertex> v2 = m2.getVertices();
final Layer layer1 = layerRange.get(pair.a);
final Layer layer2 = layerRange.get(pair.b);
final boolean layer1Fixed = fixedLayers.contains(layer1);
final boolean layer2Fixed = fixedLayers.contains(layer2);
if (!(layer1Fixed && layer2Fixed)) {
final BlockMatchPairCallable bmpc = new BlockMatchPairCallable(pair, layerRange, layer1Fixed, layer2Fixed, filter, param, v1, v2, box);
futures.add(service.submit(bmpc));
}
}
for (final Future<BlockMatchPairCallable.BlockMatchResults> future : futures) {
final BlockMatchPairCallable.BlockMatchResults results = future.get();
final Collection<PointMatch> pm12 = results.pm12, pm21 = results.pm21;
final Triple<Integer, Integer, AbstractModel<?>> pair = results.pair;
final Tile<?> t1 = tiles.get(pair.a);
final Tile<?> t2 = tiles.get(pair.b);
final SpringMesh m1 = meshes.get(pair.a);
final SpringMesh m2 = meshes.get(pair.b);
final double springConstant = 1.0 / (pair.b - pair.a);
final boolean layer1Fixed = results.layer1Fixed;
final boolean layer2Fixed = results.layer2Fixed;
if (layer1Fixed) {
initMeshes.fixTile(t1);
} else {
if (param.useLocalSmoothnessFilter) {
Utils.log(pair.a + " > " + pair.b + ": " + pm12.size() + " candidates passed local smoothness filter.");
} else {
Utils.log(pair.a + " > " + pair.b + ": found " + pm12.size() + " correspondences.");
}
for (final PointMatch pm : pm12) {
final Vertex p1 = (Vertex) pm.getP1();
final Vertex p2 = new Vertex(pm.getP2());
p1.addSpring(p2, new Spring(0, springConstant));
m2.addPassiveVertex(p2);
}
/*
* adding Tiles to the initialing TileConfiguration, adding a Tile
* multiple times does not harm because the TileConfiguration is
* backed by a Set.
*/
if (pm12.size() > pair.c.getMinNumMatches()) {
initMeshes.addTile(t1);
initMeshes.addTile(t2);
t1.connect(t2, pm12);
}
}
if (layer2Fixed)
initMeshes.fixTile(t2);
else {
if (param.useLocalSmoothnessFilter) {
Utils.log(pair.a + " < " + pair.b + ": " + pm21.size() + " candidates passed local smoothness filter.");
} else {
Utils.log(pair.a + " < " + pair.b + ": found " + pm21.size() + " correspondences.");
}
for (final PointMatch pm : pm21) {
final Vertex p1 = (Vertex) pm.getP1();
final Vertex p2 = new Vertex(pm.getP2());
p1.addSpring(p2, new Spring(0, springConstant));
m1.addPassiveVertex(p2);
}
/*
* adding Tiles to the initialing TileConfiguration, adding a Tile
* multiple times does not harm because the TileConfiguration is
* backed by a Set.
*/
if (pm21.size() > pair.c.getMinNumMatches()) {
initMeshes.addTile(t1);
initMeshes.addTile(t2);
t2.connect(t1, pm21);
}
}
Utils.log(pair.a + " <> " + pair.b + " spring constant = " + springConstant);
}
/* 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) {
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");
} 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()) {
final Point p1 = pm.getP1();
final Point p2 = pm.getP2();
final double[] l = p1.getL();
final double[] 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();
final LayerSet ls = first.getParent();
final Area infArea = AreaUtils.infiniteArea();
final List<VectorData> vectorData = new ArrayList<VectorData>();
for (final Layer layer : ls.getLayers()) {
vectorData.addAll(Utils.castCollection(layer.getDisplayables(VectorData.class, false, true), VectorData.class, true));
}
vectorData.addAll(Utils.castCollection(ls.getZDisplayables(VectorData.class, true), VectorData.class, true));
/* transfer layer transform into patch transforms and append to patches */
if (propagateTransformBefore || propagateTransformAfter) {
if (propagateTransformBefore) {
final ThinPlateSplineTransform tps = makeTPS(meshes.get(0).getVA().keySet());
final int firstLayerIndex = first.getParent().getLayerIndex(first.getId());
for (int i = 0; i < firstLayerIndex; ++i) {
applyTransformToLayer(layers.get(i), tps, filter);
for (final VectorData vd : vectorData) {
vd.apply(layers.get(i), infArea, tps);
}
}
}
if (propagateTransformAfter) {
final Layer last = layerRange.get(layerRange.size() - 1);
final CoordinateTransform ct;
if (param.useTps)
ct = makeTPS(meshes.get(meshes.size() - 1).getVA().keySet());
else {
final MovingLeastSquaresTransform2 mls = new MovingLeastSquaresTransform2();
mls.setMatches(meshes.get(meshes.size() - 1).getVA().keySet());
ct = mls;
}
final int lastLayerIndex = last.getParent().getLayerIndex(last.getId());
for (int i = lastLayerIndex + 1; i < layers.size(); ++i) {
applyTransformToLayer(layers.get(i), ct, filter);
for (final VectorData vd : vectorData) {
vd.apply(layers.get(i), infArea, ct);
}
}
}
}
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 ThinPlateSplineTransform tps = makeTPS(meshes.get(l).getVA().keySet());
applyTransformToLayer(layer, tps, filter);
for (final VectorData vd : vectorData) {
vd.apply(layer, infArea, tps);
}
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 {
firstLayerIndex = first.getParent().getLayerIndex(first.getId());
}
if (propagateTransformAfter)
lastLayerIndex = layers.size() - 1;
else {
final Layer last = layerRange.get(layerRange.size() - 1);
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();
}
}
Utils.log("Done.");
}
use of mpicbg.models.PointMatch in project TrakEM2 by trakem2.
the class ElasticMontage method exec.
@SuppressWarnings("deprecation")
public final void exec(final Param param, final List<Patch> patches, final Set<Patch> fixedPatches) throws Exception {
/* free memory */
patches.get(0).getProject().getLoader().releaseAll();
/* create tiles and models for all patches */
final ArrayList<AbstractAffineTile2D<?>> tiles = new ArrayList<AbstractAffineTile2D<?>>();
final ArrayList<AbstractAffineTile2D<?>> fixedTiles = new ArrayList<AbstractAffineTile2D<?>>();
Align.tilesFromPatches(param.po, patches, fixedPatches, tiles, fixedTiles);
if (!param.isAligned) {
Align.alignTiles(param.po, tiles, fixedTiles, param.tilesAreInPlace, param.maxNumThreads);
/* Apply the estimated affine transform to patches */
for (final AbstractAffineTile2D<?> t : tiles) t.getPatch().setAffineTransform(t.createAffine());
Display.update();
}
/* generate tile pairs for all by now overlapping tiles */
final ArrayList<AbstractAffineTile2D<?>[]> tilePairs = new ArrayList<AbstractAffineTile2D<?>[]>();
AbstractAffineTile2D.pairOverlappingTiles(tiles, tilePairs);
/* check if there was any pair */
if (tilePairs.size() == 0) {
Utils.log("Elastic montage could not find any overlapping patches after pre-montaging.");
return;
}
Utils.log(tilePairs.size() + " pairs of patches will be block-matched...");
/* make pairwise global models local */
final ArrayList<Triple<AbstractAffineTile2D<?>, AbstractAffineTile2D<?>, InvertibleCoordinateTransform>> pairs = new ArrayList<Triple<AbstractAffineTile2D<?>, AbstractAffineTile2D<?>, InvertibleCoordinateTransform>>();
/*
* The following casting madness is necessary to get this code compiled
* with Sun/Oracle Java 6 which otherwise generates an inconvertible
* type exception.
*
* TODO Remove as soon as this bug is fixed in Sun/Oracle javac.
*/
for (final AbstractAffineTile2D<?>[] pair : tilePairs) {
final AbstractAffineModel2D<?> m;
switch(param.po.desiredModelIndex) {
case 0:
final TranslationModel2D t = (TranslationModel2D) (Object) pair[1].getModel().createInverse();
t.concatenate((TranslationModel2D) (Object) pair[0].getModel());
m = t;
break;
case 1:
final RigidModel2D r = (RigidModel2D) (Object) pair[1].getModel().createInverse();
r.concatenate((RigidModel2D) (Object) pair[0].getModel());
m = r;
break;
case 2:
final SimilarityModel2D s = (SimilarityModel2D) (Object) pair[1].getModel().createInverse();
s.concatenate((SimilarityModel2D) (Object) pair[0].getModel());
m = s;
break;
case 3:
final AffineModel2D a = (AffineModel2D) (Object) pair[1].getModel().createInverse();
a.concatenate((AffineModel2D) (Object) pair[0].getModel());
m = a;
break;
default:
m = null;
}
pairs.add(new Triple<AbstractAffineTile2D<?>, AbstractAffineTile2D<?>, InvertibleCoordinateTransform>(pair[0], pair[1], m));
}
/* Elastic alignment */
/* Initialization */
final double springTriangleHeightTwice = 2 * Math.sqrt(0.75 * param.springLengthSpringMesh * param.springLengthSpringMesh);
final ArrayList<SpringMesh> meshes = new ArrayList<SpringMesh>(tiles.size());
final HashMap<AbstractAffineTile2D<?>, SpringMesh> tileMeshMap = new HashMap<AbstractAffineTile2D<?>, SpringMesh>();
for (final AbstractAffineTile2D<?> tile : tiles) {
final double w = tile.getWidth();
final double h = tile.getHeight();
final int numX = Math.max(2, (int) Math.ceil(w / param.springLengthSpringMesh) + 1);
final int numY = Math.max(2, (int) Math.ceil(h / springTriangleHeightTwice) + 1);
final double wMesh = (numX - 1) * param.springLengthSpringMesh;
final double hMesh = (numY - 1) * springTriangleHeightTwice;
final SpringMesh mesh = new SpringMesh(numX, numY, wMesh, hMesh, param.stiffnessSpringMesh, param.maxStretchSpringMesh * param.bmScale, param.dampSpringMesh);
meshes.add(mesh);
tileMeshMap.put(tile, mesh);
}
// final int blockRadius = Math.max( 32, Util.roundPos( param.springLengthSpringMesh / 2 ) );
final int blockRadius = Math.max(Util.roundPos(16 / param.bmScale), param.bmBlockRadius);
/**
* TODO set this something more than the largest error by the approximate model
*/
final int searchRadius = param.bmSearchRadius;
final AbstractModel<?> localSmoothnessFilterModel = mpicbg.trakem2.align.Util.createModel(param.bmLocalModelIndex);
for (final Triple<AbstractAffineTile2D<?>, AbstractAffineTile2D<?>, InvertibleCoordinateTransform> pair : pairs) {
final AbstractAffineTile2D<?> t1 = pair.a;
final AbstractAffineTile2D<?> t2 = pair.b;
final SpringMesh m1 = tileMeshMap.get(t1);
final SpringMesh m2 = tileMeshMap.get(t2);
final ArrayList<PointMatch> pm12 = new ArrayList<PointMatch>();
final ArrayList<PointMatch> pm21 = new ArrayList<PointMatch>();
final ArrayList<Vertex> v1 = m1.getVertices();
final ArrayList<Vertex> v2 = m2.getVertices();
final String patchName1 = patchName(t1.getPatch());
final String patchName2 = patchName(t2.getPatch());
final PatchImage pi1 = t1.getPatch().createTransformedImage();
if (pi1 == null) {
Utils.log("Patch `" + patchName1 + "' failed generating a transformed image. Skipping...");
continue;
}
final PatchImage pi2 = t2.getPatch().createTransformedImage();
if (pi2 == null) {
Utils.log("Patch `" + patchName2 + "' failed generating a transformed image. Skipping...");
continue;
}
final FloatProcessor fp1 = (FloatProcessor) pi1.target.convertToFloat();
final ByteProcessor mask1 = pi1.getMask();
final FloatProcessor fpMask1 = mask1 == null ? null : scaleByte(mask1);
final FloatProcessor fp2 = (FloatProcessor) pi2.target.convertToFloat();
final ByteProcessor mask2 = pi2.getMask();
final FloatProcessor fpMask2 = mask2 == null ? null : scaleByte(mask2);
if (!fixedTiles.contains(t1)) {
BlockMatching.matchByMaximalPMCC(fp1, fp2, fpMask1, fpMask2, param.bmScale, pair.c, blockRadius, blockRadius, searchRadius, searchRadius, param.bmMinR, param.bmRodR, param.bmMaxCurvatureR, v1, pm12, new ErrorStatistic(1));
if (param.bmUseLocalSmoothnessFilter) {
Utils.log("`" + patchName1 + "' > `" + patchName2 + "': found " + pm12.size() + " correspondence candidates.");
localSmoothnessFilterModel.localSmoothnessFilter(pm12, pm12, param.bmLocalRegionSigma, param.bmMaxLocalEpsilon, param.bmMaxLocalTrust);
Utils.log("`" + patchName1 + "' > `" + patchName2 + "': " + pm12.size() + " candidates passed local smoothness filter.");
} else {
Utils.log("`" + patchName1 + "' > `" + patchName2 + "': found " + pm12.size() + " correspondences.");
}
} else {
Utils.log("Skipping fixed patch `" + patchName1 + "'.");
}
if (!fixedTiles.contains(t2)) {
BlockMatching.matchByMaximalPMCC(fp2, fp1, fpMask2, fpMask1, param.bmScale, pair.c.createInverse(), blockRadius, blockRadius, searchRadius, searchRadius, param.bmMinR, param.bmRodR, param.bmMaxCurvatureR, v2, pm21, new ErrorStatistic(1));
if (param.bmUseLocalSmoothnessFilter) {
Utils.log("`" + patchName1 + "' < `" + patchName2 + "': found " + pm21.size() + " correspondence candidates.");
localSmoothnessFilterModel.localSmoothnessFilter(pm21, pm21, param.bmLocalRegionSigma, param.bmMaxLocalEpsilon, param.bmMaxLocalTrust);
Utils.log("`" + patchName1 + "' < `" + patchName2 + "': " + pm21.size() + " candidates passed local smoothness filter.");
} else {
Utils.log("`" + patchName1 + "' < `" + patchName2 + "': found " + pm21.size() + " correspondences.");
}
} else {
Utils.log("Skipping fixed patch `" + patchName2 + "'.");
}
for (final PointMatch pm : pm12) {
final Vertex p1 = (Vertex) pm.getP1();
final Vertex p2 = new Vertex(pm.getP2());
p1.addSpring(p2, new Spring(0, 1.0f));
m2.addPassiveVertex(p2);
}
for (final PointMatch pm : pm21) {
final Vertex p1 = (Vertex) pm.getP1();
final Vertex p2 = new Vertex(pm.getP2());
p1.addSpring(p2, new Spring(0, 1.0f));
m1.addPassiveVertex(p2);
}
}
/* initialize */
for (final Map.Entry<AbstractAffineTile2D<?>, SpringMesh> entry : tileMeshMap.entrySet()) entry.getValue().init(entry.getKey().getModel());
/* optimize the meshes */
try {
final long t0 = System.currentTimeMillis();
IJ.log("Optimizing spring meshes...");
if (param.useLegacyOptimizer) {
Utils.log(" ...using legacy optimizer...");
SpringMesh.optimizeMeshes2(meshes, param.po.maxEpsilon, param.maxIterationsSpringMesh, param.maxPlateauwidthSpringMesh, param.visualize);
} else {
SpringMesh.optimizeMeshes(meshes, param.po.maxEpsilon, param.maxIterationsSpringMesh, param.maxPlateauwidthSpringMesh, param.visualize);
}
IJ.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;
}
/* apply */
for (final Map.Entry<AbstractAffineTile2D<?>, SpringMesh> entry : tileMeshMap.entrySet()) {
final AbstractAffineTile2D<?> tile = entry.getKey();
if (!fixedTiles.contains(tile)) {
final Patch patch = tile.getPatch();
final SpringMesh mesh = entry.getValue();
final Set<PointMatch> matches = mesh.getVA().keySet();
Rectangle box = patch.getCoordinateTransformBoundingBox();
/* compensate for existing coordinate transform bounding box */
for (final PointMatch pm : matches) {
final Point p1 = pm.getP1();
final double[] l = p1.getL();
l[0] += box.x;
l[1] += box.y;
}
final ThinPlateSplineTransform mlt = ElasticLayerAlignment.makeTPS(matches);
patch.appendCoordinateTransform(mlt);
box = patch.getCoordinateTransformBoundingBox();
patch.getAffineTransform().setToTranslation(box.x, box.y);
patch.updateInDatabase("transform");
patch.updateBucket();
patch.updateMipMaps();
}
}
Utils.log("Done.");
}
use of mpicbg.models.PointMatch in project TrakEM2 by trakem2.
the class AbstractAffineTile2D method makeVirtualConnection.
/**
* Add a virtual {@linkplain PointMatch connection} between two
* {@linkplain AbstractAffineTile2D Tiles}. The
* {@linkplain PointMatch connection} is placed in the center of the
* intersection area of both tiles.
*
* TODO Not yet tested---Do we need these virtual connections?
*
* @param t
*/
public final void makeVirtualConnection(final AbstractAffineTile2D<?> t) {
final Area a = new Area(patch.getPerimeter());
final Area b = new Area(t.patch.getPerimeter());
a.intersect(b);
final double[] fa = new double[2];
int i = 0;
final double[] coords = new double[6];
final PathIterator p = a.getPathIterator(null);
while (!p.isDone()) {
p.currentSegment(coords);
fa[0] += coords[0];
fa[1] += coords[1];
++i;
p.next();
}
if (i > 0) {
fa[0] /= i;
fa[1] /= i;
final double[] fb = fa.clone();
try {
model.applyInverseInPlace(fa);
t.model.applyInverseInPlace(fb);
} catch (final NoninvertibleModelException e) {
return;
}
final Point pa = new Point(fa);
final Point pb = new Point(fb);
final PointMatch ma = new PointMatch(pa, pb, 0.1f);
final PointMatch mb = new PointMatch(pb, pa, 0.1f);
addVirtualMatch(ma);
addConnectedTile(t);
t.addVirtualMatch(mb);
t.addConnectedTile(this);
}
}
Aggregations