use of mpi.fruitfly.math.datastructures.FloatArray2D in project TrakEM2 by trakem2.
the class StitchingTEM method makeStripe.
// static public ImageProcessor makeStripe(final Patch p, final double scale, final boolean ignore_patch_transform) {
// return makeStripe(p, null, scale, ignore_patch_transform);
// }
/**
* @return FloatProcessor.
* @param ignore_patch_transform will prevent resizing of the ImageProcessor in the event of the Patch having a transform different than identity.
*/
// TODO 2: there is a combination of options that ends up resulting in the actual ImageProcessor of the Patch being returned as is, which is DANGEROUS because it can potentially result in changes in the data.
public static ImageProcessor makeStripe(final Patch p, final Roi roi, final double scale, final boolean ignore_patch_transform) {
ImagePlus imp = null;
ImageProcessor ip = null;
final Loader loader = p.getProject().getLoader();
// check if using mipmaps and if there is a file for it. If there isn't, most likely this method is being called in an import sequence as grid procedure.
if (loader.isMipMapsRegenerationEnabled() && loader.checkMipMapFileExists(p, scale)) {
// Read the transform image from the patch (this way we avoid the JPEG artifacts)
final Patch.PatchImage pai = p.createTransformedImage();
pai.target.setMinAndMax(p.getMin(), p.getMax());
// p.getProject().getLoader().fetchImage(p, scale);
Image image = pai.target.createImage();
// Utils.log2("patch w,h " + p.getWidth() + ", " + p.getHeight() + " fetched image w,h: " + image.getWidth(null) + ", " + image.getHeight(null));
if (Math.abs(p.getWidth() * scale - image.getWidth(null)) > 0.001 || Math.abs(p.getHeight() * scale - image.getHeight(null)) > 0.001) {
// slow but good quality. Makes an RGB image, but it doesn't matter.
image = image.getScaledInstance((int) (p.getWidth() * scale), (int) (p.getHeight() * scale), Image.SCALE_AREA_AVERAGING);
// Utils.log2(" resizing, now image w,h: " + image.getWidth(null) + ", " + image.getHeight(null));
}
try {
imp = new ImagePlus("s", image);
ip = imp.getProcessor();
// imp.show();
} catch (final Exception e) {
IJError.print(e);
}
// cut
if (null != roi) {
// scale ROI!
Rectangle rb = roi.getBounds();
final Roi roi2 = new Roi((int) (rb.x * scale), (int) (rb.y * scale), (int) (rb.width * scale), (int) (rb.height * scale));
rb = roi2.getBounds();
if (ip.getWidth() != rb.width || ip.getHeight() != rb.height) {
ip.setRoi(roi2);
ip = ip.crop();
}
}
// Utils.log2("scale: " + scale + " ip w,h: " + ip.getWidth() + ", " + ip.getHeight());
} else {
final Patch.PatchImage pai = p.createTransformedImage();
pai.target.setMinAndMax(p.getMin(), p.getMax());
ip = pai.target;
imp = new ImagePlus("", ip);
// compare and adjust
if (!ignore_patch_transform && p.getAffineTransform().getType() != AffineTransform.TYPE_TRANSLATION) {
// if it's not only a translation:
final Rectangle b = p.getBoundingBox();
ip = ip.resize(b.width, b.height);
// Utils.log2("resizing stripe for patch: " + p);
// the above is only meant to correct for improperly acquired images at the microscope, the scale only.
}
// cut
if (null != roi) {
final Rectangle rb = roi.getBounds();
if (ip.getWidth() != rb.width || ip.getHeight() != rb.height) {
ip.setRoi(roi);
ip = ip.crop();
}
}
// scale
if (scale < 1) {
// floats have 4 bytes, plus some java peripherals correction factor
p.getProject().getLoader().releaseToFit((long) (ip.getWidth() * ip.getHeight() * 4 * 1.2));
ip = ip.convertToFloat();
// scaling with area averaging is the same as a gaussian of sigma 0.5/scale and then resize with nearest neightbor So this line does the gaussian, and line below does the neares-neighbor scaling
ip.setPixels(ImageFilter.computeGaussianFastMirror(new FloatArray2D((float[]) ip.getPixels(), ip.getWidth(), ip.getHeight()), Math.sqrt(0.25 / scale / scale - 0.25)).data);
// scale maintaining aspect ratio
ip = ip.resize((int) (ip.getWidth() * scale));
}
}
// return a FloatProcessor
if (imp.getType() != ImagePlus.GRAY32)
return ip.convertToFloat();
return ip;
}
use of mpi.fruitfly.math.datastructures.FloatArray2D in project TrakEM2 by trakem2.
the class CrossCorrelation2D method computeCrossCorrelationMT.
/**
* Computes a translational registration with the help of the cross correlation measure. <br>
* Limits the overlap to 30% and restricts the shift furthermore by a factor you can tell him
* (this is useful if you f. ex. know that the vertical shift is much less than the horizontal).
*
* NOTE: Works multithreaded
*
* @param relMinOverlapX double - if you want to scan for less possible translations seen from a direct overlay,
* give the relative factor here (e.g. 0.3 means DONOT scan the outer 30%)
* NOTE: Below 0.05 does not really make sense as you then compare only very few pixels (even one) on the edges
* which gives then an R of 1 (perfect match)
* @param relMinOverlapY double - if you want to scan for less possible translations seen from a direct overlay,
* give the relative factor here (e.g. 0.3 means DONOT scan the outer 30%)
* NOTE: Below 0.05 does not really make sense as you then compare only very few pixels (even one) on the edges
* which gives then an R of 1 (perfect match)
* @param showImages boolean - Show the result of the cross correlation translation
* @return double[] return a double array containing {displaceX, displaceY, R}
*/
public double[] computeCrossCorrelationMT(final double relMinOverlapX, final double relMinOverlapY, final boolean showImages) {
// final double relMinOverlap = 0.30;
final int w1 = img1.width;
final int w2 = img2.width;
final int h1 = img1.height;
final int h2 = img2.height;
final int min_border_w = (int) (w1 < w2 ? w1 * relMinOverlapX + 0.5 : w2 * relMinOverlapX + 0.5);
final int min_border_h = (int) (h1 < h2 ? h1 * relMinOverlapY + 0.5 : h2 * relMinOverlapY + 0.5);
/*System.out.println(w1 + " " + h1 + " " + w2 + " " + h2);
System.out.println(min_border_w + " " + min_border_h);
System.out.println("Y [" + (-h2 + min_border_h) + " , " + (h1 - min_border_h) + "]");*/
final AtomicInteger ai = new AtomicInteger(-w1 + min_border_w);
Thread[] threads = MultiThreading.newThreads();
for (int ithread = 0; ithread < threads.length; ++ithread) threads[ithread] = new Thread(new Runnable() {
public void run() {
for (int moveX = ai.getAndIncrement(); moveX < w2 - min_border_w; moveX = ai.getAndIncrement()) {
for (int moveY = -h1 + min_border_h; moveY < h2 - min_border_h; moveY++) {
// compute average
double avg1 = 0, avg2 = 0;
int count = 0;
double value1, value2;
// for (int x1 = 0; x1 < w1; x1++)
for (int x1 = -min(0, moveX); x1 < min(w1, w2 - moveX); x1++) {
int x2 = x1 + moveX;
// for (int y1 = 0; y1 < h1; y1++)
for (int y1 = -min(0, moveY); y1 < min(h1, h2 - moveY); y1++) {
int y2 = y1 + moveY;
/*if (y2 < 0 || y2 > h2 - 1)
continue;*/
value1 = img1.get(x1, y1);
if (value1 == -1)
continue;
value2 = img2.get(x2, y2);
if (value2 == -1)
continue;
avg1 += value1;
avg2 += value2;
count++;
}
}
if (0 == count)
continue;
avg1 /= (double) count;
avg2 /= (double) count;
double var1 = 0, var2 = 0;
double coVar = 0;
double dist1, dist2;
// for (int x1 = 0; x1 < w1; x1++)
for (int x1 = -min(0, moveX); x1 < min(w1, w2 - moveX); x1++) {
int x2 = x1 + moveX;
// for (int y1 = 0; y1 < h1; y1++)
for (int y1 = -min(0, moveY); y1 < min(h1, h2 - moveY); y1++) {
int y2 = y1 + moveY;
/*if (y2 < 0 || y2 > h2 - 1)
continue;*/
value1 = img1.get(x1, y1);
if (value1 == -1)
continue;
value2 = img2.get(x2, y2);
if (value2 == -1)
continue;
dist1 = value1 - avg1;
dist2 = value2 - avg2;
coVar += dist1 * dist2;
var1 += dist1 * dist1;
var2 += dist2 * dist2;
}
}
var1 /= (double) count;
var2 /= (double) count;
coVar /= (double) count;
double stDev1 = Math.sqrt(var1);
double stDev2 = Math.sqrt(var2);
// compute correlation coeffienct
double R = coVar / (stDev1 * stDev2);
compareAndSetR(R, moveX, moveY);
if (R < -1 || R > 1) {
System.out.println("BIG ERROR! R =" + R);
}
}
// System.out.println(moveX + " [" + (-w2 + min_border_w) + ", " + (w1 - min_border_w) + "] + best R: " + maxR + " " + displaceX + " " + displaceY);
}
}
});
MultiThreading.startAndJoin(threads);
if (showImages) {
System.out.println(-displaceX + " " + -displaceY + " " + maxR);
FloatArray2D result = drawTranslatedImages(img1, img2, new Point(-displaceX, -displaceY), DRAWTYPE_OVERLAP);
FloatArrayToImagePlus(result, "result", 0, 0).show();
}
return new double[] { -displaceX, -displaceY, maxR };
}
use of mpi.fruitfly.math.datastructures.FloatArray2D in project TrakEM2 by trakem2.
the class ImageFilter method distortSamplingY.
public static FloatArray2D distortSamplingY(final FloatArray2D input) {
final FloatArray2D output = new FloatArray2D(input.width, input.height);
final int filterSize = 3;
float avg;
final Random rnd = new Random(7893469);
for (int y = 0; y < input.height; y++) {
final FloatArray2D kernel = new FloatArray2D(1, 3);
final float random = (rnd.nextFloat() - 0.5f) * 2;
float val1, val2, val3;
if (random < 0) {
val1 = -random;
val2 = 1 + random;
val3 = 0;
} else {
val3 = random;
val2 = 1 - random;
val1 = 0;
}
kernel.set(val1, 0, 0);
kernel.set(val2, 0, 1);
kernel.set(val3, 0, 2);
for (int x = 0; x < input.width; x++) {
avg = 0;
for (int fy = -filterSize / 2; fy <= filterSize / 2; fy++) {
try {
avg += input.get(x, y + fy) * kernel.get(0, fy + filterSize / 2);
} catch (final Exception e) {
}
;
}
output.set(avg, x, y);
}
}
return output;
}
use of mpi.fruitfly.math.datastructures.FloatArray2D in project TrakEM2 by trakem2.
the class ImageFilter method distortSamplingX.
public static FloatArray2D distortSamplingX(final FloatArray2D input) {
final FloatArray2D output = new FloatArray2D(input.width, input.height);
final int filterSize = 3;
float avg;
final Random rnd = new Random(353245632);
for (int x = 0; x < input.width; x++) {
final FloatArray2D kernel = new FloatArray2D(3, 1);
final float random = (rnd.nextFloat() - 0.5f) * 2;
float val1, val2, val3;
if (random < 0) {
val1 = -random;
val2 = 1 + random;
val3 = 0;
} else {
val3 = random;
val2 = 1 - random;
val1 = 0;
}
kernel.set(val1, 0, 0);
kernel.set(val2, 1, 0);
kernel.set(val3, 2, 0);
for (int y = 0; y < input.height; y++) {
avg = 0;
for (int fx = -filterSize / 2; fx <= filterSize / 2; fx++) {
try {
avg += input.get(x + fx, y) * kernel.get(fx + filterSize / 2, 0);
} catch (final Exception e) {
}
;
}
output.set(avg, x, y);
}
}
return output;
}
use of mpi.fruitfly.math.datastructures.FloatArray2D in project TrakEM2 by trakem2.
the class ImageFilter method computeGaussianFastMirror.
public static FloatArray2D computeGaussianFastMirror(final FloatArray2D input, final double sigma) {
final FloatArray2D output = new FloatArray2D(input.width, input.height);
float avg, kernelsum = 0;
final float[] kernel = createGaussianKernel1D(sigma, true);
final int filterSize = kernel.length;
// get kernel sum
for (final double value : kernel) kernelsum += value;
// fold in x
for (int x = 0; x < input.width; x++) for (int y = 0; y < input.height; y++) {
avg = 0;
if (x - filterSize / 2 >= 0 && x + filterSize / 2 < input.width)
for (int f = -filterSize / 2; f <= filterSize / 2; f++) avg += input.get(x + f, y) * kernel[f + filterSize / 2];
else
for (int f = -filterSize / 2; f <= filterSize / 2; f++) avg += input.getMirror(x + f, y) * kernel[f + filterSize / 2];
output.set(avg / kernelsum, x, y);
}
// fold in y
final float[] temp = new float[input.height];
for (int x = 0; x < input.width; x++) {
for (int y = 0; y < input.height; y++) {
avg = 0;
if (y - filterSize / 2 >= 0 && y + filterSize / 2 < input.height)
for (int f = -filterSize / 2; f <= filterSize / 2; f++) avg += output.get(x, y + f) * kernel[f + filterSize / 2];
else
for (int f = -filterSize / 2; f <= filterSize / 2; f++) avg += output.getMirror(x, y + f) * kernel[f + filterSize / 2];
temp[y] = avg / kernelsum;
}
for (int y = 0; y < input.height; y++) output.set(temp[y], x, y);
}
return output;
}
Aggregations