Zprojector sum algorithm

imagej

#1

Hi everybody,
Here is a piece of code I use:

ZProjector zp = new ZProjector(pile);
zp.setMethod(ZProjector.SUM_METHOD);
zp.setStartSlice(1);
zp.setStopSlice(pile.getNSlices());
zp.doProjection();
ImagePlus imps = zp.getProjection();

Looking to imps with thresholds it appears that the sum results are spread across the range (8 bits). Has somebody an axplanation for this?

Thanks for an answer

Alan


#2

Hi @Alan,

I’m not sure what you mean by this. Could you explain what the input looks like, what the output is and in what way this differs from you expectation.

John


#3

Hi John,
Imagine a stack with 8 slices each one with 0 and 1 values.
Adding the 8 slices together will produce a result between 0 and 8.
Doing this with the ZProjector produces the following values:

255, 223,…255 -i*32

Does it answer your question?

Alan


#4

I am unable to reproduce this problem. Here is my test script:

  stack = IJ.createImage("Stack", "8-bit noise", 256, 256, 8);
  IJ.run(stack, "Divide...", "value=256 stack");
  stats = stack.getStatistics();
  print("max1="+stats.max);
  zp = new ZProjector(stack);
  zp.setMethod(ZProjector.SUM_METHOD);
  zp.setStartSlice(1);
  zp.setStopSlice(stack.getNSlices());
  zp.doProjection();
  sum = zp.getProjection();
  stats = sum.getStatistics();
  print("max2="+stats.max);
  sum.show();

And here is the output:

  max1=1
  max2=8

Here is a macro version of the script:

  newImage("Untitled", "8-bit noise", 256, 256, 8);
  run("Divide...", "value=256 stack");
  Stack.getStatistics(voxelCount, mean, min, max)
  print("stack max="+max);
  run("Z Project...", "projection=[Sum Slices]");
  getStatistics(voxelCount, mean, min, max)
  print("sum max="+max);

#5

Hello Wayne,
Here is the plugin in which I get the problem:

import ij.*;
import ij.io.*;
import ij.process.*;
import ij.gui.*;
import ij.plugin.*;

import java.awt.*;

public class ZProjTest1 implements PlugIn {
	double offset[][] = new double[9][2]; 
	public void run(String arg) {

	// Prépare les offsets

	offset[0][0]=0.0;
	offset[0][1]=0.0;

	offset[1][0]=1.0;
	offset[1][1]=0.0;

	offset[2][0]=1.0;
	offset[2][1]=1.0;

	offset[3][0]=0.0;
	offset[3][1]=1.0;

	offset[4][0]=-1.0;
	offset[4][1]=1.0;

	offset[5][0]=-1.0;
	offset[5][1]=0.0;

	offset[6][0]=-1.0;
	offset[6][1]=-1.0;

	offset[7][0]=0.0;
	offset[7][1]=-1.0;

	offset[8][0]=1.0;
	offset[8][1]=-1.0;

	
	// Open image dialogue ouverture fichier

	OpenDialog od = new OpenDialog("Open image file", arg);
	String file = od.getFileName();
	if (file == null) return;
	String directory = od.getDirectory();
	Opener opener = new Opener();

	ImagePlus imp0 = opener.openImage(directory, file);
	imp0.show();
	IJ.showMessage("Original  ");		


	// Seuile l'image

	double tmin=40.0;  //Arbitraire
	double tmax=170.0; //Arbitraire
	ImageProcessor ip0 = imp0.getProcessor();
	ip0.setThreshold(tmin,tmax,0); //BLACK_AND_WHITE_LUT=1, 0=RED_LUT
	ImagePlus imp1 = createMaskFromThreshold(imp0,imp0.getShortTitle()+"_bin");
	imp1.show();
	IJ.showMessage("Seuils  ");		

	// crée la pile, remplir avec imp1 (binaire)

	ImageProcessor ip1 = imp1.getProcessor();
	ImagePlus pile = makeStack(ip1,9); // nb slices mais premier index =0 !!!
	pile.show();
	int nSlices = pile.getStackSize();
   	 IJ.showMessage("nb Slices:  "+String.valueOf(nSlices));		

	// Aligne les voisins dans la pile

	for (int i=0;i<9; i++){
		doTranslation(pile,offset[i][0],offset[i][1],i);
	}
	IJ.showMessage("Translations show  ");		

	// repasser à  0-1 au lieu de 0-255

	for (int i=1;i<=9; i++){
		pile.setSlice(i);
		ImagePlus  impi=pile;
		ImageProcessor ipi =impi.getProcessor();
		// passer de 255 -> 1, on garde le dernier bit
		ipi.and(0x01);
	}


	// Addition des tranches de pile avec ZProjector

/*	ZProjector zp = new ZProjector(pile);
	zp.setMethod(ZProjector.SUM_METHOD);
	zp.setStartSlice(1);
	zp.setStopSlice(pile.getNSlices());
	zp.doProjection();
	ImagePlus imps = zp.getProjection();
*/
	ZProjector projector = new ZProjector(pile);	
    ImagePlus imps = projector.run(pile, "Sum Slices", 1, 9);

	imps.show();
	imps.setTitle("Somme");

	IJ.run(imps, "8-bit", "");
	imps.setTitle("Somme");
	imps.show();
}

