danforthcenter / plantcv

Plant phenotyping with image analysis
Mozilla Public License 2.0
665 stars 265 forks source link

How to handle uint8/[0,255] format HSI? #1599

Open HaleySchuhl opened 2 months ago

HaleySchuhl commented 2 months ago

Start a discussion about anything you would like So far plantcv has added support for a handful of different hyper/multispectral image formats (#972, #956, #781) and @rayn-alex brought up a formatting incompatibility that could make sense to handle automatically.

"It might make sense to introduce a cast to float, possibly already in read_data depending on the input data type. So the Spectral_data objects are always float32/0-1. The RAYN Vision System camera for example produces uint8/0-255 multispectral images and I need to convert to float32 and rescale them to 0-1 in my pcv workflows because otherwise the results do not make sense."

This sounds like a good argument to cast Spectral_data during read_data, or even inside _find_closest / other ideas ??

rayn-alex commented 2 months ago

I think it makes more sense in read_data because then all Spectral_data objects have the same array data type. Is there anything against that?

I guess the only argument against needless conversion is the floating-point error, but I guess it's negligible for these applications, right?

rayn-alex commented 2 months ago

Here is a sample image from the RVS Camera sample_set.zip

HaleySchuhl commented 1 month ago

Thank you @rayn-alex this is super helpful. And my apologies for my slower response. I would agree that handling various datatypes as soon as possible makes the most sense, and we can evaluate if the decimal accuracy has an impact practically on results.

How do you currently convert your images into a "plantcv friendly datatype" ?

rayn-alex commented 1 month ago

No worries.

Just like this:

spectral_data = readimage(filename=img_file, mode='envi')
spectral_data.array_data = spectral_data.array_data.astype("float32")  # required for further calculations
if spectral_data.d_type == np.uint8:  # only convert if data seems to be uint8
    spectral_data.array_data = spectral_data.array_data / 255  # convert 0-255 (orig.) to 0-1 range