Getting the number of pixels which values are below a certain threshold

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Getting the number of pixels which values are below a certain threshold

Stephan Bender
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
Reply | Threaded
Open this post in threaded view
|

Re: Getting the number of pixels which values are below a certain threshold

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
Reply | Threaded
Open this post in threaded view
|

Re: Getting the number of pixels which values are below a certain threshold

Stephan Bender
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
Reply | Threaded
Open this post in threaded view
|

Re: Getting the number of pixels which values are below a certain threshold

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
Reply | Threaded
Open this post in threaded view
|

Re: Getting the number of pixels which values are below a certain threshold

Stephan Bender
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
Reply | Threaded
Open this post in threaded view
|

Re: Getting the number of pixels which values are below a certain threshold

Michael Schmid
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
Reply | Threaded
Open this post in threaded view
|

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

Steven Vanek
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



     
Reply | Threaded
Open this post in threaded view
|

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

Rasband, Wayne (NIH/NIMH) [E]
On Mar 14, 2010, at 4:29 PM, Steven Vanek wrote:

> 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.

Here is a macro that converts pixels in an RGB image to white if the red, green and blue values are within specified ranges or black if they are not. It also calculates and displays the percent of the image with the specified values.

-wayne

  if (bitDepth!=24)
     exit("RGB image required");
  Dialog.create("Thresholder");
  Dialog.addNumber("r1:", 0);
  Dialog.addNumber("r2:", 255);
  Dialog.addNumber("g1:", 0);
  Dialog.addNumber("g2:", 255);
  Dialog.addNumber("b1:", 0);
  Dialog.addNumber("b2:", 255);
  Dialog.show();
  setupUndo;
  r1 = Dialog.getNumber();
  r2 = Dialog.getNumber();
  g1 = Dialog.getNumber();
  g2 = Dialog.getNumber();
  b1 = Dialog.getNumber();
  b2 = Dialog.getNumber();
  getSelectionBounds(x1, y1, width, height);
  count = 0;
  for (y=y1; y<y1+height; y++) {
     for (x=x1; x<x1+width; x++) {
        v = getPixel(x,y);
        r = (v&0xff0000)>>16;
        g = (v&0xff00)>>8;
        b = (v&0xff);
        if (r>=r1&&r<=r2&&g>=g1&&g<=g2&&b>=b1&&b<=b2) {
           putPixel(x, y, 0xffffff);
           count++;
        } else
           putPixel(x, y, 0);
     }
  }
  print("Percent thresholded: "+count*100/(width*height));
Reply | Threaded
Open this post in threaded view
|

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

Steven Vanek
Wow! great, thanks so much, will give it a try.  I assume it converts the image 'in place'; ie I want to save as first to not overwrite the original image?

Steve

 






________________________________
From: "Rasband, Wayne (NIH/NIMH) [E]" <[hidden email]>
To: [hidden email]
Sent: Sun, March 14, 2010 11:05:20 PM
Subject: Re: to Michal Schmid or other re Getting the number of pixels which values are below (between, now!) a certain threshold

On Mar 14, 2010, at 4:29 PM, Steven Vanek wrote:

> 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.

Here is a macro that converts pixels in an RGB image to white if the red, green and blue values are within specified ranges or black if they are not. It also calculates and displays the percent of the image with the specified values.

-wayne

  if (bitDepth!=24)
     exit("RGB image required");
  Dialog.create("Thresholder");
  Dialog.addNumber("r1:", 0);
  Dialog.addNumber("r2:", 255);
  Dialog.addNumber("g1:", 0);
  Dialog.addNumber("g2:", 255);
  Dialog.addNumber("b1:", 0);
  Dialog.addNumber("b2:", 255);
  Dialog.show();
  setupUndo;
  r1 = Dialog.getNumber();
  r2 = Dialog.getNumber();
  g1 = Dialog.getNumber();
  g2 = Dialog.getNumber();
  b1 = Dialog.getNumber();
  b2 = Dialog.getNumber();
  getSelectionBounds(x1, y1, width, height);
  count = 0;
  for (y=y1; y<y1+height; y++) {
     for (x=x1; x<x1+width; x++) {
        v = getPixel(x,y);
        r = (v&0xff0000)>>16;
        g = (v&0xff00)>>8;
        b = (v&0xff);
        if (r>=r1&&r<=r2&&g>=g1&&g<=g2&&b>=b1&&b<=b2) {
           putPixel(x, y, 0xffffff);
           count++;
        } else
           putPixel(x, y, 0);
     }
  }
  print("Percent thresholded: "+count*100/(width*height));



     
Reply | Threaded
Open this post in threaded view
|

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

Prodanov Dimiter
In reply to this post by Steven Vanek
Hi,

What you ask for is essentially a combination between the functionalities present in Gabriel's color threshold plugin and my Color Histogram,

Best regards,

Dimiter Prodanov

-----Original Message-----
From: Steven Vanek [mailto:[hidden email]]
Sent: Sunday 14 March 2010 21:29
Subject: to Michal Schmid or other re Getting the number of pixels which values are below (between, now!) a certain threshold

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