landam / grass-gis-git-migration-test

0 stars 0 forks source link

i.rgb.his, i.his.rgb, d.his support for >8 bit #29

Open landam opened 5 years ago

landam commented 5 years ago

Reported by hamish on 5 Oct 2009 06:49 UTC Hi,

it would be nice if i.rgb.his, i.his.rgb, d.his modules could have support for >8 bit colors.

attached is a patch which does this for i.rgb.his.

i.his.rgb and d.his are a bit deeper into the max=255 and casting CELLs to unsigned char.

Hamish

GRASS GIS version and provenance

svn-trunk

Migrated-From: https://trac.osgeo.org/grass/ticket/774

landam commented 5 years ago

Attachment from hamish on 5 Oct 2009 06:50 UTC patch to add 16bit channel support to i.rgb.his https://trac.osgeo.org/grass/attachment/ticket/774/irgbhis_16bit.diff

landam commented 5 years ago

Attachment from hamish on 7 Oct 2009 03:50 UTC updated patch for i.rgb.his and i.his.rgb https://trac.osgeo.org/grass/attachment/ticket/774/irgbhis_16bit2.diff

landam commented 5 years ago

Attachment from nikosa on 25 Aug 2016 00:34 UTC Rewritten, outputs in ranges as defined in the HSL/HSV color space model https://trac.osgeo.org/grass/attachment/ticket/774/i.rgb.his.diff

landam commented 5 years ago

Comment by hamish on 5 Oct 2009 08:00 UTC for d.his main.c we can probably pass HIS_toRGB() something like (int)(value[atcol]/pow(2, bitdepth-8)) to rescale >8bit to 0,255.

opt_bit_depth->options = "8-16";

(we can only set the color to 8-bit per channel, right? so we have to degrade at some point.. might as well be here)

Hamish

landam commented 5 years ago

Comment by glynn on 6 Oct 2009 00:39 UTC Replying to [ticket:774 hamish]:

it would be nice if i.rgb.his, i.his.rgb, d.his modules could have support for >8 bit colors.

i.his.rgb and d.his are a bit deeper into the max=255 and casting CELLs to unsigned char.

d.his uses the raster's colour table, so it will work with integer rasters of any bit depth, as well as FP rasters. The use of 8 bits within d.his is due to both GRASS' colour tables and the display architecture using 8-bit intensity values.

I'm not sure that there is much point in changing the display architecture when display hardware which supports more than 8-bit intensity is so rare (I know that some image formats support more than this, but that's not much use if the images are going to be displayed on hardware which only supports 8 bits).

For i. or r. modules, you can either use the raster's colour table, or you need an associated scale parameter for each input raster (and possibly an offset parameter as well), or you require that all inputs be FP rasters where 0.0 is black and 1.0 is white.

Using the colour table limits you to 8-bit resolution, but it does at least allow you to use maps with more resolution as inputs.

landam commented 5 years ago

Comment by hamish on 7 Oct 2009 03:58 UTC updated patch attached allowing >8 bit support for i.rgb.his and i.his.rgb. Patch is against latest 6.5svn.

Note round-trip is a little lossy due to hexagonal approximation to the color-cone. TODO: use real cone geometry maths.

These modules write out colr/ tables as min,max of channel. Would it be better to write them out as 0,max_level for the particular bit-depth? e.g. 0,255 for 8-bit and 0,2047 for 11-bit. Then d.rgb and d.his give natural looking results without subtle extra steps.

Hamish

landam commented 5 years ago

Comment by glynn on 7 Oct 2009 06:52 UTC Replying to [comment:3 hamish]:

These modules write out colr/ tables as min,max of channel. Would it be better to write them out as 0,max_level for the particular bit-depth? e.g. 0,255 for 8-bit and 0,2047 for 11-bit. Then d.rgb and d.his give natural looking results without subtle extra steps.

Apart from anything else, assigning black/white to the min/max of the data is definitely wrong.

