Posted by
vbindokas on
Apr 16, 2008; 11:08am
URL: http://imagej.273.s1.nabble.com/Count-cells-in-stack-tp3695075p3695077.html
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 <
[hidden email]> 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
>>
>>
>
>
>
>
--
__
Vytas Bindokas, Ph.D.
Research Assoc. / Assoc. Prof.,
Director, BSD Light Microscopy Core Facility
Dept Neurobiol Pharmacol Physiol MC0926
947 E 58th Street
The University of Chicago
Chicago IL 60637
Room Abbott 120
773-702-4875
email
[hidden email]
web site for LMCF:
http://digital.bsd.uchicago.edu/index.htmlThis email is intended only for the use of the individual or entity to which it is addressed and may contain information that is privileged and confidential. If the reader of this email message is not the intended recipient, you are hereby notified that any dissemination, distribution, or copying of this communication is prohibited. If you have received this email in error, please notify the sender and destroy/delete all copies of the transmittal. Thank you.