use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class AlignTask method alignSelection.
public static final void alignSelection(final Selection selection, final int m) throws Exception {
final List<Patch> patches = new ArrayList<Patch>();
for (final Displayable d : selection.getSelected()) if (d instanceof Patch)
patches.add((Patch) d);
final HashSet<Patch> fixedPatches = new HashSet<Patch>();
// Add active Patch, if any, as the nail
final Displayable active = selection.getActive();
if (null != active && active instanceof Patch)
fixedPatches.add((Patch) active);
// Add all locked Patch instances to fixedPatches
for (final Patch patch : patches) if (patch.isLocked())
fixedPatches.add(patch);
alignPatches(patches, fixedPatches, m);
}
use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class AlignTask method alignPatchesTask.
public static final Bureaucrat alignPatchesTask(final List<Patch> patches, final Set<Patch> fixedPatches) {
if (0 == patches.size()) {
Utils.log("Can't align zero patches.");
return null;
}
final Worker worker = new Worker("Aligning images", false, true) {
@Override
public void run() {
startedWorking();
try {
final int m = chooseAlignmentMode();
if (-1 == m)
return;
alignPatches(patches, fixedPatches, m);
Display.repaint();
} catch (final Throwable e) {
IJError.print(e);
} finally {
finishedWorking();
}
}
@Override
public void cleanup() {
patches.get(0).getLayer().getParent().undoOneStep();
}
};
return Bureaucrat.createAndStart(worker, patches.get(0).getProject());
}
use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class AlignTask method transformPatchesAndVectorData.
/**
* For registering within the same project instance.
*/
public static final void transformPatchesAndVectorData(final Collection<Patch> patches, final Runnable alignment) {
if (patches.isEmpty()) {
Utils.log("No patches to align!");
return;
}
// 1 - Collect all VectorData to transform
final ArrayList<Displayable> vdata = new ArrayList<Displayable>();
final LayerSet ls = patches.iterator().next().getLayerSet();
for (final Layer layer : ls.getLayers()) {
vdata.addAll(layer.getDisplayables(VectorData.class, false, true));
}
vdata.addAll(ls.getZDisplayables(VectorData.class, true));
// Perhaps none:
if (vdata.isEmpty()) {
alignment.run();
return;
}
// 2 - Store current transformation of each Patch under any VectorData
final HashSet<Long> lids = new HashSet<Long>();
for (final Patch p : patches) lids.add(p.getLayer().getId());
final ReferenceData rd = createTransformPropertiesTable(vdata, null, lids);
// 3 - Align:
alignment.run();
// 4 - Transform VectorData instances to match the position of the Patch instances over which they were defined
if (null != rd && !vdata.isEmpty())
transformVectorData(rd, vdata, ls);
}
use of ini.trakem2.display.Patch 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 ini.trakem2.display.Patch in project TrakEM2 by trakem2.
the class ElasticLayerAlignment method exec.
/**
* Stateful. Changing the parameters of this instance. Do not use in parallel.
*
* @param layerRange
* @param fixedLayers
* @param propagateTransformBefore
* @param propagateTransformAfter
* @param fov
* @param filter
* @throws Exception
*/
public final void exec(final Project project, final List<Layer> layerRange, final Set<Layer> fixedLayers, final boolean propagateTransformBefore, final boolean propagateTransformAfter, final Rectangle fov, final Filter<Patch> filter) throws Exception {
Rectangle box = null;
final HashSet<Layer> emptyLayers = new HashSet<Layer>();
for (final Iterator<Layer> it = layerRange.iterator(); it.hasNext(); ) {
/* remove empty layers */
final Layer la = it.next();
if (!la.contains(Patch.class, true)) {
emptyLayers.add(la);
// it.remove();
} else {
/* accumulate boxes */
if (// The first layer:
null == box)
box = la.getMinimalBoundingBox(Patch.class, true);
else
box = box.union(la.getMinimalBoundingBox(Patch.class, true));
}
}
if (box == null)
box = new Rectangle();
if (fov != null)
box = box.intersection(fov);
if (box.width <= 0 || box.height <= 0) {
Utils.log("Bounding box empty.");
return;
}
if (layerRange.size() == emptyLayers.size()) {
Utils.log("All layers in range are empty!");
return;
}
/* do not work if there is only one layer selected */
if (layerRange.size() - emptyLayers.size() < 2) {
Utils.log("All except one layer in range are empty!");
return;
}
if (!p.setup(box))
return;
exec(p.clone(), project, layerRange, fixedLayers, emptyLayers, box, propagateTransformBefore, propagateTransformAfter, filter);
}
Aggregations