use of mcib3d.geom.Voxel3D in project mcib3d-core by mcib3d.
the class Align2DData method computeRotation2ImagesFHT.
/**
* compute the rotation between 2 images using the Fourier Transform.<BR>
* use the power spectrum to be free of translation<BR>
* then convert to polar coordinate to compute rotation with cross-correlation
*
* @param image1 reference image
* @param image2 image to rotate
* @param range the rotation computed will be between [-range,+range[
* @param angleprecision the precision wanted (1 for degrees precision, 0.1
* for decidegrees precision)
* @return angle in degrees to rotate the second image for it to
* coincide with the first
*/
public static double computeRotation2ImagesFHT(ImageProcessor image1, ImageProcessor image2, double range, double angleprecision) {
// System.out.println("FHT " + image1.getWidth());
ImageProcessor img1 = toPolar(new FHTImage3D(image1).center().getPowerSpectrum(true).getProcessor(1), range, angleprecision);
ImageProcessor img2 = toPolar(new FHTImage3D(image2).center().getPowerSpectrum(true).getProcessor(1), range, angleprecision);
Voxel3D corr = FHTImage3D.getMaxCorrelation(img1, img2);
// IJ.write("max (" + corr.getX() + ", " + corr.getY() + ", " + corr.getZ() + ") =" + corr.getValue());
return -corr.getX() * angleprecision;
// ImageProcessor img1 = new FHTImage3D(image1).center().getPowerSpectrum(true).getProcessor(1);
// ImageProcessor img2 = new FHTImage3D(image2).center().getPowerSpectrum(true).getProcessor(1);
// return computeRotation2Images(img1, img2, range, angleprecision);
}
use of mcib3d.geom.Voxel3D in project mcib3d-core by mcib3d.
the class Segment3DSpots method segmentSpotMax.
/**
* Segment an object from a seed, keep only max local
*
* @param lcThreshold Threshold to connect pixels
* @param val value of the object
* @param xdep x coordinate of the seed
* @param ydep y coordinate of the seed
* @param zdep z coordinate of the seed
* @return true if object cold be segmented
*/
public ArrayList<Voxel3D> segmentSpotMax(int xdep, int ydep, int zdep, int lcThreshold, int val) {
boolean changement = true;
int xfin = xdep + 1;
int yfin = ydep + 1;
int zfin = zdep + 1;
int sens = 1;
if (labelImage == null) {
this.createLabelImage();
}
// pixel already segmented ?
if (labelImage.getPixel(xdep, ydep, zdep) > 0) {
return null;
}
labelImage.setPixel(xdep, ydep, zdep, val);
// volume++;
ArrayList<Voxel3D> object = new ArrayList<Voxel3D>();
object.add(new Voxel3D(xdep, ydep, zdep, val));
int i;
int j;
int k;
int l;
int m;
int n;
ImageHandler original = rawImage;
float pixelCenter;
int waterCenter = 0;
int water = 0;
while (changement) {
changement = false;
for (k = sens == 1 ? zdep : zfin; ((sens == 1 && k <= zfin) || (sens == -1 && k >= zdep)); k += sens) {
for (j = sens == 1 ? ydep : yfin; ((sens == 1 && j <= yfin) || (sens == -1 && j >= ydep)); j += sens) {
for (i = sens == 1 ? xdep : xfin; ((sens == 1 && i <= xfin) || (sens == -1 && i >= xdep)); i += sens) {
if (labelImage.contains(i, j, k) && labelImage.getPixel(i, j, k) == val) {
if (WATERSHED) {
waterCenter = watershedImage.getPixelInt(i, j, k);
}
pixelCenter = original.getPixel(i, j, k);
for (n = k - 1; n < k + 2; n++) {
for (m = j - 1; m < j + 2; m++) {
for (l = i - 1; l < i + 2; l++) {
if (labelImage.contains(l, m, n)) {
if (WATERSHED) {
water = watershedImage.getPixelInt(l, m, n);
}
if ((labelImage.getPixel(l, m, n) == 0) && (original.getPixel(l, m, n) >= lcThreshold) && (original.getPixel(l, m, n) <= pixelCenter) && (water == waterCenter)) {
labelImage.setPixel(l, m, n, val);
// original.putPixel(l, m, n, 0);
// add voxel to object
object.add(new Voxel3D(l, m, n, val));
// update min-max
if (l < xdep) {
xdep--;
}
if (l > xfin) {
xfin++;
}
if (m < ydep) {
ydep--;
}
if (m > yfin) {
yfin++;
}
if (n < zdep) {
zdep--;
}
if (n > zfin) {
zfin++;
}
changement = true;
}
}
}
}
}
}
}
}
}
sens *= -1;
}
return object;
}
use of mcib3d.geom.Voxel3D in project mcib3d-core by mcib3d.
the class Segment3DSpots method segmentSpotBlock.
/**
* @param xdep
* @param ydep
* @param zdep
* @param lcThreshold
* @param val
* @return
*/
public ArrayList<Voxel3D> segmentSpotBlock(int xdep, int ydep, int zdep, int lcThreshold, int val) {
boolean changement = true;
int xfin = xdep + 1;
int yfin = ydep + 1;
int zfin = zdep + 1;
int sens = 1;
if (labelImage == null) {
this.createLabelImage();
}
// pixel already segmented ?
if (labelImage.getPixel(xdep, ydep, zdep) > 0) {
return null;
}
labelImage.setPixel(xdep, ydep, zdep, val);
ArrayList<Voxel3D> object = new ArrayList<Voxel3D>();
object.add(new Voxel3D(xdep, ydep, zdep, val));
int volume = 1;
int i;
int j;
int k;
int l;
int m;
int n;
int sx = rawImage.sizeX;
int sy = rawImage.sizeY;
int sz = rawImage.sizeZ;
ImageHandler original = rawImage;
ArrayList<Voxel3D> neigh;
Iterator it;
Voxel3D tmpneigh;
float pixelCenter;
int waterne = 0, water = 0;
boolean ok;
// int ite = 0;
while (changement) {
// IJ.log("Ite " + ite + " " + xdep + " " + xfin);
// ite++;
changement = false;
for (k = sens == 1 ? zdep : zfin; ((sens == 1 && k <= zfin) || (sens == -1 && k >= zdep)); k += sens) {
for (j = sens == 1 ? ydep : yfin; ((sens == 1 && j <= yfin) || (sens == -1 && j >= ydep)); j += sens) {
for (i = sens == 1 ? xdep : xfin; ((sens == 1 && i <= xfin) || (sens == -1 && i >= xdep)); i += sens) {
if (labelImage.contains(i, j, k) && labelImage.getPixel(i, j, k) == val) {
pixelCenter = original.getPixel(i, j, k);
if (WATERSHED) {
water = watershedImage.getPixelInt(i, j, k);
}
// create neighbors list
neigh = new ArrayList<Voxel3D>();
for (n = k - 1; n < k + 2; n++) {
for (m = j - 1; m < j + 2; m++) {
for (l = i - 1; l < i + 2; l++) {
if ((l >= 0) && (l < sx) && (m >= 0) && (m < sy) && (n >= 0) && (n < sz)) {
if (WATERSHED) {
waterne = watershedImage.getPixelInt(l, m, n);
}
if ((labelImage.getPixel(l, m, n) == 0) && (original.getPixel(l, m, n) >= lcThreshold) && (waterne == water)) {
neigh.add(new Voxel3D(l, m, n, original.getPixel(l, m, n)));
}
}
}
// l
}
// m
}
// n
// analyse list
ok = true;
// empty
if (neigh.isEmpty()) {
ok = false;
}
// test 1 neighbor
if (neigh.size() == 1) {
ok = false;
}
// test all neighbors
it = neigh.iterator();
while (it.hasNext() && ok) {
tmpneigh = (Voxel3D) it.next();
// BLOCK
if (tmpneigh.getValue() > pixelCenter) {
ok = false;
break;
}
}
if (ok) {
changement = true;
if (neigh.size() > volMax) {
return null;
}
it = neigh.iterator();
while (it.hasNext()) {
tmpneigh = (Voxel3D) it.next();
l = tmpneigh.getRoundX();
m = tmpneigh.getRoundY();
n = tmpneigh.getRoundZ();
labelImage.setPixel(l, m, n, val);
object.add(new Voxel3D(l, m, n, val));
volume++;
if (volume > volMax) {
if (show) {
IJ.log("VOL :" + volume);
}
return null;
}
// update min-max
if (l < xdep) {
xdep--;
}
if (l > xfin) {
xfin++;
}
if (m < ydep) {
ydep--;
}
if (m > yfin) {
yfin++;
}
if (n < zdep) {
zdep--;
}
if (n > zfin) {
zfin++;
}
}
}
// BLOCKING
// else {
// it = neigh.iterator();
// while ((it != null) && (it.hasNext())) {
// tmpneigh = (Voxel3D) it.next();
// l = (int) tmpneigh.getX();
// m = (int) tmpneigh.getY();
// n = (int) tmpneigh.getZ();
// 0 do not change 1 exclude from future seg
// labelImage.putPixel(l, m, n, 0);
// }
// }
}
// labelimage==value
}
// i
}
// j
}
// k
sens *= -1;
}
// IJ.log("obj size: ");
return object;
}
use of mcib3d.geom.Voxel3D in project mcib3d-core by mcib3d.
the class Segment3DSpots method splitSpotWatershed.
public static Object3DVoxels[] splitSpotWatershed(Object3D obj, float rad, float dist) {
ImageInt seg = obj.createSegImage(0, 0, 0, obj.getXmax(), obj.getYmax(), obj.getZmax(), 255);
// seg.show();
ImagePlus segplus = seg.getImagePlus();
segplus.setCalibration(obj.getCalibration());
// return
Object3DVoxels[] res = null;
try {
int cpus = ThreadUtil.getNbCpus();
// FIXME variable multithread
ImageFloat edt3d = EDT.run(seg, 1f, false, cpus);
// 3D filtering of the edt to remove small local maxima
ImageFloat edt3dseeds = FastFilters3D.filterFloatImage(edt3d, FastFilters3D.MEAN, 1, 1, 1, cpus, false);
// edt3d.showDuplicate("edt");
// ImageStack localMax = FastFilters3D.filterFloatImageStack(edt3d.getImageStack(), FastFilters3D.MAXLOCAL, rad, rad, rad, cpus, false);
ImageFloat maxlocal3d = FastFilters3D.filterFloatImage(edt3dseeds, FastFilters3D.MAXLOCAL, rad, rad, rad, cpus, false);
// maxlocal3d.show("max local");
ArrayList<Voxel3D> locals = obj.listVoxels(maxlocal3d, 0);
int nb = locals.size();
// IJ.log("nb=" + nb);
if (nb < 2) {
return null;
}
// look for most far apart local maxima
int i1 = 0;
int i2 = 0;
double dmax = 0.0;
double d;
for (int i = 0; i < nb; i++) {
for (int j = i + 1; j < nb; j++) {
d = locals.get(i).distance(locals.get(j));
if (d > dmax) {
dmax = d;
i1 = i;
i2 = j;
}
}
}
// perform a 2-means clustering
double cx1 = 0;
double cy1 = 0;
double cz1 = 0;
double cx2 = 0;
double cy2 = 0;
double cz2 = 0;
double d1;
double d2;
Voxel3D PP1 = new Voxel3D(locals.get(i1).getX(), locals.get(i1).getY(), locals.get(i1).getZ(), 1);
Voxel3D PP2 = new Voxel3D(locals.get(i2).getX(), locals.get(i2).getY(), locals.get(i2).getZ(), 2);
Voxel3D P1 = new Voxel3D(cx1, cy1, cz1, 0);
Voxel3D P2 = new Voxel3D(cx2, cy2, cz2, 0);
int nb1, nb2;
int nbite = 0;
while ((nb > 2) && ((P1.distance(PP1) > 1) || (P2.distance(PP2) > 1)) && (nbite < 100)) {
nbite++;
cx1 = 0;
cy1 = 0;
cx2 = 0;
cy2 = 0;
cz1 = 0;
cz2 = 0;
nb1 = 0;
nb2 = 0;
P1.setX(PP1.getX());
P1.setY(PP1.getY());
P1.setZ(PP1.getZ());
P2.setX(PP2.getX());
P2.setY(PP2.getY());
P2.setZ(PP2.getZ());
for (Voxel3D local : locals) {
d1 = P1.distance(local);
d2 = P2.distance(local);
if (d1 < d2) {
cx1 += local.getX();
cy1 += local.getY();
cz1 += local.getZ();
nb1++;
} else {
cx2 += local.getX();
cy2 += local.getY();
cz2 += local.getZ();
nb2++;
}
}
cx1 /= nb1;
cy1 /= nb1;
cx2 /= nb2;
cy2 /= nb2;
cz1 /= nb1;
cz2 /= nb2;
PP1.setX(cx1);
PP1.setY(cy1);
PP1.setZ(cz1);
PP2.setX(cx2);
PP2.setY(cy2);
PP2.setZ(cz2);
}
// check minimal distances
double distPP = PP1.distance(PP2);
IJ.log("Centers found for split PP1=" + PP1 + " PP2=" + PP2 + " distance " + distPP);
if (distPP < dist) {
return null;
}
// find closest max local to two barycenters, in case barycenters outside object
Voxel3D PP1closest = new Voxel3D(locals.get(0));
Voxel3D PP2closest = new Voxel3D(locals.get(0));
double dist1 = PP1.distanceSquare(PP1closest);
double dist2 = PP2.distanceSquare(PP2closest);
for (Voxel3D local : locals) {
double dd1 = PP1.distanceSquare(local);
double dd2 = PP2.distanceSquare(local);
if (dd1 < dist1) {
dist1 = dd1;
PP1closest = local;
}
if (dd2 < dist2) {
dist2 = dd2;
PP2closest = local;
}
}
ImageInt seeds = new ImageShort("seeds", seg.sizeX, seg.sizeY, seg.sizeZ);
seeds.setPixel(PP1closest.getRoundX(), PP1closest.getRoundY(), PP1closest.getRoundZ(), 255);
seeds.setPixel(PP2closest.getRoundX(), PP2closest.getRoundY(), PP2closest.getRoundZ(), 255);
// seeds.show();
// Watershed3D_old wat = new Watershed3D_old(edt3d, seeds, 0, 0);
// ImageInt wat2 = wat.getWatershedImage3D();
// ImageHandler edt16 = edt3d.convertToShort(true);
Watershed3D wat = new Watershed3D(edt3d, seeds, 0, 0);
ImageInt wat2 = wat.getWatershedImage3D();
// wat2.show();
// in watershed label starts at 1
Object3DVoxels ob1 = new Object3DVoxels(wat2, 1);
Object3DVoxels ob2 = new Object3DVoxels(wat2, 2);
// IJ.log("split1="+ob1+" split2="+ob2);
// translate objects if needed by miniseg
// ob1.translate(seg.offsetX, seg.offsetY, seg.offsetZ);
// new ImagePlus("wat", wat2.getStack()).show();
res = new Object3DVoxels[2];
res[0] = ob1;
res[1] = ob2;
} catch (Exception e) {
IJ.log("Exception EDT " + e);
}
return res;
}
use of mcib3d.geom.Voxel3D in project mcib3d-core by mcib3d.
the class Segment3DSpots method segmentSpotClassical.
// FIXME a revoir, notamment dist ??
/**
* Segment an object from a seed
*
* @param lcThreshold Threshold to connect pixels
* @param val value of the object
* @param xdep x coordinate of the seed
* @param ydep y coordinate of the seed
* @param zdep z coordinate of the seed
* @return true if object cold be segmented
*/
public ArrayList<Voxel3D> segmentSpotClassical(int xdep, int ydep, int zdep, int lcThreshold, int val) {
boolean change = true;
int xEnd = xdep + 1;
int yEnd = ydep + 1;
int zEnd = zdep + 1;
int sens = 1;
if (labelImage == null) {
this.createLabelImage();
}
// pixel already segmented ?
if (labelImage.getPixel(xdep, ydep, zdep) > 0) {
return null;
}
labelImage.setPixel(xdep, ydep, zdep, val);
ArrayList<Voxel3D> object = new ArrayList<Voxel3D>();
object.add(new Voxel3D(xdep, ydep, zdep, val));
int volume = 1;
int i;
int j;
int k;
int l;
int m;
int n;
ImageHandler original = rawImage;
int waterCenter = 0;
int water = 0;
while (change) {
change = false;
for (k = sens == 1 ? zdep : zEnd; ((sens == 1 && k <= zEnd) || (sens == -1 && k >= zdep)); k += sens) {
for (j = sens == 1 ? ydep : yEnd; ((sens == 1 && j <= yEnd) || (sens == -1 && j >= ydep)); j += sens) {
for (i = sens == 1 ? xdep : xEnd; ((sens == 1 && i <= xEnd) || (sens == -1 && i >= xdep)); i += sens) {
if (labelImage.contains(i, j, k) && labelImage.getPixel(i, j, k) == val) {
if (WATERSHED) {
waterCenter = watershedImage.getPixelInt(i, j, k);
}
for (n = k - 1; n < k + 2; n++) {
for (m = j - 1; m < j + 2; m++) {
for (l = i - 1; l < i + 2; l++) {
if (labelImage.contains(l, m, n)) {
if (WATERSHED) {
water = watershedImage.getPixelInt(l, m, n);
}
if ((labelImage.getPixel(l, m, n) == 0) && (original.getPixel(l, m, n) >= lcThreshold) && (water == waterCenter)) {
labelImage.setPixel(l, m, n, val);
// original.putPixel(l, m, n, 0);
// add voxel to object
object.add(new Voxel3D(l, m, n, val));
volume++;
if (volume > volMax) {
if (show) {
IJ.log("VOL TOO BIG STOP SEG :" + volume);
}
return null;
}
// update min-max
if (l < xdep) {
xdep--;
}
if (l > xEnd) {
xEnd++;
}
if (m < ydep) {
ydep--;
}
if (m > yEnd) {
yEnd++;
}
if (n < zdep) {
zdep--;
}
if (n > zEnd) {
zEnd++;
}
change = true;
}
}
}
}
}
}
}
}
}
sens *= -1;
}
return object;
}
Aggregations