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 |
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 |
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 |
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 |
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 |
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 |
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 |
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)); |
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)); |
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 |
Free forum by Nabble | Edit this page |