This plugin is working very well for me. Thanks so much for your work
and sharing. I still need to tweak it a bit as it misses a few in
stacks with tightly packed cells. But it is quite close.
Thanks for the help, Mike
vbindoka wrote:
> Dear all,
> The 3-D objects counter plugin does a good job for isolated objects
> (defined by threshold), but lacks a 3D watershed routine. The existing
> watershed routines either don't work well in 3D or take too long.
> Uneven heterochromatin staining poses another difficulty. I wrote this
> macro to separate most nuclei based on XY and resampled XZ 2D
> watershedding, plus refinement of identities by Euclidean distances.
> It's not perfect, but seems to do a good job with a few sample data sets
> I collected. It doesn't overcount as far as tested. It background
> corrects and outputs a labeled RGB map (plus the text stats from 3D
> objects counter plugin). Default values work for 20-30 pixel-diameter
> nuclei sampled is 1-2 um Zstacks. Yu may need to tune rolling ball
> diameter, smoothing, thresholds, etc. (it's a brute-force approach, so
> I'd be interested in improvements/comments)
> I include the text here (watch for broken code lines), or you can
> download it from our macro site (sample data should be posted today).
>
http://digital.bsd.uchicago.edu/imagejmacros.html> _________cut below for 3D_nuclei_counter.txt _____________________
>
> //macro to count DAPI nuclei in confocal Z stack (16bit)
> //it reduces the image to the object centers then counts those by means
> of the
> // 3D_object_counter plugin (required), and that takes care of merging
> overlapped objects
> //
http://rsb.info.nih.gov/ij/plugins/track/objects.html> // Final output is a numbered red-green stack plus the report
> // tuning steps would be the median radii and the expand diameters (decr
> both for low magnification)
> // Vytas Bindokas, Univ of Chicago, Apr 2008
> // this uses distance maps plus XY and XZ watershed steps to split
> objects "3D"; action is not perfect !
> // tuning steps are the rolling ball diam, the remove outlier diams;
> use smaller for low magnification input
>
> run("Colors...", "foreground=white background=black selection=yellow");
> t1=getTitle();
> run("Set Measurements...", " mean centroid redirect=None decimal=6");
> n0=nSlices;
> h=getHeight();
> w=getWidth();
> getVoxelSize(width, height, depth, unit);
> wi=width;
> hei=height;
> d=depth;
> u=unit;
> run("Subtract Background...", "rolling=25 stack"); //try diameter of
> nucleus
> run("Duplicate...", "title=countme duplicate");
> run("Set Scale...", "distance=0 known=1 pixel=1 unit=pixel");
> setSlice(n0/2);
> run("Enhance Contrast", "saturated=0.1 normalize normalize_all ");
> //correct for Z intensity loss
> run("Remove Outliers...", "radius=7 threshold=0 which=Bright stack");
> //this smooths DAPI heterochromatin staining patterns
> run("Remove Outliers...", "radius=2 threshold=0 which=Dark stack");
> //smooths background
>
> // tuning point below
>
> setAutoThreshold(); //you can set a fixed range, if needed,
> by activating next line...
> //setThreshold(9500, 65535); //goal is to pick up entire nucleus
> (vs uneven bits)
> run("Make Binary", " "); run("Median...", "radius=3 stack");
> //to smooth and fill some holes
> run("Watershed", "stack");
> run("Distance Map", "stack"); // "find" centers for next steps
> (seems to aid splitting XY and XZ)
> run("Grays");
>
> mo=1; //this is noise tolerance, lower = finds more
> maxima (tune as needed); values are DISTANCE TO EDGE
> for (i=1; i<=nSlices; i++){
> setSlice(i); getStatistics(area, mean, min, max); if
> (max>min){ //skip if frame blank...
> run("Find Maxima...", "noise="+mo+" output=[Point Selection]");
> run("Enlarge...", "enlarge=4"); //pad around each
> maximum; tune if need be
> run("Clear Outside", "slice");
> }
> run("Select None");
> }
>
> makeLine(0, 0, w, 0);
> run("Reslice [/]...", "input=1 output=1 slice="+h+""); //repeat
> watershedding and localization in Z axis
> rename("xz");
> run("Enhance Contrast", "saturated=0.1");
> run("Median...", "radius=1 stack");
> run("Convert to Mask", " black");
> run("Watershed", "stack");
> run("Distance Map", "stack");
>
> for (i=1; i<=nSlices; i++){
> setSlice(i);
> getStatistics(area, mean, min, max);
> if (max>min){ run("Find Maxima...", "noise=0 output=[Point
> Selection]"); //since this is pixels, not true Z, I suggest keeping
> these values LOW
> run("Enlarge...", "enlarge=1");
> //run("Fill", "slice");
> }
> run("Select None");
> }
> n1=nSlices;
> h1=getHeight();
> w1=getWidth();
> makeLine(0, 0, w1, 0);
> // run("Set Scale...", "distance=0 known=1 pixel=1 unit=pixel");
> run("Reslice [/]...", "input="+1+" output="+1+" slice="+h1);
> //return to XY view
> rename("zvu");
> setVoxelSize(wi, hei, d, u);
> setSlice(nSlices/2);
> run("Grays");
> run("Despeckle", "stack");
>
> // 3D counts can take much memory! consider going 8-bit here if it
> can't run in OS limits
> //the min & max size below can select what to 3D count
> run(" 3D objects counter", "threshold=1 slice=25 min=6 max=13107200
> particles dot=3 numbers font=12");
>
> run("8-bit"); //the next few lines build the red map data
> for overlays
> setMinAndMax(0, 1);
> run("Apply LUT", "stack");
> selectWindow("xz");
> close();
> selectWindow("countme");
> close();
> selectWindow("zvu");
> close();
> selectWindow(t1);
> run("Enhance Contrast", "saturated=0.5 normalize normalize_all");
> run("Despeckle", "stack");
> run("RGB Merge...", "red=[Particles zvu] green=["+t1+"] blue=*None*
> gray=*None*");
> rename("counted"+t1);
>
> ______________ end cut ___________________________
>
>
>
> Fernando Sales wrote:
>> Mike,
>>
>> if you have a program that segments and identify the cells in each
>> slice of
>> the stack, you can generate a binary mask and count the number of
>> "islands"
>> of white pixels (suppose that the cells are white and the backgroung is
>> black). I've developed a plugin which implements a labelling algorithm to
>> identify different objects in a binary scene. Then, this way you can
>> count
>> the number of cells slice by slice.
>>
>> Cheers,
>> Fernando
>> On Fri, Apr 11, 2008 at 3:54 PM, Mike Myerburg
>> <myerburg@gmail.com> wrote:
>>
>>
>>> Hi-
>>>
>>> I study polarized cells that form a pseudostratified epithelial layer on
>>> filters. I am trying to make a plugin that will count the # of nuclei
>>> present in a stack. Because the cells are not a monolayer, I cannot
>>> accurately count them by making an zprojection and then do standard
>>> automated counting (the nuclei are occasionally on top of each
>>> other). It
>>> seems that it "should" be possible to make a plugin to analyze the
>>> nuclei in
>>> 3D and then count the number within a stack.
>>>
>>> Has something like this already been made? Any suggestions?
>>>
>>> Cheers, Mike
>>>
>>>
>>
>>
>>
>>
>