	//procedures de translation
	void doTranslation(ImagePlus pile,double u0, double v0, int x) {
		pile.setSlice(x+1);
		pile.setProcessor(Shift(pile.getProcessor(),(double)u0,(double)v0));
	}

	//procedures de shift
	ImageProcessor Shift(ImageProcessor ip, double x0, double y0) {
		ip.setInterpolationMethod(0);
		ip.translate(x0, y0);
	return ip;
	}

	// selfexplained
	public void showImageMaximized(ImagePlus imp) {
		imp.show();
		ImageWindow win = imp.getWindow();
		win.setExtendedState(ImageWindow.MAXIMIZED_BOTH);
	} 

	// génère l'image binaire avec les seuils
    ImagePlus createMaskFromThreshold(ImagePlus imp, String imgnom) {
        ImageProcessor ip = imp.getProcessor();
        if (ip.getMinThreshold()==ImageProcessor.NO_THRESHOLD)
            {IJ.error("Create Mask", "Area selection or thresholded image required"); 
				return null;
			}
        double t1 = ip.getMinThreshold();
        double t2 = ip.getMaxThreshold();
        IJ.run("Duplicate...", "title="+imgnom);
        ImagePlus imp2 = WindowManager.getCurrentImage();
        ImageProcessor ip2 = imp2.getProcessor();
        ip2.setThreshold(t1, t2, ip2.getLutUpdateMode());
        IJ.run("Convert to Mask");
    return imp2;
	}

	// crée un stack
 	ImagePlus makeStack(ImageProcessor ip, int nbi) {
		int width = ip.getWidth();
		int height = ip.getHeight();
		ImagePlus stack = IJ.createImage("Itérés", "GRAY8", width, height, nbi);
		for (int k =1; k<=nbi;  k++){
			insertStack(ip,stack,k);
		}
	return stack;
	}

	void insertStack(ImageProcessor ip, ImagePlus stack, int i) {
		int width = ip.getWidth();
		int height = ip.getHeight();
		ip.setRoi(1, 1, width, height);
		stack.setSlice(i);
		ImageProcessor 	ip2 = stack.getProcessor();
		ip2.insert(ip, 1, 1);
	}

	}

#6

Dear @Alan,

Please provide a minimal reproducible example.

Something like this JavaScript example:

  stack = IJ.createImage("Stack", "8-bit noise", 256, 256, 8);
  IJ.run(stack, "Divide...", "value=256 stack");
  stats = stack.getStatistics();
  print("max1="+stats.max);
  zp = new ZProjector(stack);
  zp.setMethod(ZProjector.SUM_METHOD);
  zp.doProjection();
  sum = zp.getProjection();
  stats = sum.getStatistics();
  print("max2="+stats.max);
  sum.show();

which outputs

  max1=1
  max2=8

#7

Hi Waine,
OK understood, I’ll do that.
How can I send attached files with the MWE.
Thanks for your answer
Alan


#8

You can post files to the forum but it would be better to have the MWE (minimal working example) generate any needed test data, as the JavaScript example I posted does.


#9

Well, inbetween it appears that I found a mistake in the program when duplicating an ImagePlus.
Please, forget the problem for the moment.
Alan