Beyond that, I suggest:

  1. changing bit_depth= to max_level=, and reading the maps as DCELL, so that the modules work with both integer and FP data, including integer data where max isn't a power of two.

  2. making the output FCELL, with values in the range 0.0 to 1.0 (or possibly 0.0 to 360.0 for hue), and using those values for 0% and 100% intensity. Note that d.his uses G_get_raster_row_colors(), so it doesn't care about the actual values, only the corresponding colours.

  3. replacing both modules with scripts which use r.mapcalc.

  4. Offering the option of "conical" HSV, i.e. RGB->YUV, H=atan2(U,V).

landam commented 5 years ago

Comment by hamish on 1 Aug 2013 03:07 UTC renewed interest, see https://trac.osgeo.org/grass/ticket/2048.

landam commented 5 years ago

Comment by neteler on 30 Dec 2015 13:27 UTC See also https://trac.osgeo.org/grass/ticket/2048

landam commented 5 years ago

Modified by @landam on 12 May 2016 06:36 UTC

landam commented 5 years ago

Comment by nikosa on 24 Aug 2016 11:17 UTC I tried irgbhis_16bit2.diff without reading much the changes it introduces. Going from RGB to HIS and back to RGB gives NULL, for all red, blue and green input maps.

landam commented 5 years ago

Comment by nikosa on 25 Aug 2016 00:48 UTC The attached diff works for me, for bitnesses >8-bit. The outputs hue, saturation and intensity are in their expected range, as per the HSL/HSV color space model. There is still an issue on how to instruct the output to be DCELL and not FCELL. Accordingly, I'd like to modify i.his.rgb.

Source for the math of concern are:

The current/old implementation is identical to the one documented at http://www.gis.usu.edu/manuals/labbook/erdas/manuals/FieldGuide.pdf ERDAS' field guide. I think, however, it was meant to deal/avoid the case when hue is undefined (this being the case when the max and min values of a band/image are identical) and, perhaps, other issues with floating point math(?).

See also:

landam commented 5 years ago

Modified by @landam on 25 Aug 2016 15:51 UTC

landam commented 5 years ago

Comment by @landam on 27 Aug 2016 13:42 UTC Milestone renamed

landam commented 5 years ago

Comment by nikosa on 11 Sep 2016 11:08 UTC Instead of http://arxiv.org/abs/1107.3348, I wanted to point to https://arxiv.org/pdf/1107.4396.pdf.

landam commented 5 years ago

Comment by nikosa on 12 Sep 2016 14:16 UTC Modified versions for i.rgb.his and i.his.rgb in respective directories at https://trac.osgeo.org/grass/browser/sandbox/alexandris?order=name.

I have reasons to support closing this ticket, after checking and updating all relevant modules or scripts that use them, of course!

A reproducible session, below, to verify that:

'''Note, however,''' the modified versions of the modules break the current functionality of i.pansharpen. This is because the the intensity values, after the modified i.rgb.his, play between 0 and 1. Before, intensity was ranging in [0,255]. The fix should be, at least, conceptually, fairly easy. See also past discussions in https://trac.osgeo.org/grass/ticket/2048.

Reproducible session


