to Michal Schmid or other re Getting the number of pixels which values are below (between, now!) a certain threshold

Posted by Steven Vanek on
URL: http://imagej.273.s1.nabble.com/Getting-the-number-of-pixels-which-values-are-below-a-certain-threshold-tp3688975p3688981.html

Hi, this is a related question so Michal, I think your expertise or others may be helpful:
 I'm also a very new user though I think I can handle learning some macro code (is there a little tutorial for coding somewhere?)

question is making a color-sensing function to return, within an rgb (jpeg in my case, though could save as a difft format) image or selection, the number of pixels with red in range (between) (r1,r2) AND green in range (g1g2) AND blue in range (b1,b2) -- essentially, triple thresholding in rgb color, and two threshold points instead of one.  Output would ideally be writing a black and white image based on true/false for pixels with the above conditional, or just calculating percent of the image with the specified values.

OR -- how could I dump all the RGB values in an image into a spreadsheet or equivalently a CSV file.  Then I could do all the conditionals in excel or some such.

I don't see anything like this as a preexisting command or macro in ImageJ thought I can't imagine it is too hard.

Steve


 Steven Vanek
Doctoral Candidate
Soil and Crop Science
Cornell University
134 Plant Science Building
Ithaca, NY 14853


ofc. 607-255-6503
cel. 607-342-5940
hom. 607-272-0910
email: [hidden email]




________________________________
From: Michael Schmid <[hidden email]>
To: [hidden email]
Sent: Tue, March 2, 2010 1:28:08 PM
Subject: Re: Getting the number of pixels which values are below a certain threshold

Hi Stephan,

ok, I see, it did not work correctly with 16-bit images. Funny enough, getRawStatistics does not give a 16-bit histogram but an 8-bit one, restricted to the min...max range, like for float images. (This is different from ImageProcessor.getHistogram).

Here is a new version. Accuracy is limited because the histogram has only 256 steps. E.g. one step corresponds to 12 brightness units in an image with pixel values from -2048 to 1300. The threshold will have an error bar of +/- 0.5 steps, e.g. roughly +/- 6 brightness units in this case.
If you need better accuracy, and if it should be fast, you need a simple plugin.

//find number of pixels below a threshold
//does not work for images with nonlinear calibration function
threshold=-500;
getStatistics(area, mean, min, max, std, histogram);
result=0;
for (i=0; i<lengthOf(histogram); i++) {
  if (bitDepth()==32 || bitDepth()==16)
    value=min+(max-min)*i/(lengthOf(histogram)-1);
  else
    value=calibrate(i);
  if (value<threshold) result+=histogram[i];
}


Michael
________________________________________________________________

On 2 Mar 2010, at 18:57, Stephan Bender wrote:

> Hi Michael,
>
> wow, thank you!
>
> There's only one problem now:
> I tried it with a DICOM image of which I know that appr. 100000 pixels are in the range of -2048 --> -500.
> However, the macro returns 262144 pixels, which is 100% of the pixels (the image is 512x512). Maybe it is related to the bit depth you use to differ cases? Sorry, I am really a newbie with ImageJ...
> All of my images are 16bit...
>
> This is the macro how I run it:
>
> name = getArgument;
> if (name=="") exit ("No argument!");
> setBatchMode(true);
> open(name);
>
> threshold=-500;
> getStatistics(area, mean, min, max, std, histogram);
> result=0;
> for (i=0; i<lengthOf(histogram); i++) {
>   if (bitDepth()==32)
>     value=min+(max-min)*i/(lengthOf(histogram)-1);
>   else
>     value=calibrate(i);
>   if (value<threshold) result+=histogram[i];
> }
> perc=result*100/(getWidth*getHeight);
> print(getTitle+": "+getWidth+"x"+getHeight+" "+result+" "+perc+" %");
>
> As I run it from the shell, I can process the result using pipes.
> However, thank you also for the tip with the file output.
>
> Best regards,
>
> Stephan
>
>
>
> Am 02.03.2010 18:28, schrieb Michael Schmid:
>> Hi Stephan,
>>
>> loops in the macro language are like in C or Java, except that you need no type declaration.
>>
>> Also there was one problem with my idea: Using 'min, max' is correct for 32-bit images only (>90% of my images are 32 bit, so I did not think about this), and there was a 'minus 1' was missing).
>>
>> So, without trying it for all image types...
>>
>> //find number of pixels below a threshold
>> threshold=-500;
>> getStatistics(area, mean, min, max, std, histogram);
>> result=0;
>> for (i=0; i<lengthOf(histogram); i++) {
>>   if (bitDepth()==32)
>>     value=min+(max-min)*i/(lengthOf(histogram)-1);
>>   else
>>     value=calibrate(i);
>>   if (value<threshold) result+=histogram[i];
>> }
>> path=getDirectory("temp")+"ij_result.txt";
>> f = File.open(path);
>> print(f, result);
>>
>>
>> Note that your macro would print to the 'Log' window, you won't be able to access this from the shell or a Batch file. The macro above prints to a file in the temp directory (depending on the operating system, on Unix-like systems: /tmp/). Use
>>   print(getDirectory("temp"));
>> to see where it goes. You can also use getDirectory("home") or any other directory you like.
>>
>> By the way, instead of calling ImageJ from the shell (or Batch file under Windows) for each file, it might be faster to create a file with all the filenames and have ImageJ open the file and process the complete list in a loop.
>>
>>
>> Michael
>> ________________________________________________________________
>>
>> On 2 Mar 2010, at 13:34, Stephan Bender wrote:
>>
>>> Hi Michael,
>>>
>>> thanks for the advice. However, I still do not get it because of the loop you describe.
>>>
>>> This is how I would start with the macro:
>>>
>>>    name = getArgument;
>>>    if (name=="") exit ("No argument!");
>>>    setBatchMode(true);
>>>    open(name);
>>>     // here goes the loop
>>>     print(getTitle+": "+result);
>>>
>>> Can you please help me with the loop?
>>>
>>> Thank you!
>>>
>>> Best regards,
>>>
>>> Stephan
>>>
>>> Am 02.03.2010 11:05, schrieb Michael Schmid:
>>>> Hi Stephan,
>>>>
>>>> this should be easy:
>>>>   getStatistics(area, mean, min, max, std, histogram);
>>>> In a 'for' loop, sum up all values in the histogram array from index 0 to
>>>>   floor(lengthOf(histogram)*(threshold-min)/(max-min))
>>>> where threshold is -500 in your case.
>>>> Write the result to a file:
>>>>  f = File.open(path);
>>>>  print(f, result);
>>>> in your shell script or batch file, you can read the value from the file.
>>>>
>>>>
>>>> Michael
>>>> ________________________________________________________________
>>>>
>>>> On 1 Mar 2010, at 18:18, Stephan Bender wrote:
>>>>
>>>>> Hello,
>>>>>
>>>>> I'm quite new to ImageJ, I hope someone can help me with this task:
>>>>>
>>>>> I need get the number of pixels which values are below a certain
>>>>> threshold. The image format is DICOM (16 bit), and I need the result
>>>>> on a Unix command line, so I guess I'll have to use a macro function.
>>>>> A common image has appr. 60% of the pixel values from -2048 to -500,
>>>>> I need to know the exact number of pixels below -500.
>>>>>
>>>>> Thank you very much for your help!
>>>>>
>>>>> Best regards,
>>>>>
>>>>> Stephan