Thank you for such a quick reply. Error was mine. TypeInt16 was incorrect and along with your explanation of how conversion works issue is resolved. Both OIIO and OpenCv are producing expected results.
Automatic conversion is really handy, my 2 cents is that for automatic conversion to be as useful as it can be, it might want to have both conversion options: based on full range and min_max. Cheers -Arman > On Oct 13, 2020, at 11:49 PM, Larry Gritz <[email protected]> wrote: > > buf.get_pixels(roi, TypeInt16, cvb.data); > > > I think that should be TypeUInt16, it's unsigned if you declared the cv::Mat > with CV_16U. But I don't think that is your primary problem. > > I don't know OpenCV well enough to know how the cv::normalize() behaves, but > I'm guessing that you are converting the full range of uint16 in cvb into the > 0-255 range of cvb8? (I'm not exactly sure why you are reading into a 16 bit > matrix and then using OpenCV to convert to 8 bits. You could have just used > get_pixels to write directly into the 8 bit matrix.) > > For the sake of nomenclature, we generally speak of the normalized ranges, > that is, in a uint8 file, a code value of 0 means 0.0 and a code value of 255 > means 1.0. For a uint16 file, a code value of 0 is 0.0 and a code value of > 65535 means 1.0. The normalized range for integer encoded files is always > presumed to be 0.0 - 1.0, but that can be encoded as uint8, or uint16, or > whatever, depending on the file type and desired precision. > > Looking at the stats of the two images (for simplicity, let's just look at > the first subimage of each, using oiiotool --stats zser8.tif zser16.tif): > > zser8.tif : 160 x 128, 1 channel, uint8 tiff (11 subimages) > Stats Min: 0 (of 255) > Stats Max: 255 (of 255) > Stats Avg: 119.29 (of 255) > Stats StdDev: 31.98 (of 255) > > zser16.tif : 160 x 128, 1 channel, uint16 tiff (11 subimages) > Stats Min: 626 (of 65535) > Stats Max: 1034 (of 65535) > Stats Avg: 838.42 (of 65535) > Stats StdDev: 49.75 (of 65535) > > These two files are NOT the same images simply represented as uint8 and > uint16 values, respectively. They are quite different. > > zser8.tif fully covers the range of a uint8, 0-255. Its average is 119 (a > mid-gray tone of 0.467 of the maximum range) and you can see from the > standard deviation (32/255 = 12.5% of the full range) that you should see > some meaningful contrast. > > However, zser16.tif has a min-to-max range of only 626 to 1034 in code > values, but normalized to the 0-65535 range, that means its minimum is 0.0096 > (=626/65535) and its maximum is 0.0158 (=1034/65535). The average is 0.0128 > and standard deviation merely 0.000759. That is a very narrow range of > values, and very dark. > > If you convert zser16.tif to an 8-bit unsigned data type, you would end up > with a minimum code value of 2 and a maximum of 4, but indeed as you note, > almost all pixels should have value 3 (= 0.0128*255). > > I think that given these input files, both OIIO and OpenCV are doing exactly > what you are telling it to do. These two files do not represent the same > image. > > >> On Oct 13, 2020, at 9:58 PM, Arman Garakani <[email protected] >> <mailto:[email protected]>> wrote: >> >> Attached are small tif multi-image files. zser8.tif and zser16.tif. They are >> 160x128 single channel and 16 bit. They are also very small. >> <zser8.tif><zser16.tif> >> >> zser8.tif works fine. zser16.tif does not ( displays all black ). I have >> tried not converting or automatic conversion to u8 or float. Forcing >> conversion to uint8 fills the destination with 0x03. >> >> To check issues with 16bit or float display, I used cv::normalize to convert >> 16bit to 8bit. Result was random stuff — normalized. >> >> In terms of automatic conversion. I could not find documentation describing >> how it is done. If there is please point me to it. >> >> Here is the test code: >> >> auto test_file = [](const ustring& filename){ >> >> ImageBuf buf(filename); >> int nsubimages = buf.nsubimages(); >> const ImageSpec& bspec = buf.spec(); >> int xres = bspec.width; >> int yres = bspec.height; >> int channels = bspec.nchannels; >> int bps = bspec.get_int_attribute("oiio:BitsPerSample", -1); >> std::cout << xres << "," << yres << "," << channels << ":" << bps << >> std::endl; >> >> // Now read them from cache and display them >> namedWindow("oiio", WINDOW_AUTOSIZE | WINDOW_OPENGL); >> for (int ss = 0; ss < nsubimages; ss++){ >> buf.reset(filename, ss, 0); >> std::string datetime = >> buf.spec().get_string_attribute("DateTime"); >> std::cout << buf.subimage() << " @ " << datetime << std::endl; >> ROI roi = buf.roi(); >> cv::Mat cvb (yres,xres, CV_16U); >> cv::Mat cvb8 (yres,xres, CV_8U); >> >> buf.get_pixels(roi, TypeInt16, cvb.data); >> cv::normalize(cvb, cvb8, 0, 255, NORM_MINMAX, CV_8UC1); >> cv::imshow("oiio", cvb8); >> cv::waitKey(); >> } >> }; >> >> _______________________________________________ >> Oiio-dev mailing list >> [email protected] <mailto:[email protected]> >> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org > > -- > Larry Gritz > [email protected] <mailto:[email protected]> > > > > > _______________________________________________ > Oiio-dev mailing list > [email protected] > http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
_______________________________________________ Oiio-dev mailing list [email protected] http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