```sh

# check range of Landsat bands
for BAND in 10 20 30; do echo `echo -e "Landsat band ${BAND}: " && r.info -r lsat7_2002_${BAND}` ;done

Landsat band 10: min=42 max=255  # this is blue
Landsat band 20: min=28 max=255  # this is green
Landsat band 30: min=1 max=255   # this is red

# convert (rgb) to his, 8-bit
i.rgb.his r=lsat7_2002_30 g=lsat7_2002_20 bl=lsat7_2002_10 h=h8 i=i8 s=s8

# rescale to 16-bit in order to test the `bits` option
for BAND in 10 20 30; do r.rescale lsat7_2002_$BAND from=0,255 output=lsat7_2002_${BAND}_16 to=0,65535 ;done

Rescale lsat7_2002_10[0,255] to lsat7_2002_10_16[0,65535]
Rescale lsat7_2002_20[0,255] to lsat7_2002_20_16[0,65535]
Rescale lsat7_2002_30[0,255] to lsat7_2002_30_16[0,65535]

# convert again, bits=16
i.rgb.his r=lsat7_2002_30_16 g=lsat7_2002_20_16 bl=lsat7_2002_10_16 h=h16 i=i16 s=s16 bits=16

# check h, i, s output ranges, 8 & 16-bit
for DIMENSION in h i s; do echo `echo "${DIMENSION}  8:" && r.info -r ${DIMENSION}8` && echo `echo -e "${DIMENSION} 16:" && r.info -r ${DIMENSION}16` ;done

h 8: min=0 max=359.434
h 16: min=0 max=359.434
i 8: min=0.08431373 max=1
i 16: min=0.08431373 max=1
s 8: min=0 max=1
s 16: min=0 max=1

# convert (his) back to rgb
i.his.rgb h=h8 i=i8 s=s8 r=https://trac.osgeo.org/grass/changeset/8 g=g8 bl=b8 bits=8
i.his.rgb h=h16 i=i16 s=s16 r=https://trac.osgeo.org/grass/changeset/16 g=g16 bl=b16 bits=16

# check rgb ranges
for COLOR in r g b; do echo `echo "${COLOR}  8:" && r.info -r ${COLOR}8` && echo `echo -e "${COLOR} 16:" && r.info -r ${COLOR}16` ;done

r 8: min=0 max=255
r 16: min=256 max=65535
g 8: min=28 max=255
g 16: min=7195.999 max=65535
b 8: min=42 max=255
b 16: min=10794 max=65535

# There is some "loss" or "smoothing" after the roundtrip. Note, for red the
# minimum is now `1` and not `0`.

# Some stats to verify

# input 8-bit Landsat 7 bands
for BAND in 10 20 30; do echo "lsat7_2002_${BAND} (8-bit): " && r.univar -g --q lsat7_2002_${BAND} && echo -e '\n' ;done

lsat7_2002_10 (8-bit):
n=250325
null_cells=0
cells=250325
min=42
max=255
range=213
mean=85.473624288425
mean_of_abs=85.473624288425
stddev=20.6960320098858
variance=428.325740954217
coeff_var=24.2133549175924
sum=21396185

lsat7_2002_20 (8-bit):
n=250325
null_cells=0
cells=250325
min=28
max=255
range=227
mean=70.9216418655748
mean_of_abs=70.9216418655748
stddev=23.3183338152895
variance=543.744691921275
coeff_var=32.8790101327423
sum=17753460

lsat7_2002_30 (8-bit):
n=250325
null_cells=0
cells=250325
min=1
max=255
range=254
mean=66.6989074203535
mean_of_abs=66.6989074203535
stddev=34.7033706761684
variance=1204.32393628754
coeff_var=52.029893769412
sum=16696404

# rescaled to 16-bit Landsat 7 bands
for BAND in 10 20 30; do echo "lsat7_2002_${BAND} (16-bit): " && r.univar -g --q lsat7_2002_${BAND}_16 && echo -e '\n' ;done

lsat7_2002_10 (16-bit):
n=250325
null_cells=0
cells=250325
min=10794
max=65535
range=54741
mean=21966.7214421252
mean_of_abs=21966.7214421252
stddev=5318.88022654064
variance=28290486.8642851
coeff_var=24.2133549175924
sum=5498819545

lsat7_2002_20 (16-bit):
n=250325
null_cells=0
cells=250325
min=7196
max=65535
range=58339
mean=18226.8619594527
mean_of_abs=18226.8619594527
stddev=5992.81179052941
variance=35913793.1567083
coeff_var=32.8790101327423
sum=4562639220

lsat7_2002_30 (16-bit):
n=250325
null_cells=0
cells=250325
min=257
max=65535
range=65278
mean=17141.6192070309
mean_of_abs=17141.6192070309
stddev=8918.76626377528
variance=79544391.667856
coeff_var=52.029893769412
sum=4290975828

# his, 8-bit
for DIMENSION in h i s; do echo "${DIMENSION} (8-bit): " && r.univar -g --q ${DIMENSION}8 && echo -e '\n' ;done

h (8-bit):
n=250007
null_cells=318
cells=250325
min=0
max=359.433959960938
range=359.433959960938
mean=232.677368810375
mean_of_abs=232.677368810375
stddev=47.0943195962118
variance=2217.87493823014
coeff_var=20.2401805714901
sum=58170970.9441754

i (8-bit):
n=250325
null_cells=0
cells=250325
min=0.084313727915287
max=1
range=0.915686272084713
mean=0.294945252267712
mean_of_abs=0.294945252267712
stddev=0.10312914101826
variance=0.0106356197271642
coeff_var=34.9655199483101
sum=73832.1702739149

s (8-bit):
n=250325
null_cells=0
cells=250325
min=0
max=1
range=1
mean=0.188441316597818
mean_of_abs=0.188441316597818
stddev=0.105874696347741
variance=0.0112094513267264
coeff_var=56.1844388795609
sum=47171.5725773489

# his, 16-bit
for DIMENSION in h i s; do echo "${DIMENSION} (16-bit): " && r.univar -g --q ${DIMENSION}16 && echo -e '\n' ;done

h (16-bit):
n=250007
null_cells=318
cells=250325
min=0
max=359.433959960938
range=359.433959960938
mean=232.677368810375
mean_of_abs=232.677368810375
stddev=47.0943195962118
variance=2217.87493823014
coeff_var=20.2401805714901
sum=58170970.9441754

i (16-bit):
n=250325
null_cells=0
cells=250325
min=0.084313727915287
max=1
range=0.915686272084713
mean=0.294945252267712
mean_of_abs=0.294945252267712
stddev=0.10312914101826
variance=0.0106356197271642
coeff_var=34.9655199483101
sum=73832.1702739149

s (16-bit):
n=250325
null_cells=0
cells=250325
min=0
max=1
range=1
mean=0.188441316597818
mean_of_abs=0.188441316597818
stddev=0.105874696347741
variance=0.0112094513267264
coeff_var=56.1844388795609
sum=47171.5725773489

# colors, 8-bit
for COLOR in r g b; do echo "${COLOR} (8-bit):" && r.univar -g --q ${COLOR}8 &&
    echo -e '\n' ;done
r (8-bit):
n=250007
null_cells=318
cells=250325
min=0
max=255
range=255
mean=66.2976036670973
mean_of_abs=66.2976036670973
stddev=34.0979922976592
variance=1162.67307873122
coeff_var=51.4317115726787
sum=16574865

g (8-bit):
n=250007
null_cells=318
cells=250325
min=27.9999961853027
max=255
range=227.000003814697
mean=70.6895694237074
mean_of_abs=70.6895694237074
stddev=22.3983713595429
variance=501.687039559992
coeff_var=31.6855393831711
sum=17672887.1829128

b (8-bit):
n=250007
null_cells=318
cells=250325
min=42
max=255
range=213
mean=85.2600618087387
mean_of_abs=85.2600618087387
stddev=19.8145003705753
variance=392.614424935528
coeff_var=23.2400727259904
sum=21315612.2726173

# colors, 16-bit
for COLOR in r g b; do echo "${COLOR} (16-bit):" && r.univar -g --q ${COLOR}16 && echo -e '\n' ;done

r (16-bit):
n=250007
null_cells=318
cells=250325
min=256
max=65535
range=65279
mean=17080.4321518997
mean_of_abs=17080.4321518997
stddev=8757.35508357642
variance=76691268.0598418
coeff_var=51.2712734999647
sum=4270227601

g (16-bit):
n=250007
null_cells=318
cells=250325
min=7195.9990234375
max=65535
range=58339.0009765625
mean=18167.2193426611
mean_of_abs=18167.2193426611
stddev=5756.38144044411
variance=33135927.2878894
coeff_var=31.6855393875644
sum=4541932006.20068

b (16-bit):
n=250007
null_cells=318
cells=250325
min=10794
max=65535
range=54741
mean=21911.8358886264
mean_of_abs=21911.8358886264
stddev=5092.32659532506
variance=25931790.1534549
coeff_var=23.2400727223788
sum=5478112355.00781
landam commented 5 years ago

Comment by @landam on 26 Jan 2018 08:59 UTC The status of this issue is not clear.

landam commented 5 years ago

Comment by neteler on 26 Jan 2018 11:40 UTC Ticket retargeted after milestone closed

landam commented 5 years ago

Comment by mlennert on 7 Feb 2018 12:57 UTC Nikos, how confident are you about your version in the sandbox ? Can it replace the version in trunk ?

landam commented 5 years ago

Comment by nikosa on 7 Feb 2018 16:23 UTC The statistics in https://trac.osgeo.org/grass/ticket/774#comment:13, show that going from either an 8-bit or 16-bit RGB to HIS and back to RGB, figures are not scrambled. Some rounding applies, as exemplified in the same stats above. Even visually, I confirmed (not documented here) that the old and the new versions perform the same.

It will break i.pansharpen, unless i.pansharpen treats intensity ranging in [0,1].

Nevertheless, another set of tests would be certainly good to have to confirm the correctness of the new version.

landam commented 5 years ago

Comment by neteler on 2 Mar 2018 16:39 UTC Replying to [comment:17 Nikos Alexandris]:

The statistics in https://trac.osgeo.org/grass/ticket/774#comment:13, show that going from either an 8-bit or 16-bit RGB to HIS and back to RGB, figures are not scrambled. Some rounding applies, as exemplified in the same stats above. Even visually, I confirmed (not documented here) that the old and the new versions perform the same.

This sounds very promising.

It will break i.pansharpen, unless i.pansharpen treats intensity ranging in [0,1].

Would it be hard to add that to i.pansharpen?

Nevertheless, another set of tests would be certainly good to have to confirm the correctness of the new version.

I'd suggest to "svn move" it from sandbox to addons for wider testing with g.extention.

landam commented 5 years ago

Comment by wenzeslaus on 2 Mar 2018 17:13 UTC Replying to [comment:16 mlennert]:

Nikos, how confident are you about your version in the sandbox ? Can it replace the version in trunk ?

This is a computational danger zone, I think also automatic tests are required. I suggest to add tests to the modules in trunk and use them to test the new modules (whether they are in sandbox or addons).

landam commented 5 years ago

Comment by nikosa on 5 Mar 2018 08:49 UTC Replying to [comment:19 wenzeslaus]:

Replying to [comment:16 mlennert]:

Nikos, how confident are you about your version in the sandbox ? Can it replace the version in trunk ?

This is a computational danger zone, I think also automatic tests are required. I suggest to add tests to the modules in trunk and use them to test the new modules (whether they are in sandbox or addons).

I fully agree. These tests would be another good exercise for me. If I only can make it to the upcoming code sprint, I will work on these.

Please, see also/don't forget the other two:

landam commented 5 years ago

Comment by nikosa on 22 Mar 2018 18:57 UTC A gunittest is available at: https://github.com/NikosAlexandris/test_color_space_conversions/blob/master/test_color_space_roundtrips.py

The tests compare the input R, G and B images (Landsat imagery from the nc_spm_08_grass7 test data set) from 6- up to 16-bit (by rescaling the original inputs) with the output R, G and B after a roundtrip from RGB to HIS and back to RGB color spaces.

They confirm, as far as I understand, that the suggested modules

work with precision levels 0.1 and 0.01. Setting the precision to 0.001, will cause the the test fail for bits= >= 15.

HIS values are also tested for being inside the expected ranges.

A review of the script would be much appreciated in order to confirm its functionality.

Some points:

Can someone move the test to trunk as suggested by Vaclav?

landam commented 5 years ago

Modified by neteler on 12 Jun 2018 20:48 UTC

landam commented 5 years ago

Comment by @landam on 25 Sep 2018 16:51 UTC All enhancement tickets should be assigned to 7.6 milestone.

landam commented 5 years ago

Comment by @landam on 25 Jan 2019 21:07 UTC Ticket retargeted after milestone closed