use of mpicbg.models.TranslationModel2D in project TrakEM2 by trakem2.
the class MovingLeastSquaresTransform method init.
@Override
public final void init(final String data) throws NumberFormatException {
matches.clear();
final String[] fields = data.split("\\s+");
if (fields.length > 3) {
final int d = Integer.parseInt(fields[1]);
if ((fields.length - 3) % (2 * d + 1) == 0) {
if (d == 2) {
if (fields[0].equals("translation"))
model = new TranslationModel2D();
else if (fields[0].equals("rigid"))
model = new RigidModel2D();
else if (fields[0].equals("similarity"))
model = new SimilarityModel2D();
else if (fields[0].equals("affine"))
model = new AffineModel2D();
else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
} else if (d == 3) {
if (fields[0].equals("affine"))
model = new AffineModel3D();
else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
} else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
alpha = Double.parseDouble(fields[2]);
int i = 2;
while (i < fields.length - 1) {
final double[] p1 = new double[d];
for (int k = 0; k < d; ++k) p1[k] = Double.parseDouble(fields[++i]);
final double[] p2 = new double[d];
for (int k = 0; k < d; ++k) p2[k] = Double.parseDouble(fields[++i]);
final double weight = Double.parseDouble(fields[++i]);
final PointMatch m = new PointMatch(new Point(p1), new Point(p2), weight);
matches.add(m);
}
} else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
} else
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
}
use of mpicbg.models.TranslationModel2D in project TrakEM2 by trakem2.
the class MovingLeastSquaresTransform2 method init2.
public void init2(final String s) throws Exception {
// WARNING: assumes all whitespace is single
final int len = s.length();
int i = 0;
// Advance to the first white space
while (' ' != s.charAt(++i)) {
}
// Interpret model by the last letter of the name
final char modelLastChar = s.charAt(i - 1);
// Determine dimension 2 or 3
final int n = (s.charAt(i + 1)) - 48;
switch(n) {
case 3:
model = new AffineModel3D();
break;
case 2:
switch(modelLastChar) {
case // translation
'n':
model = new TranslationModel2D();
break;
case // rigid
'd':
model = new RigidModel2D();
break;
case // similarity
'y':
model = new SimilarityModel2D();
break;
case // affine
'e':
model = new AffineModel2D();
break;
default:
throw new Exception("Unknown model " + s.substring(0, i));
}
break;
default:
throw new NumberFormatException("Unsupported model dimensions: " + n + " for " + this.getClass().getCanonicalName());
}
// 'i' is at whitespace before n
// Move i to whitespace before alpha
i += 2;
// Mark last char before whitespace
int cut = i - 1;
// 'i' ends up at the whitespace after alpha
while (' ' != s.charAt(++i)) {
}
// Parse alpha
float[] f = new float[1];
parse(s, cut, i - 1, f, 0);
this.alpha = f[0];
// Count numbers by counting one whitespace before each number
int nVals = 0;
for (int k = i; k < len; ++k) {
if (' ' == s.charAt(k))
++nVals;
}
// The size of a unit of numbers
final int cell = n + n + 1;
// Detect inconsistency:
if (0 != nVals % cell) {
throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
}
// Create arrays
this.p = new float[n][nVals / cell];
this.q = new float[n][this.p[0].length];
this.w = new float[this.p[0].length];
// Mark the whitespace char before the first number
cut = i - 1;
// Start parsing from the end
i = len - 1;
int count = 0;
if (2 == n) {
while (i > cut) {
// Determine which array from {p,q,w} and which position in the array, using n and count:
switch(// n for dimensions, +1 for the weight
count % cell) {
case 0:
f = this.w;
break;
case 1:
f = this.q[1];
break;
case 2:
f = this.q[0];
break;
case 3:
f = this.p[1];
break;
case 4:
f = this.p[0];
break;
}
i = parse(s, cut, i, f, this.w.length - (count / cell) - 1);
++count;
}
} else {
while (i > cut) {
// Determine which array from {p,q,w} and which position in the array, using n and count:
switch(// n for dimensions, +1 for the weight
count % (n + n + 1)) {
case 0:
f = this.w;
break;
case 1:
f = this.q[2];
break;
case 2:
f = this.q[1];
break;
case 3:
f = this.q[0];
break;
case 4:
f = this.p[2];
break;
case 5:
f = this.p[1];
break;
case 6:
f = this.p[0];
break;
}
i = parse(s, cut, i, f, this.w.length - (count / cell) - 1);
++count;
}
}
}
use of mpicbg.models.TranslationModel2D in project TrakEM2 by trakem2.
the class StitchingTEM method montageWithPhaseCorrelation.
/**
* Perform montage based on phase correlation
* @param col collection of patches
* @param param phase correlation parameters
*/
public static void montageWithPhaseCorrelation(final Collection<Patch> col, final PhaseCorrelationParam param) {
if (null == col || col.size() < 1)
return;
final ArrayList<Patch> al = new ArrayList<Patch>(col);
final ArrayList<AbstractAffineTile2D<?>> tiles = new ArrayList<AbstractAffineTile2D<?>>();
final ArrayList<AbstractAffineTile2D<?>> fixed_tiles = new ArrayList<AbstractAffineTile2D<?>>();
for (final Patch p : al) {
// Pre-check: just a warning
final int aff_type = p.getAffineTransform().getType();
switch(p.getAffineTransform().getType()) {
case AffineTransform.TYPE_IDENTITY:
case AffineTransform.TYPE_TRANSLATION:
// ok
break;
default:
Utils.log2("WARNING: patch with a non-translation transform: " + p);
break;
}
// create tiles
final TranslationTile2D tile = new TranslationTile2D(new TranslationModel2D(), p);
tiles.add(tile);
if (p.isLocked2()) {
Utils.log("Added fixed (locked) tile " + p);
fixed_tiles.add(tile);
}
}
// Get acceptable values
double cc_scale = param.cc_scale;
if (cc_scale < 0 || cc_scale > 1) {
Utils.log("Unacceptable cc_scale of " + param.cc_scale + ". Using 1 instead.");
cc_scale = 1;
}
float overlap = param.overlap;
if (overlap < 0 || overlap > 1) {
Utils.log("Unacceptable overlap of " + param.overlap + ". Using 1 instead.");
overlap = 1;
}
for (int i = 0; i < al.size(); i++) {
final Patch p1 = al.get(i);
final Rectangle r1 = p1.getBoundingBox();
// find overlapping, add as connections
for (int j = i + 1; j < al.size(); j++) {
if (Thread.currentThread().isInterrupted())
return;
final Patch p2 = al.get(j);
final Rectangle r2 = p2.getBoundingBox();
if (r1.intersects(r2)) {
// Skip if it's a diagonal overlap
final int dx = Math.abs(r1.x - r2.x);
final int dy = Math.abs(r1.y - r2.y);
if (dx > r1.width / 2 && dy > r1.height / 2) {
// skip diagonal match
Utils.log2("Skipping diagonal overlap between " + p1 + " and " + p2);
continue;
}
p1.getProject().getLoader().releaseToFit((long) (p1.getWidth() * p1.getHeight() * 25));
final double[] R;
if (1 == overlap) {
R = correlate(p1, p2, overlap, cc_scale, TOP_BOTTOM, 0, 0, param.min_R);
if (SUCCESS == R[2]) {
addMatches(tiles.get(i), tiles.get(j), R[0], R[1]);
}
} else {
switch(getClosestOverlapLocation(p1, p2)) {
case // p1 overlaps p2 from the left
0:
R = correlate(p1, p2, overlap, cc_scale, LEFT_RIGHT, 0, 0, param.min_R);
if (SUCCESS == R[2]) {
addMatches(tiles.get(i), tiles.get(j), R[0], R[1]);
}
break;
case // p1 overlaps p2 from the top
1:
R = correlate(p1, p2, overlap, cc_scale, TOP_BOTTOM, 0, 0, param.min_R);
if (SUCCESS == R[2]) {
addMatches(tiles.get(i), tiles.get(j), R[0], R[1]);
}
break;
case // p1 overlaps p2 from the right
2:
R = correlate(p2, p1, overlap, cc_scale, LEFT_RIGHT, 0, 0, param.min_R);
if (SUCCESS == R[2]) {
addMatches(tiles.get(j), tiles.get(i), R[0], R[1]);
}
break;
case // p1 overlaps p2 from the bottom
3:
R = correlate(p2, p1, overlap, cc_scale, TOP_BOTTOM, 0, 0, param.min_R);
if (SUCCESS == R[2]) {
addMatches(tiles.get(j), tiles.get(i), R[0], R[1]);
}
break;
default:
Utils.log("Unknown overlap direction!");
continue;
}
}
}
}
}
if (param.remove_disconnected || param.hide_disconnected) {
for (final Iterator<AbstractAffineTile2D<?>> it = tiles.iterator(); it.hasNext(); ) {
final AbstractAffineTile2D<?> t = it.next();
if (null != t.getMatches() && t.getMatches().isEmpty()) {
if (param.hide_disconnected)
t.getPatch().setVisible(false);
else if (param.remove_disconnected)
t.getPatch().remove(false);
it.remove();
}
}
}
// Optimize tile configuration by removing bad matches
optimizeTileConfiguration(tiles, fixed_tiles, param);
for (final AbstractAffineTile2D<?> t : tiles) t.getPatch().setAffineTransform(t.getModel().createAffine());
try {
Display.repaint(al.get(0).getLayer());
} catch (final Exception e) {
}
}
use of mpicbg.models.TranslationModel2D in project TrakEM2 by trakem2.
the class Distortion_Correction method extractSIFTPointsThreaded.
protected static void extractSIFTPointsThreaded(final int index, final List<Feature>[] siftFeatures, final List<PointMatch>[] inliers, final AbstractAffineModel2D<?>[] models) {
// save all matching candidates
final List<PointMatch>[] candidates = new List[siftFeatures.length - 1];
final Thread[] threads = MultiThreading.newThreads();
// start at second
final AtomicInteger ai = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ++ithread) {
threads[ithread] = new Thread() {
@Override
public void run() {
setPriority(Thread.NORM_PRIORITY);
for (int j = ai.getAndIncrement(); j < candidates.length; j = ai.getAndIncrement()) {
final int i = (j < index ? j : j + 1);
candidates[j] = FloatArray2DSIFT.createMatches(siftFeatures[index], siftFeatures[i], 1.5f, null, Float.MAX_VALUE, 0.5f);
}
}
};
}
MultiThreading.startAndJoin(threads);
// get rid of the outliers and save the rigid transformations to match
// the inliers
final AtomicInteger ai2 = new AtomicInteger(0);
for (int ithread = 0; ithread < threads.length; ++ithread) {
threads[ithread] = new Thread() {
@Override
public void run() {
setPriority(Thread.NORM_PRIORITY);
for (int i = ai2.getAndIncrement(); i < candidates.length; i = ai2.getAndIncrement()) {
final List<PointMatch> tmpInliers = new ArrayList<PointMatch>();
// RigidModel2D m =
// RigidModel2D.estimateBestModel(candidates.get(i),
// tmpInliers, sp.min_epsilon, sp.max_epsilon,
// sp.min_inlier_ratio);
final AbstractAffineModel2D<?> m;
switch(sp.expectedModelIndex) {
case 0:
m = new TranslationModel2D();
break;
case 1:
m = new RigidModel2D();
break;
case 2:
m = new SimilarityModel2D();
break;
case 3:
m = new AffineModel2D();
break;
default:
return;
}
boolean modelFound = false;
try {
modelFound = m.filterRansac(candidates[i], tmpInliers, 1000, sp.maxEpsilon, sp.minInlierRatio, 10);
} catch (final NotEnoughDataPointsException e) {
modelFound = false;
}
if (modelFound)
IJ.log("Model found:\n " + candidates[i].size() + " candidates\n " + tmpInliers.size() + " inliers\n " + String.format("%.2f", m.getCost()) + "px average displacement");
else
IJ.log("No Model found.");
inliers[index * (sp.numberOfImages - 1) + i] = tmpInliers;
models[index * (sp.numberOfImages - 1) + i] = m;
// System.out.println("**** MODEL ADDED: " +
// (index*(sp.numberOfImages-1)+i));
}
}
};
}
MultiThreading.startAndJoin(threads);
}
use of mpicbg.models.TranslationModel2D in project TrakEM2 by trakem2.
the class Distortion_Correction method extractSIFTPoints.
protected void extractSIFTPoints(final int index, final List<Feature>[] siftFeatures, final List<List<PointMatch>> inliers, final List<AbstractAffineModel2D<?>> models) {
// save all matching candidates
final List<List<PointMatch>> candidates = new ArrayList<List<PointMatch>>();
for (int j = 0; j < siftFeatures.length; j++) {
if (index == j)
continue;
candidates.add(FloatArray2DSIFT.createMatches(siftFeatures[index], siftFeatures[j], 1.5f, null, Float.MAX_VALUE, 0.5f));
}
// get rid of the outliers and save the transformations to match the inliers
for (int i = 0; i < candidates.size(); ++i) {
final List<PointMatch> tmpInliers = new ArrayList<PointMatch>();
final AbstractAffineModel2D<?> m;
switch(sp.expectedModelIndex) {
case 0:
m = new TranslationModel2D();
break;
case 1:
m = new RigidModel2D();
break;
case 2:
m = new SimilarityModel2D();
break;
case 3:
m = new AffineModel2D();
break;
default:
return;
}
try {
m.filterRansac(candidates.get(i), tmpInliers, 1000, sp.maxEpsilon, sp.minInlierRatio, 10);
} catch (final NotEnoughDataPointsException e) {
e.printStackTrace();
}
inliers.add(tmpInliers);
models.add(m);
}
}
Aggregations