Working with Java I have raw data files with 32 bit integer gray scale data
which I read into a byte[] array. I process these data as ints looking for adjacent pixels that have the same value in order to debug a problem with the camera. I'd like to create a scaled grayscale RGB from the original data so that I may color the detected adjacent pixels to allow us to detect patterns visually but I don't understand how to create and populate a grayscale integer ImageJ array and have not found an example by Google searching. How do I do this? TIA -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Good day,
ImageJ doesn't support 32 bit integer gray scale images. Supported are 8bit and 16bit integer as well as 32bit float. Furthermore 24bit (3 X 8bit) RGB and index color 8bit. Regards Herbie ::::::::::::::::::::::::::::::::::::::::::::: Am 12.02.19 um 19:15 schrieb Robert Lockwood: > Working with Java I have raw data files with 32 bit integer gray scale data > which I read into a byte[] array. I process these data as ints looking for > adjacent pixels that have the same value in order to debug a problem with > the camera. > > I'd like to create a scaled grayscale RGB from the original data so that I > may color the detected adjacent pixels to allow us to detect patterns > visually but I don't understand how to create and populate a grayscale > integer ImageJ array and have not found an example by Google searching. > > How do I do this? > TIA > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
If you do this in Java, I think there are a couple of workarounds.
Here's one idea: Since you already can "process these data as ints", you should be able to create your own 8-bit RGB image. Of course, you only get 8-bits of gray scale. Here's another idea: you should be able to import the image as a 32-bit float image. If there is non-zero data in the upper 8 bits, the image will look very strange, but at least you'll have a 32-bit array. Next, take each 32-bit float pixel value and use Float.floatToRawIntBits to get your 32-bit integer values. Since you can already create the int values from your byte array, I would start with that idea. Be careful about signed/unsigned. Finally, I would consider creating a 24-bit integer gray-scale value, and using that as a 32-bit float (using Float.intBitsToFloat). This gives you a float image where the values are between 0.0 and 1.0. You can then use an Overlay to highlight the problem pixels. Use either idea above to get a 32-bit unsigned value, and scale it to 24-bits. Convert that to a float, and store it in a 32-bit float image. Or, simply create a 16-bit integer gray scale image, and use an Overlay. Your choice may depend on what you know about the range of values. The advantage of my 24-bit version above is that you have a bit more flexibility in dynamically adjusting the range of displayed gray levels. The disadvantage is that the numbers will all be presented as (0.0..1.0) instead of [0..65535] (for the 16-bit version) -- Kenneth Sloan [hidden email] Vision is the art of seeing what is invisible to others. > On Feb 12, 2019, at 12:37, Herbie <[hidden email]> wrote: > > Good day, > > ImageJ doesn't support 32 bit integer gray scale images. > > Supported are 8bit and 16bit integer as well as 32bit float. Furthermore 24bit (3 X 8bit) RGB and index color 8bit. > > Regards > > Herbie > > ::::::::::::::::::::::::::::::::::::::::::::: > Am 12.02.19 um 19:15 schrieb Robert Lockwood: >> Working with Java I have raw data files with 32 bit integer gray scale data >> which I read into a byte[] array. I process these data as ints looking for >> adjacent pixels that have the same value in order to debug a problem with >> the camera. >> I'd like to create a scaled grayscale RGB from the original data so that I >> may color the detected adjacent pixels to allow us to detect patterns >> visually but I don't understand how to create and populate a grayscale >> integer ImageJ array and have not found an example by Google searching. >> How do I do this? >> TIA >> -- >> ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by Robert Lockwood
Hi Robert,
ImageJ can import 32-bit images; it opens them as 32-bit floating point (which results in some loss of accuracy for high pixel values). You can then apply a color LUT of your choice or any other processing you like. Use File>Import>Raw or the corresponding IJ.run command (Use the Macro Recorder in 'Java' mode). Michael ________________________________________________________________ On 2019-02-12 19:15, Robert Lockwood wrote: > Working with Java I have raw data files with 32 bit integer gray scale > data > which I read into a byte[] array. I process these data as ints looking > for > adjacent pixels that have the same value in order to debug a problem > with > the camera. > > I'd like to create a scaled grayscale RGB from the original data so > that I > may color the detected adjacent pixels to allow us to detect patterns > visually but I don't understand how to create and populate a grayscale > integer ImageJ array and have not found an example by Google searching. > > How do I do this? > TIA > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by Kenneth Sloan-2
When I look at the imported images in Fiji I apply Brightness/Contrast with
auto for a decent image. If I can do the same thing in Java and then convert to RGB I can then manipulate the pixels I've identified by my comparison code. BTW the values in my 32 bit first came from the camera as defined as C unsigned shorts so all the values are less than 64K so I can extract the Java short values easily. On Tue, Feb 12, 2019 at 11:20 AM Kenneth Sloan <[hidden email]> wrote: > If you do this in Java, I think there are a couple of workarounds. > > Here's one idea: Since you already can "process these data as ints", you > should be able to create your own 8-bit RGB image. Of course, you only > get 8-bits of gray scale. > > Here's another idea: you should be able to import the image as a 32-bit > float image. If there is non-zero data in the upper 8 bits, the image > will look > very strange, but at least you'll have a 32-bit array. Next, take each > 32-bit float pixel value and use Float.floatToRawIntBits to get > your 32-bit integer values. > > Since you can already create the int values from your byte array, I would > start > with that idea. > > Be careful about signed/unsigned. > > Finally, I would consider creating a 24-bit integer gray-scale value, and > using > that as a 32-bit float (using Float.intBitsToFloat). This gives you a > float image > where the values are between 0.0 and 1.0. You can then use an Overlay to > highlight > the problem pixels. Use either idea above to get a 32-bit unsigned value, > and > scale it to 24-bits. Convert that to a float, and store it in a 32-bit > float image. > > Or, simply create a 16-bit integer gray scale image, and use an Overlay. > > Your choice may depend on what you know about the range of values. The > advantage of > my 24-bit version above is that you have a bit more flexibility in > dynamically adjusting > the range of displayed gray levels. The disadvantage is that the numbers > will all > be presented as (0.0..1.0) instead of [0..65535] (for the 16-bit version) > > -- > Kenneth Sloan > [hidden email] > Vision is the art of seeing what is invisible to others. > > > > > > > On Feb 12, 2019, at 12:37, Herbie <[hidden email]> wrote: > > > > Good day, > > > > ImageJ doesn't support 32 bit integer gray scale images. > > > > Supported are 8bit and 16bit integer as well as 32bit float. Furthermore > 24bit (3 X 8bit) RGB and index color 8bit. > > > > Regards > > > > Herbie > > > > ::::::::::::::::::::::::::::::::::::::::::::: > > Am 12.02.19 um 19:15 schrieb Robert Lockwood: > >> Working with Java I have raw data files with 32 bit integer gray scale > data > >> which I read into a byte[] array. I process these data as ints looking > for > >> adjacent pixels that have the same value in order to debug a problem > with > >> the camera. > >> I'd like to create a scaled grayscale RGB from the original data so > that I > >> may color the detected adjacent pixels to allow us to detect patterns > >> visually but I don't understand how to create and populate a grayscale > >> integer ImageJ array and have not found an example by Google searching. > >> How do I do this? > >> TIA > >> -- > >> ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > > > -- > > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Ah...if the data are really 16-bit, then my recommendation is to
import the image as a 32-bit float, apply Brightness/Contrast, and use an OVERLAY to highlight the problem pixels. But, if you really want RGB, import as 32-bit, adjust, and use Image->Type->RGB and you are done. Note that this loses precision (but, you can't see much more than 8-bits on the screen anyway). You also lose access to the actual original pixel values - but perhaps that's not important. I do this routinely with data that claim to be 32-bit floats in the range [0.0..1.0). These are essentially 24-bit unsigned integers. It looks like there is no reason for you to import a byte array and twiddle bits to construct ints. Fiji will happily import the image as 32-bit float, adjust brightness/contrast, and convert to RGB (if that's what you want). Is your code to find and highlight problem pixels written as a Fiji plugin, or as a stand-alone Java program? -- Kenneth Sloan [hidden email] Vision is the art of seeing what is invisible to others. > On Feb 12, 2019, at 14:48, Robert Lockwood <[hidden email]> wrote: > > When I look at the imported images in Fiji I apply Brightness/Contrast with > auto for a decent image. > > If I can do the same thing in Java and then convert to RGB I can then > manipulate the pixels I've identified by my comparison code. > > BTW the values in my 32 bit first came from the camera as defined as C > unsigned shorts so all the values are less than 64K so I can extract the > Java short values easily. > > On Tue, Feb 12, 2019 at 11:20 AM Kenneth Sloan <[hidden email]> > wrote: > >> If you do this in Java, I think there are a couple of workarounds. >> >> Here's one idea: Since you already can "process these data as ints", you >> should be able to create your own 8-bit RGB image. Of course, you only >> get 8-bits of gray scale. >> >> Here's another idea: you should be able to import the image as a 32-bit >> float image. If there is non-zero data in the upper 8 bits, the image >> will look >> very strange, but at least you'll have a 32-bit array. Next, take each >> 32-bit float pixel value and use Float.floatToRawIntBits to get >> your 32-bit integer values. >> >> Since you can already create the int values from your byte array, I would >> start >> with that idea. >> >> Be careful about signed/unsigned. >> >> Finally, I would consider creating a 24-bit integer gray-scale value, and >> using >> that as a 32-bit float (using Float.intBitsToFloat). This gives you a >> float image >> where the values are between 0.0 and 1.0. You can then use an Overlay to >> highlight >> the problem pixels. Use either idea above to get a 32-bit unsigned value, >> and >> scale it to 24-bits. Convert that to a float, and store it in a 32-bit >> float image. >> >> Or, simply create a 16-bit integer gray scale image, and use an Overlay. >> >> Your choice may depend on what you know about the range of values. The >> advantage of >> my 24-bit version above is that you have a bit more flexibility in >> dynamically adjusting >> the range of displayed gray levels. The disadvantage is that the numbers >> will all >> be presented as (0.0..1.0) instead of [0..65535] (for the 16-bit version) >> >> -- >> Kenneth Sloan >> [hidden email] >> Vision is the art of seeing what is invisible to others. >> >> >> >> >> >>> On Feb 12, 2019, at 12:37, Herbie <[hidden email]> wrote: >>> >>> Good day, >>> >>> ImageJ doesn't support 32 bit integer gray scale images. >>> >>> Supported are 8bit and 16bit integer as well as 32bit float. Furthermore >> 24bit (3 X 8bit) RGB and index color 8bit. >>> >>> Regards >>> >>> Herbie >>> >>> ::::::::::::::::::::::::::::::::::::::::::::: >>> Am 12.02.19 um 19:15 schrieb Robert Lockwood: >>>> Working with Java I have raw data files with 32 bit integer gray scale >> data >>>> which I read into a byte[] array. I process these data as ints looking >> for >>>> adjacent pixels that have the same value in order to debug a problem >> with >>>> the camera. >>>> I'd like to create a scaled grayscale RGB from the original data so >> that I >>>> may color the detected adjacent pixels to allow us to detect patterns >>>> visually but I don't understand how to create and populate a grayscale >>>> integer ImageJ array and have not found an example by Google searching. >>>> How do I do this? >>>> TIA >>>> -- >>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >>> >>> -- >>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >> >> -- >> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >> > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Thanks, Kenneth, this is a stand-alone program to detect adjacent pixels
that have the same values and save the probably converted data as grayscale with the detected pixels in color. Here is the code I have now, compiles and runs but unfinished // read raw image file byte[] bytes = Files.toByteArray(dFile); // represent as integers IntBuffer rawIntImage = ByteBuffer.wrap(bytes).asIntBuffer(); // set up for data using imageJ final ImagePlus imp = IJ.createImage(dFile.getName(), "16-bit", NCOLS, NROWS, 1); final ShortProcessor sp = (ShortProcessor) imp.getProcessor(); final short[] shortImage = (short[]) sp.getPixels(); int index = 0; while(rawIntImage.hasRemaining()) { shortImage[index++] = (short) rawIntImage.get(); } // sp.convertToByte(true).convertToRGB(); // What is returned here? I need "IntBuffer rawIntImage" to use to detect the adjacent duplicate pixels I'm assuming that 'convertToByte' will do the brightness and contrast mapping returning a ByteProcessor, is that correct? Then I need to convert to RGB ? On Tue, Feb 12, 2019 at 1:19 PM Kenneth Sloan <[hidden email]> wrote: > Ah...if the data are really 16-bit, then my recommendation is to > import the image as a 32-bit float, apply Brightness/Contrast, > and use an OVERLAY to highlight the problem pixels. > > But, if you really want RGB, import as 32-bit, adjust, > and use Image->Type->RGB and you are done. > > Note that this loses precision (but, you can't see much more than > 8-bits on the screen anyway). > > You also lose access to the actual original pixel values - but > perhaps that's not important. > > I do this routinely with data that claim to be 32-bit floats in the > range [0.0..1.0). These are essentially 24-bit unsigned integers. > > It looks like there is no reason for you to import a byte array > and twiddle bits to construct ints. Fiji will happily import > the image as 32-bit float, adjust brightness/contrast, and convert > to RGB (if that's what you want). > > Is your code to find and highlight problem pixels written as a > Fiji plugin, or as a stand-alone Java program? > > > -- > Kenneth Sloan > [hidden email] > Vision is the art of seeing what is invisible to others. > > > > > > > On Feb 12, 2019, at 14:48, Robert Lockwood <[hidden email]> wrote: > > > > When I look at the imported images in Fiji I apply Brightness/Contrast > with > > auto for a decent image. > > > > If I can do the same thing in Java and then convert to RGB I can then > > manipulate the pixels I've identified by my comparison code. > > > > BTW the values in my 32 bit first came from the camera as defined as C > > unsigned shorts so all the values are less than 64K so I can extract the > > Java short values easily. > > > > On Tue, Feb 12, 2019 at 11:20 AM Kenneth Sloan <[hidden email]> > > wrote: > > > >> If you do this in Java, I think there are a couple of workarounds. > >> > >> Here's one idea: Since you already can "process these data as ints", you > >> should be able to create your own 8-bit RGB image. Of course, you only > >> get 8-bits of gray scale. > >> > >> Here's another idea: you should be able to import the image as a 32-bit > >> float image. If there is non-zero data in the upper 8 bits, the image > >> will look > >> very strange, but at least you'll have a 32-bit array. Next, take each > >> 32-bit float pixel value and use Float.floatToRawIntBits to get > >> your 32-bit integer values. > >> > >> Since you can already create the int values from your byte array, I > would > >> start > >> with that idea. > >> > >> Be careful about signed/unsigned. > >> > >> Finally, I would consider creating a 24-bit integer gray-scale value, > and > >> using > >> that as a 32-bit float (using Float.intBitsToFloat). This gives you a > >> float image > >> where the values are between 0.0 and 1.0. You can then use an Overlay > to > >> highlight > >> the problem pixels. Use either idea above to get a 32-bit unsigned > value, > >> and > >> scale it to 24-bits. Convert that to a float, and store it in a 32-bit > >> float image. > >> > >> Or, simply create a 16-bit integer gray scale image, and use an Overlay. > >> > >> Your choice may depend on what you know about the range of values. The > >> advantage of > >> my 24-bit version above is that you have a bit more flexibility in > >> dynamically adjusting > >> the range of displayed gray levels. The disadvantage is that the > numbers > >> will all > >> be presented as (0.0..1.0) instead of [0..65535] (for the 16-bit > version) > >> > >> -- > >> Kenneth Sloan > >> [hidden email] > >> Vision is the art of seeing what is invisible to others. > >> > >> > >> > >> > >> > >>> On Feb 12, 2019, at 12:37, Herbie <[hidden email]> wrote: > >>> > >>> Good day, > >>> > >>> ImageJ doesn't support 32 bit integer gray scale images. > >>> > >>> Supported are 8bit and 16bit integer as well as 32bit float. > Furthermore > >> 24bit (3 X 8bit) RGB and index color 8bit. > >>> > >>> Regards > >>> > >>> Herbie > >>> > >>> ::::::::::::::::::::::::::::::::::::::::::::: > >>> Am 12.02.19 um 19:15 schrieb Robert Lockwood: > >>>> Working with Java I have raw data files with 32 bit integer gray scale > >> data > >>>> which I read into a byte[] array. I process these data as ints > looking > >> for > >>>> adjacent pixels that have the same value in order to debug a problem > >> with > >>>> the camera. > >>>> I'd like to create a scaled grayscale RGB from the original data so > >> that I > >>>> may color the detected adjacent pixels to allow us to detect patterns > >>>> visually but I don't understand how to create and populate a grayscale > >>>> integer ImageJ array and have not found an example by Google > searching. > >>>> How do I do this? > >>>> TIA > >>>> -- > >>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html > >>> > >>> -- > >>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html > >> > >> -- > >> ImageJ mailing list: http://imagej.nih.gov/ij/list.html > >> > > > > -- > > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Once you have a ShortProcessor, you can convert directly to a ColorProcessor using:
ColorProcessor cp = sp.convertToColorProcessor(); I am not sure how the 16-bit values are converted to 8+8+8 RGB. You may have to call sp.setMinAndMax(min,max); before the conversion. But...it looks as if the safest route might be: sp.setMinAndMax(min,max); // in case you want to adjust these ColorProcessor cp = sp.convertToByteProcessor(true).convertToRGB() I'm unclear on the difference between convertToRGB() and convertToColorProcessor. From the documentation: public ColorProcessor <https://imagej.nih.gov/ij/developer/api/ij/process/ColorProcessor.html> convertToColorProcessor() Returns an RGB version of this image as a ColorProcessor. public ImageProcessor <https://imagej.nih.gov/ij/developer/api/ij/process/ImageProcessor.html> convertToRGB() Returns an RGB version of this image as a ColorProcessor. The only difference is in the declared type of the returned processor. Both are actually "ColorProcessor", but notice that "convertToRGB()" returns an "ImageProcessor" (which just happens to be a "ColorProcessor". Can someone explain the reason for this apparent duplication? -- Kenneth Sloan [hidden email] Vision is the art of seeing what is invisible to others. > On Feb 12, 2019, at 16:21, Robert Lockwood <[hidden email]> wrote: > > Thanks, Kenneth, this is a stand-alone program to detect adjacent pixels > that have t: > he same values and save the probably converted data as grayscale > with the detected pixels in color. > > Here is the code I have now, compiles and runs but unfinished > > // read raw image file > byte[] bytes = Files.toByteArray(dFile); > // represent as integers > IntBuffer rawIntImage = ByteBuffer.wrap(bytes).asIntBuffer(); > > // set up for data using imageJ > final ImagePlus imp = IJ.createImage(dFile.getName(), "16-bit", > NCOLS, NROWS, 1); > final ShortProcessor sp = (ShortProcessor) imp.getProcessor(); > final short[] shortImage = (short[]) sp.getPixels(); > int index = 0; > while(rawIntImage.hasRemaining()) { > shortImage[index++] = (short) rawIntImage.get(); > } > // sp.convertToByte(true).convertToRGB(); // What is returned > here? > > I need "IntBuffer rawIntImage" to use to detect the adjacent duplicate > pixels > I'm assuming that 'convertToByte' will do the brightness and contrast > mapping returning a ByteProcessor, is that correct? Then I need to convert > to RGB ? > > > On Tue, Feb 12, 2019 at 1:19 PM Kenneth Sloan <[hidden email]> > wrote: > >> Ah...if the data are really 16-bit, then my recommendation is to >> import the image as a 32-bit float, apply Brightness/Contrast, >> and use an OVERLAY to highlight the problem pixels. >> >> But, if you really want RGB, import as 32-bit, adjust, >> and use Image->Type->RGB and you are done. >> >> Note that this loses precision (but, you can't see much more than >> 8-bits on the screen anyway). >> >> You also lose access to the actual original pixel values - but >> perhaps that's not important. >> >> I do this routinely with data that claim to be 32-bit floats in the >> range [0.0..1.0). These are essentially 24-bit unsigned integers. >> >> It looks like there is no reason for you to import a byte array >> and twiddle bits to construct ints. Fiji will happily import >> the image as 32-bit float, adjust brightness/contrast, and convert >> to RGB (if that's what you want). >> >> Is your code to find and highlight problem pixels written as a >> Fiji plugin, or as a stand-alone Java program? >> >> >> -- >> Kenneth Sloan >> [hidden email] >> Vision is the art of seeing what is invisible to others. >> >> >> >> >> >>> On Feb 12, 2019, at 14:48, Robert Lockwood <[hidden email]> wrote: >>> >>> When I look at the imported images in Fiji I apply Brightness/Contrast >> with >>> auto for a decent image. >>> >>> If I can do the same thing in Java and then convert to RGB I can then >>> manipulate the pixels I've identified by my comparison code. >>> >>> BTW the values in my 32 bit first came from the camera as defined as C >>> unsigned shorts so all the values are less than 64K so I can extract the >>> Java short values easily. >>> >>> On Tue, Feb 12, 2019 at 11:20 AM Kenneth Sloan <[hidden email]> >>> wrote: >>> >>>> If you do this in Java, I think there are a couple of workarounds. >>>> >>>> Here's one idea: Since you already can "process these data as ints", you >>>> should be able to create your own 8-bit RGB image. Of course, you only >>>> get 8-bits of gray scale. >>>> >>>> Here's another idea: you should be able to import the image as a 32-bit >>>> float image. If there is non-zero data in the upper 8 bits, the image >>>> will look >>>> very strange, but at least you'll have a 32-bit array. Next, take each >>>> 32-bit float pixel value and use Float.floatToRawIntBits to get >>>> your 32-bit integer values. >>>> >>>> Since you can already create the int values from your byte array, I >> would >>>> start >>>> with that idea. >>>> >>>> Be careful about signed/unsigned. >>>> >>>> Finally, I would consider creating a 24-bit integer gray-scale value, >> and >>>> using >>>> that as a 32-bit float (using Float.intBitsToFloat). This gives you a >>>> float image >>>> where the values are between 0.0 and 1.0. You can then use an Overlay >> to >>>> highlight >>>> the problem pixels. Use either idea above to get a 32-bit unsigned >> value, >>>> and >>>> scale it to 24-bits. Convert that to a float, and store it in a 32-bit >>>> float image. >>>> >>>> Or, simply create a 16-bit integer gray scale image, and use an Overlay. >>>> >>>> Your choice may depend on what you know about the range of values. The >>>> advantage of >>>> my 24-bit version above is that you have a bit more flexibility in >>>> dynamically adjusting >>>> the range of displayed gray levels. The disadvantage is that the >> numbers >>>> will all >>>> be presented as (0.0..1.0) instead of [0..65535] (for the 16-bit >> version) >>>> >>>> -- >>>> Kenneth Sloan >>>> [hidden email] >>>> Vision is the art of seeing what is invisible to others. >>>> >>>> >>>> >>>> >>>> >>>>> On Feb 12, 2019, at 12:37, Herbie <[hidden email]> wrote: >>>>> >>>>> Good day, >>>>> >>>>> ImageJ doesn't support 32 bit integer gray scale images. >>>>> >>>>> Supported are 8bit and 16bit integer as well as 32bit float. >> Furthermore >>>> 24bit (3 X 8bit) RGB and index color 8bit. >>>>> >>>>> Regards >>>>> >>>>> Herbie >>>>> >>>>> ::::::::::::::::::::::::::::::::::::::::::::: >>>>> Am 12.02.19 um 19:15 schrieb Robert Lockwood: >>>>>> Working with Java I have raw data files with 32 bit integer gray scale >>>> data >>>>>> which I read into a byte[] array. I process these data as ints >> looking >>>> for >>>>>> adjacent pixels that have the same value in order to debug a problem >>>> with >>>>>> the camera. >>>>>> I'd like to create a scaled grayscale RGB from the original data so >>>> that I >>>>>> may color the detected adjacent pixels to allow us to detect patterns >>>>>> visually but I don't understand how to create and populate a grayscale >>>>>> integer ImageJ array and have not found an example by Google >> searching. >>>>>> How do I do this? >>>>>> TIA >>>>>> -- >>>>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >>>>> >>>>> -- >>>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >>>> >>>> -- >>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >>>> >>> >>> -- >>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >> >> -- >> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >> > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
OK, I'm soldiering on...
My IDE tells me I need a cast: ColorProcessor cp = (ColorProcessor) sp.convertToByteProcessor(true).convertToRGB() sp.getMin() & sp.getMax() return reasonable values. cp.get(500) for both .convertToRGB() and convertToColorProcessor() return negative values. Apparently there are 3 color components so there's no alpha. Does this mean that the data are 24 bit? On Tue, Feb 12, 2019 at 3:12 PM Kenneth Sloan <[hidden email]> wrote: > Once you have a ShortProcessor, you can convert directly to a > ColorProcessor using: > > ColorProcessor cp = sp.convertToColorProcessor(); > > I am not sure how the 16-bit values are converted to 8+8+8 RGB. You may > have to call > > sp.setMinAndMax(min,max); > > before the conversion. > > But...it looks as if the safest route might be: > > sp.setMinAndMax(min,max); // in case you want to adjust these > ColorProcessor cp = sp.convertToByteProcessor(true).convertToRGB() > > I'm unclear on the difference between convertToRGB() and > convertToColorProcessor. From the documentation: > > public ColorProcessor < > https://imagej.nih.gov/ij/developer/api/ij/process/ColorProcessor.html> > convertToColorProcessor() > Returns an RGB version of this image as a ColorProcessor. > > public ImageProcessor < > https://imagej.nih.gov/ij/developer/api/ij/process/ImageProcessor.html> > convertToRGB() > Returns an RGB version of this image as a ColorProcessor. > > The only difference is in the declared type of the returned processor. > Both are actually "ColorProcessor", but notice > that "convertToRGB()" returns an "ImageProcessor" (which just happens to > be a "ColorProcessor". > > Can someone explain the reason for this apparent duplication? > > -- > Kenneth Sloan > [hidden email] > Vision is the art of seeing what is invisible to others. > > > > > > > On Feb 12, 2019, at 16:21, Robert Lockwood <[hidden email]> wrote: > > > > Thanks, Kenneth, this is a stand-alone program to detect adjacent pixels > > that have t: > > he same values and save the probably converted data as grayscale > > with the detected pixels in color. > > > > Here is the code I have now, compiles and runs but unfinished > > > > // read raw image file > > byte[] bytes = Files.toByteArray(dFile); > > // represent as integers > > IntBuffer rawIntImage = ByteBuffer.wrap(bytes).asIntBuffer(); > > > > // set up for data using imageJ > > final ImagePlus imp = IJ.createImage(dFile.getName(), > "16-bit", > > NCOLS, NROWS, 1); > > final ShortProcessor sp = (ShortProcessor) imp.getProcessor(); > > final short[] shortImage = (short[]) sp.getPixels(); > > int index = 0; > > while(rawIntImage.hasRemaining()) { > > shortImage[index++] = (short) rawIntImage.get(); > > } > > // sp.convertToByte(true).convertToRGB(); // What is returned > > here? > > > > I need "IntBuffer rawIntImage" to use to detect the adjacent duplicate > > pixels > > I'm assuming that 'convertToByte' will do the brightness and contrast > > mapping returning a ByteProcessor, is that correct? Then I need to > convert > > to RGB ? > > > > > > On Tue, Feb 12, 2019 at 1:19 PM Kenneth Sloan <[hidden email]> > > wrote: > > > >> Ah...if the data are really 16-bit, then my recommendation is to > >> import the image as a 32-bit float, apply Brightness/Contrast, > >> and use an OVERLAY to highlight the problem pixels. > >> > >> But, if you really want RGB, import as 32-bit, adjust, > >> and use Image->Type->RGB and you are done. > >> > >> Note that this loses precision (but, you can't see much more than > >> 8-bits on the screen anyway). > >> > >> You also lose access to the actual original pixel values - but > >> perhaps that's not important. > >> > >> I do this routinely with data that claim to be 32-bit floats in the > >> range [0.0..1.0). These are essentially 24-bit unsigned integers. > >> > >> It looks like there is no reason for you to import a byte array > >> and twiddle bits to construct ints. Fiji will happily import > >> the image as 32-bit float, adjust brightness/contrast, and convert > >> to RGB (if that's what you want). > >> > >> Is your code to find and highlight problem pixels written as a > >> Fiji plugin, or as a stand-alone Java program? > >> > >> > >> -- > >> Kenneth Sloan > >> [hidden email] > >> Vision is the art of seeing what is invisible to others. > >> > >> > >> > >> > >> > >>> On Feb 12, 2019, at 14:48, Robert Lockwood <[hidden email]> > wrote: > >>> > >>> When I look at the imported images in Fiji I apply Brightness/Contrast > >> with > >>> auto for a decent image. > >>> > >>> If I can do the same thing in Java and then convert to RGB I can then > >>> manipulate the pixels I've identified by my comparison code. > >>> > >>> BTW the values in my 32 bit first came from the camera as defined as C > >>> unsigned shorts so all the values are less than 64K so I can extract > the > >>> Java short values easily. > >>> > >>> On Tue, Feb 12, 2019 at 11:20 AM Kenneth Sloan < > [hidden email]> > >>> wrote: > >>> > >>>> If you do this in Java, I think there are a couple of workarounds. > >>>> > >>>> Here's one idea: Since you already can "process these data as ints", > you > >>>> should be able to create your own 8-bit RGB image. Of course, you > only > >>>> get 8-bits of gray scale. > >>>> > >>>> Here's another idea: you should be able to import the image as a > 32-bit > >>>> float image. If there is non-zero data in the upper 8 bits, the image > >>>> will look > >>>> very strange, but at least you'll have a 32-bit array. Next, take > each > >>>> 32-bit float pixel value and use Float.floatToRawIntBits to get > >>>> your 32-bit integer values. > >>>> > >>>> Since you can already create the int values from your byte array, I > >> would > >>>> start > >>>> with that idea. > >>>> > >>>> Be careful about signed/unsigned. > >>>> > >>>> Finally, I would consider creating a 24-bit integer gray-scale value, > >> and > >>>> using > >>>> that as a 32-bit float (using Float.intBitsToFloat). This gives you a > >>>> float image > >>>> where the values are between 0.0 and 1.0. You can then use an Overlay > >> to > >>>> highlight > >>>> the problem pixels. Use either idea above to get a 32-bit unsigned > >> value, > >>>> and > >>>> scale it to 24-bits. Convert that to a float, and store it in a > 32-bit > >>>> float image. > >>>> > >>>> Or, simply create a 16-bit integer gray scale image, and use an > Overlay. > >>>> > >>>> Your choice may depend on what you know about the range of values. > The > >>>> advantage of > >>>> my 24-bit version above is that you have a bit more flexibility in > >>>> dynamically adjusting > >>>> the range of displayed gray levels. The disadvantage is that the > >> numbers > >>>> will all > >>>> be presented as (0.0..1.0) instead of [0..65535] (for the 16-bit > >> version) > >>>> > >>>> -- > >>>> Kenneth Sloan > >>>> [hidden email] > >>>> Vision is the art of seeing what is invisible to others. > >>>> > >>>> > >>>> > >>>> > >>>> > >>>>> On Feb 12, 2019, at 12:37, Herbie <[hidden email]> wrote: > >>>>> > >>>>> Good day, > >>>>> > >>>>> ImageJ doesn't support 32 bit integer gray scale images. > >>>>> > >>>>> Supported are 8bit and 16bit integer as well as 32bit float. > >> Furthermore > >>>> 24bit (3 X 8bit) RGB and index color 8bit. > >>>>> > >>>>> Regards > >>>>> > >>>>> Herbie > >>>>> > >>>>> ::::::::::::::::::::::::::::::::::::::::::::: > >>>>> Am 12.02.19 um 19:15 schrieb Robert Lockwood: > >>>>>> Working with Java I have raw data files with 32 bit integer gray > scale > >>>> data > >>>>>> which I read into a byte[] array. I process these data as ints > >> looking > >>>> for > >>>>>> adjacent pixels that have the same value in order to debug a problem > >>>> with > >>>>>> the camera. > >>>>>> I'd like to create a scaled grayscale RGB from the original data so > >>>> that I > >>>>>> may color the detected adjacent pixels to allow us to detect > patterns > >>>>>> visually but I don't understand how to create and populate a > grayscale > >>>>>> integer ImageJ array and have not found an example by Google > >> searching. > >>>>>> How do I do this? > >>>>>> TIA > >>>>>> -- > >>>>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html > >>>>> > >>>>> -- > >>>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html > >>>> > >>>> -- > >>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html > >>>> > >>> > >>> -- > >>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html > >> > >> -- > >> ImageJ mailing list: http://imagej.nih.gov/ij/list.html > >> > > > > -- > > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
You started with a scalar (float) image. You converted it to an 8-bit integer image.
The convertToRGB() simply replicates the 8-bit byte for the R,G,B channels and sets A==0; By the time you converted to RGB, you had only 8 bits. get(500) uses ImageProcessor.get() and returns an int. I always treat images as 2D and avoid fetching pixels by pretending to know how they are laid out in memory - but I presume that get() returns the bits representing RGBA as an int. I suppose stepping through a 1D array is "faster", but (to my taste) that's a false economy. A negative value indicates that the R value is > 127. Since it's a grayscale image, that makes R=G=B > 127, so "brighter than middle gray". None of this says anything about how many bits you started with. If you want to know the range of values in the original data, I recommend that you compute that yourself while processing the original 32 bit ints. How did you end up creating the ORIGINAL image - did you import it as a FloatProcessor, or did you build your byte array and construct 32 bit ints? For absolute control, I would use your byte array methods to construct pixel values, determine the range of actual values, and then create a (scaled, if necessary) 16-bit ShortProcessor. I would then set min and max, and convert directly from the ShortProcessor to a ColorProcessor. For ease of programming, I would try to import the original image as a 32-bit float image, and then use get(). I'm guessing (because I don't even do this) that get() will return the actual 32-bits used to represent the Float. But, I could be wrong about that. All of this simply avoids the bit-twiddling you are doing with the byte array. I would then proceed as above: determine range, create a (possibly scaled) 16-bit ShortProcessor, and convert to RGB. I would probably only use the "import as Float" method if I were *certain* that the raw data was no bigger than 24 bits. The acid test is to display the image. I might also create a test suite consisting of (small) 32-bit images with known values testing the various boundaries - say 0xffffffff, and 0x7fffffff, and 0x00ffffff, and 0x0000ffff, for starters. I would start with images that had constant values (one image for each of the above values), and then images consisting of ramps from 0 to each of the above values. Finally, ramps that start a bit higher than 0, to test your setting of min/max. That's 12 test images in all. Have fun! -- Kenneth Sloan [hidden email] Vision is the art of seeing what is invisible to others. > On Feb 12, 2019, at 18:22, Robert Lockwood <[hidden email]> wrote: > > OK, I'm soldiering on... > My IDE tells me I need a cast: > ColorProcessor cp = (ColorProcessor) > sp.convertToByteProcessor(true).convertToRGB() > sp.getMin() & sp.getMax() return reasonable values. > cp.get(500) for both .convertToRGB() and convertToColorProcessor() return > negative values. Apparently there are 3 color components so there's no > alpha. Does this mean that the data are 24 bit? > > > > > On Tue, Feb 12, 2019 at 3:12 PM Kenneth Sloan <[hidden email] <mailto:[hidden email]>> > wrote: > >> Once you have a ShortProcessor, you can convert directly to a >> ColorProcessor using: >> >> ColorProcessor cp = sp.convertToColorProcessor(); >> >> I am not sure how the 16-bit values are converted to 8+8+8 RGB. You may >> have to call >> >> sp.setMinAndMax(min,max); >> >> before the conversion. >> >> But...it looks as if the safest route might be: >> >> sp.setMinAndMax(min,max); // in case you want to adjust these >> ColorProcessor cp = sp.convertToByteProcessor(true).convertToRGB() >> >> I'm unclear on the difference between convertToRGB() and >> convertToColorProcessor. From the documentation: >> >> public ColorProcessor < >> https://imagej.nih.gov/ij/developer/api/ij/process/ColorProcessor.html <https://imagej.nih.gov/ij/developer/api/ij/process/ColorProcessor.html>> >> convertToColorProcessor() >> Returns an RGB version of this image as a ColorProcessor. >> >> public ImageProcessor < >> https://imagej.nih.gov/ij/developer/api/ij/process/ImageProcessor.html <https://imagej.nih.gov/ij/developer/api/ij/process/ImageProcessor.html>> >> convertToRGB() >> Returns an RGB version of this image as a ColorProcessor. >> >> The only difference is in the declared type of the returned processor. >> Both are actually "ColorProcessor", but notice >> that "convertToRGB()" returns an "ImageProcessor" (which just happens to >> be a "ColorProcessor". >> >> Can someone explain the reason for this apparent duplication? >> >> -- >> Kenneth Sloan >> [hidden email] >> Vision is the art of seeing what is invisible to others. >> >> >> >> >> >>> On Feb 12, 2019, at 16:21, Robert Lockwood <[hidden email]> wrote: >>> >>> Thanks, Kenneth, this is a stand-alone program to detect adjacent pixels >>> that have t: >>> he same values and save the probably converted data as grayscale >>> with the detected pixels in color. >>> >>> Here is the code I have now, compiles and runs but unfinished >>> >>> // read raw image file >>> byte[] bytes = Files.toByteArray(dFile); >>> // represent as integers >>> IntBuffer rawIntImage = ByteBuffer.wrap(bytes).asIntBuffer(); >>> >>> // set up for data using imageJ >>> final ImagePlus imp = IJ.createImage(dFile.getName(), >> "16-bit", >>> NCOLS, NROWS, 1); >>> final ShortProcessor sp = (ShortProcessor) imp.getProcessor(); >>> final short[] shortImage = (short[]) sp.getPixels(); >>> int index = 0; >>> while(rawIntImage.hasRemaining()) { >>> shortImage[index++] = (short) rawIntImage.get(); >>> } >>> // sp.convertToByte(true).convertToRGB(); // What is returned >>> here? >>> >>> I need "IntBuffer rawIntImage" to use to detect the adjacent duplicate >>> pixels >>> I'm assuming that 'convertToByte' will do the brightness and contrast >>> mapping returning a ByteProcessor, is that correct? Then I need to >> convert >>> to RGB ? >>> >>> >>> On Tue, Feb 12, 2019 at 1:19 PM Kenneth Sloan <[hidden email]> >>> wrote: >>> >>>> Ah...if the data are really 16-bit, then my recommendation is to >>>> import the image as a 32-bit float, apply Brightness/Contrast, >>>> and use an OVERLAY to highlight the problem pixels. >>>> >>>> But, if you really want RGB, import as 32-bit, adjust, >>>> and use Image->Type->RGB and you are done. >>>> >>>> Note that this loses precision (but, you can't see much more than >>>> 8-bits on the screen anyway). >>>> >>>> You also lose access to the actual original pixel values - but >>>> perhaps that's not important. >>>> >>>> I do this routinely with data that claim to be 32-bit floats in the >>>> range [0.0..1.0). These are essentially 24-bit unsigned integers. >>>> >>>> It looks like there is no reason for you to import a byte array >>>> and twiddle bits to construct ints. Fiji will happily import >>>> the image as 32-bit float, adjust brightness/contrast, and convert >>>> to RGB (if that's what you want). >>>> >>>> Is your code to find and highlight problem pixels written as a >>>> Fiji plugin, or as a stand-alone Java program? >>>> >>>> >>>> -- >>>> Kenneth Sloan >>>> [hidden email] >>>> Vision is the art of seeing what is invisible to others. >>>> >>>> >>>> >>>> >>>> >>>>> On Feb 12, 2019, at 14:48, Robert Lockwood <[hidden email]> >> wrote: >>>>> >>>>> When I look at the imported images in Fiji I apply Brightness/Contrast >>>> with >>>>> auto for a decent image. >>>>> >>>>> If I can do the same thing in Java and then convert to RGB I can then >>>>> manipulate the pixels I've identified by my comparison code. >>>>> >>>>> BTW the values in my 32 bit first came from the camera as defined as C >>>>> unsigned shorts so all the values are less than 64K so I can extract >> the >>>>> Java short values easily. >>>>> >>>>> On Tue, Feb 12, 2019 at 11:20 AM Kenneth Sloan < >> [hidden email]> >>>>> wrote: >>>>> >>>>>> If you do this in Java, I think there are a couple of workarounds. >>>>>> >>>>>> Here's one idea: Since you already can "process these data as ints", >> you >>>>>> should be able to create your own 8-bit RGB image. Of course, you >> only >>>>>> get 8-bits of gray scale. >>>>>> >>>>>> Here's another idea: you should be able to import the image as a >> 32-bit >>>>>> float image. If there is non-zero data in the upper 8 bits, the image >>>>>> will look >>>>>> very strange, but at least you'll have a 32-bit array. Next, take >> each >>>>>> 32-bit float pixel value and use Float.floatToRawIntBits to get >>>>>> your 32-bit integer values. >>>>>> >>>>>> Since you can already create the int values from your byte array, I >>>> would >>>>>> start >>>>>> with that idea. >>>>>> >>>>>> Be careful about signed/unsigned. >>>>>> >>>>>> Finally, I would consider creating a 24-bit integer gray-scale value, >>>> and >>>>>> using >>>>>> that as a 32-bit float (using Float.intBitsToFloat). This gives you a >>>>>> float image >>>>>> where the values are between 0.0 and 1.0. You can then use an Overlay >>>> to >>>>>> highlight >>>>>> the problem pixels. Use either idea above to get a 32-bit unsigned >>>> value, >>>>>> and >>>>>> scale it to 24-bits. Convert that to a float, and store it in a >> 32-bit >>>>>> float image. >>>>>> >>>>>> Or, simply create a 16-bit integer gray scale image, and use an >> Overlay. >>>>>> >>>>>> Your choice may depend on what you know about the range of values. >> The >>>>>> advantage of >>>>>> my 24-bit version above is that you have a bit more flexibility in >>>>>> dynamically adjusting >>>>>> the range of displayed gray levels. The disadvantage is that the >>>> numbers >>>>>> will all >>>>>> be presented as (0.0..1.0) instead of [0..65535] (for the 16-bit >>>> version) >>>>>> >>>>>> -- >>>>>> Kenneth Sloan >>>>>> [hidden email] >>>>>> Vision is the art of seeing what is invisible to others. >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>>> On Feb 12, 2019, at 12:37, Herbie <[hidden email]> wrote: >>>>>>> >>>>>>> Good day, >>>>>>> >>>>>>> ImageJ doesn't support 32 bit integer gray scale images. >>>>>>> >>>>>>> Supported are 8bit and 16bit integer as well as 32bit float. >>>> Furthermore >>>>>> 24bit (3 X 8bit) RGB and index color 8bit. >>>>>>> >>>>>>> Regards >>>>>>> >>>>>>> Herbie >>>>>>> >>>>>>> ::::::::::::::::::::::::::::::::::::::::::::: >>>>>>> Am 12.02.19 um 19:15 schrieb Robert Lockwood: >>>>>>>> Working with Java I have raw data files with 32 bit integer gray >> scale >>>>>> data >>>>>>>> which I read into a byte[] array. I process these data as ints >>>> looking >>>>>> for >>>>>>>> adjacent pixels that have the same value in order to debug a problem >>>>>> with >>>>>>>> the camera. >>>>>>>> I'd like to create a scaled grayscale RGB from the original data so >>>>>> that I >>>>>>>> may color the detected adjacent pixels to allow us to detect >> patterns >>>>>>>> visually but I don't understand how to create and populate a >> grayscale >>>>>>>> integer ImageJ array and have not found an example by Google >>>> searching. >>>>>>>> How do I do this? >>>>>>>> TIA >>>>>>>> -- >>>>>>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >>>>>>> >>>>>>> -- >>>>>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >>>>>> >>>>>> -- >>>>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >>>>>> >>>>> >>>>> -- >>>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >>>> >>>> -- >>>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >>>> >>> >>> -- >>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html >> >> >> -- >> ImageJ mailing list: http://imagej.nih.gov/ij/list.html <http://imagej.nih.gov/ij/list.html> >> > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html <http://imagej.nih.gov/ij/list.html> -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by Robert Lockwood
Hi all,
> ImageJ doesn't support 32 bit integer gray scale images. It is more precise to write "ImageJ1 doesn't support 32-bit integer grayscale images." ImageJ2 does support them. Here is Groovy code illustrating it: --snip-- v = Integer.MAX_VALUE int[] values = [ v, v - 1, v - 2, v / 4, v / 4 - 3, v / 8 - 5, v / 3, v / 2 + 5, v / 2 + 3, v / 2 + 7, v / 2 + 11, v / 2 + 13 ] img = net.imglib2.img.array.ArrayImgs.ints(values, 4, 3) access = img.randomAccess() for (y=0; y<3; y++) { for (x=0; x<4; x++) { access.setPosition(x, 0) access.setPosition(y, 1) println("($x, $y) = ${access.get()} (array value=${values[4*y+x]})") } } --snap-- Regards, Curtis -- Curtis Rueden LOCI software architect - https://loci.wisc.edu/software ImageJ2 lead, Fiji maintainer - https://imagej.net/User:Rueden Have you tried the Image.sc Forum? https://forum.image.sc/ On Tue, Feb 12, 2019 at 12:38 PM Herbie <[hidden email]> wrote: > Good day, > > ImageJ doesn't support 32 bit integer gray scale images. > > Supported are 8bit and 16bit integer as well as 32bit float. Furthermore > 24bit (3 X 8bit) RGB and index color 8bit. > > Regards > > Herbie > > ::::::::::::::::::::::::::::::::::::::::::::: > Am 12.02.19 um 19:15 schrieb Robert Lockwood: > > Working with Java I have raw data files with 32 bit integer gray scale > data > > which I read into a byte[] array. I process these data as ints looking > for > > adjacent pixels that have the same value in order to debug a problem with > > the camera. > > > > I'd like to create a scaled grayscale RGB from the original data so that > I > > may color the detected adjacent pixels to allow us to detect patterns > > visually but I don't understand how to create and populate a grayscale > > integer ImageJ array and have not found an example by Google searching. > > > > How do I do this? > > TIA > > > > -- > > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by Kenneth Sloan-2
Thanks, Kenneth, Herby, Michael, I've not worked with anything other than
16 bit unsigned images as that's our native data. I've been able to create the image that I wanted with one problem. I've replaced the second of the adjacent pixels with the same value with a green pixel in the RGB image I created from my 16 bit data but some are green and some are white! I'll need to save a file with the unexamined RGB data next, I guess, to see if its a processing artifact. On Tue, Feb 12, 2019 at 7:07 PM Kenneth Sloan <[hidden email]> wrote: > You started with a scalar (float) image. You converted it to an 8-bit > integer image. > The convertToRGB() simply replicates the 8-bit byte for the R,G,B channels > and sets A==0; > > By the time you converted to RGB, you had only 8 bits. > > get(500) uses ImageProcessor.get() and returns an int. I always treat > images > as 2D and avoid fetching pixels by pretending to know how they are laid out > in memory - but I presume that get() returns the bits representing RGBA as > an int. > I suppose stepping through a 1D array is "faster", but (to my taste) > that's a false economy. > > A negative value indicates that the R value is > 127. Since it's a > grayscale image, that > makes R=G=B > 127, so "brighter than middle gray". > > None of this says anything about how many bits you started with. If you > want to know > the range of values in the original data, I recommend that you compute > that yourself while > processing the original 32 bit ints. > > How did you end up creating the ORIGINAL image - did you import it as a > FloatProcessor, or > did you build your byte array and construct 32 bit ints? > > For absolute control, I would use your byte array methods to construct > pixel values, determine > the range of actual values, and then create a (scaled, if necessary) > 16-bit ShortProcessor. > > I would then set min and max, and convert directly from the ShortProcessor > to a ColorProcessor. > > For ease of programming, I would try to import the original image as a > 32-bit float image, and > then use get(). I'm guessing (because I don't even do this) that get() > will return the actual 32-bits > used to represent the Float. But, I could be wrong about that. All of > this simply avoids the bit-twiddling > you are doing with the byte array. I would then proceed as above: > determine range, create a (possibly scaled) > 16-bit ShortProcessor, and convert to RGB. I would probably only use the > "import as Float" method if I > were *certain* that the raw data was no bigger than 24 bits. > > The acid test is to display the image. I might also create a test suite > consisting of (small) 32-bit > images with known values testing the various boundaries - say 0xffffffff, > and 0x7fffffff, and 0x00ffffff, and 0x0000ffff, for starters. I would > start with images that had constant values (one image for each of the above > values), and then > images consisting of ramps from 0 to each of the above values. Finally, > ramps that start a bit higher than 0, to test > your setting of min/max. That's 12 test images in all. > > Have fun! > > -- > Kenneth Sloan > [hidden email] > Vision is the art of seeing what is invisible to others. > > > > > > > On Feb 12, 2019, at 18:22, Robert Lockwood <[hidden email]> wrote: > > OK, I'm soldiering on... > My IDE tells me I need a cast: > ColorProcessor cp = (ColorProcessor) > sp.convertToByteProcessor(true).convertToRGB() > sp.getMin() & sp.getMax() return reasonable values. > cp.get(500) for both .convertToRGB() and convertToColorProcessor() return > negative values. Apparently there are 3 color components so there's no > alpha. Does this mean that the data are 24 bit? > > > > > On Tue, Feb 12, 2019 at 3:12 PM Kenneth Sloan <[hidden email]> > wrote: > > Once you have a ShortProcessor, you can convert directly to a > ColorProcessor using: > > ColorProcessor cp = sp.convertToColorProcessor(); > > I am not sure how the 16-bit values are converted to 8+8+8 RGB. You may > have to call > > sp.setMinAndMax(min,max); > > before the conversion. > > But...it looks as if the safest route might be: > > sp.setMinAndMax(min,max); // in case you want to adjust these > ColorProcessor cp = sp.convertToByteProcessor(true).convertToRGB() > > I'm unclear on the difference between convertToRGB() and > convertToColorProcessor. From the documentation: > > public ColorProcessor < > https://imagej.nih.gov/ij/developer/api/ij/process/ColorProcessor.html> > convertToColorProcessor() > Returns an RGB version of this image as a ColorProcessor. > > public ImageProcessor < > https://imagej.nih.gov/ij/developer/api/ij/process/ImageProcessor.html> > convertToRGB() > Returns an RGB version of this image as a ColorProcessor. > > The only difference is in the declared type of the returned processor. > Both are actually "ColorProcessor", but notice > that "convertToRGB()" returns an "ImageProcessor" (which just happens to > be a "ColorProcessor". > > Can someone explain the reason for this apparent duplication? > > -- > Kenneth Sloan > [hidden email] > Vision is the art of seeing what is invisible to others. > > > > > > On Feb 12, 2019, at 16:21, Robert Lockwood <[hidden email]> wrote: > > Thanks, Kenneth, this is a stand-alone program to detect adjacent pixels > that have t: > he same values and save the probably converted data as grayscale > with the detected pixels in color. > > Here is the code I have now, compiles and runs but unfinished > > // read raw image file > byte[] bytes = Files.toByteArray(dFile); > // represent as integers > IntBuffer rawIntImage = ByteBuffer.wrap(bytes).asIntBuffer(); > > // set up for data using imageJ > final ImagePlus imp = IJ.createImage(dFile.getName(), > > "16-bit", > > NCOLS, NROWS, 1); > final ShortProcessor sp = (ShortProcessor) imp.getProcessor(); > final short[] shortImage = (short[]) sp.getPixels(); > int index = 0; > while(rawIntImage.hasRemaining()) { > shortImage[index++] = (short) rawIntImage.get(); > } > // sp.convertToByte(true).convertToRGB(); // What is returned > here? > > I need "IntBuffer rawIntImage" to use to detect the adjacent duplicate > pixels > I'm assuming that 'convertToByte' will do the brightness and contrast > mapping returning a ByteProcessor, is that correct? Then I need to > > convert > > to RGB ? > > > On Tue, Feb 12, 2019 at 1:19 PM Kenneth Sloan <[hidden email]> > wrote: > > Ah...if the data are really 16-bit, then my recommendation is to > import the image as a 32-bit float, apply Brightness/Contrast, > and use an OVERLAY to highlight the problem pixels. > > But, if you really want RGB, import as 32-bit, adjust, > and use Image->Type->RGB and you are done. > > Note that this loses precision (but, you can't see much more than > 8-bits on the screen anyway). > > You also lose access to the actual original pixel values - but > perhaps that's not important. > > I do this routinely with data that claim to be 32-bit floats in the > range [0.0..1.0). These are essentially 24-bit unsigned integers. > > It looks like there is no reason for you to import a byte array > and twiddle bits to construct ints. Fiji will happily import > the image as 32-bit float, adjust brightness/contrast, and convert > to RGB (if that's what you want). > > Is your code to find and highlight problem pixels written as a > Fiji plugin, or as a stand-alone Java program? > > > -- > Kenneth Sloan > [hidden email] > Vision is the art of seeing what is invisible to others. > > > > > > On Feb 12, 2019, at 14:48, Robert Lockwood <[hidden email]> > > wrote: > > > When I look at the imported images in Fiji I apply Brightness/Contrast > > with > > auto for a decent image. > > If I can do the same thing in Java and then convert to RGB I can then > manipulate the pixels I've identified by my comparison code. > > BTW the values in my 32 bit first came from the camera as defined as C > unsigned shorts so all the values are less than 64K so I can extract > > the > > Java short values easily. > > On Tue, Feb 12, 2019 at 11:20 AM Kenneth Sloan < > > [hidden email]> > > wrote: > > If you do this in Java, I think there are a couple of workarounds. > > Here's one idea: Since you already can "process these data as ints", > > you > > should be able to create your own 8-bit RGB image. Of course, you > > only > > get 8-bits of gray scale. > > Here's another idea: you should be able to import the image as a > > 32-bit > > float image. If there is non-zero data in the upper 8 bits, the image > will look > very strange, but at least you'll have a 32-bit array. Next, take > > each > > 32-bit float pixel value and use Float.floatToRawIntBits to get > your 32-bit integer values. > > Since you can already create the int values from your byte array, I > > would > > start > with that idea. > > Be careful about signed/unsigned. > > Finally, I would consider creating a 24-bit integer gray-scale value, > > and > > using > that as a 32-bit float (using Float.intBitsToFloat). This gives you a > float image > where the values are between 0.0 and 1.0. You can then use an Overlay > > to > > highlight > the problem pixels. Use either idea above to get a 32-bit unsigned > > value, > > and > scale it to 24-bits. Convert that to a float, and store it in a > > 32-bit > > float image. > > Or, simply create a 16-bit integer gray scale image, and use an > > Overlay. > > > Your choice may depend on what you know about the range of values. > > The > > advantage of > my 24-bit version above is that you have a bit more flexibility in > dynamically adjusting > the range of displayed gray levels. The disadvantage is that the > > numbers > > will all > be presented as (0.0..1.0) instead of [0..65535] (for the 16-bit > > version) > > > -- > Kenneth Sloan > [hidden email] > Vision is the art of seeing what is invisible to others. > > > > > > On Feb 12, 2019, at 12:37, Herbie <[hidden email]> wrote: > > Good day, > > ImageJ doesn't support 32 bit integer gray scale images. > > Supported are 8bit and 16bit integer as well as 32bit float. > > Furthermore > > 24bit (3 X 8bit) RGB and index color 8bit. > > > Regards > > Herbie > > ::::::::::::::::::::::::::::::::::::::::::::: > Am 12.02.19 um 19:15 schrieb Robert Lockwood: > > Working with Java I have raw data files with 32 bit integer gray > > scale > > data > > which I read into a byte[] array. I process these data as ints > > looking > > for > > adjacent pixels that have the same value in order to debug a problem > > with > > the camera. > I'd like to create a scaled grayscale RGB from the original data so > > that I > > may color the detected adjacent pixels to allow us to detect > > patterns > > visually but I don't understand how to create and populate a > > grayscale > > integer ImageJ array and have not found an example by Google > > searching. > > How do I do this? > TIA > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > > > -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Free forum by Nabble | Edit this page |