i.rgb.his/i.his.rgb and 16bit images

12 messages Options
Embed this post
Permalink
Georg Kaspar-2

i.rgb.his/i.his.rgb and 16bit images

Reply Threaded More More options
Print post
Permalink
Hi,
after some problems converting 16bit quickbird images from rgb to ihs
and vice versa (see user list), i took a look at the source code and
discovered that pixel values are normalised by dividing by 255.
Naturally this leads to wrong values when using data with more than 8bit.

rgb2his.c

37 for (sample = 0; sample < columns; sample++) {
38 scaler = (double)rowbuffer[0][sample];
39 scaler /= 255.0;
40 scaleg = (double)rowbuffer[1][sample];
41 scaleg /= 255.0;
42 scaleb = (double)rowbuffer[2][sample];
43 scaleb /= 255.0;

this could be corrected by replacing the constant 255 with a variable
according to the encoding of the image.
i'm not quite shure how to do this (only did some scripting so far) -
can somebody help?
bests,
Georg

_______________________________________________
grass-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/grass-dev
Georg Kaspar-2

Re: i.rgb.his/i.his.rgb and 16bit images

Reply Threaded More More options
Print post
Permalink
Georg Kaspar wrote:
> this could be corrected by replacing the constant 255 with a variable
> according to the encoding of the image.
> i'm not quite shure how to do this (only did some scripting so far) -
> can somebody help?

to be more precise: how can i read-out the encoding of a raster file (or
the maximum value) in c? I already took a look at the programmer's
manual but didn't find what i'm looking for (i'm accustomed to javadoc...).

_______________________________________________
grass-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/grass-dev
hamish-2

Re: Re: i.rgb.his/i.his.rgb and 16bit images

Reply Threaded More More options
Print post
Permalink
In reply to this post by Georg Kaspar-2
Georg wrote:
> Georg Kaspar wrote:
> > this could be corrected by replacing the constant 255
> with a variable according to the encoding of the image.
> > i'm not quite shure how to do this (only did some
> scripting so far) - can somebody help?

see also 'gdalinfo -stats' on raw data and 'r.info -r' on grass
maps.


where is rgb2his.c, I don't see it in grass 6.5

if that is a C module, ideally the 256 should be made a
module option which defaults to 256.

see attached patch x6.5, I'm not quite sure if the approach is
right though so haven't applied it.

Also, for a long time I have wanted to replace the quick
sexidecimal method with propper cone geometry math, but not
found the time. It doesn't seem too hard, and computers are
much faster these days. :)


> to be more precise: how can i read-out the encoding of a
> raster file (or the maximum value) in c? I already took a
> look at the programmer's manual but didn't find what i'm
> looking for (i'm accustomed to javadoc...).

from d.legend:

    struct Range range;
    struct FPRange fprange;

...
    if (!fp) {
        if (G_read_range(map_name, mapset, &range) == -1)
            G_fatal_error(_("Range information for <%s> not available (run r.support)"),
                          map_name);

        G_get_range_min_max(&range, &min_ind, &max_ind);
        if (G_is_c_null_value(&min_ind))
            G_fatal_error(_("Input map contains no data"));

.
.
.

    else {                      /* is fp */
        if (G_read_fp_range(map_name, mapset, &fprange) == -1)
            G_fatal_error(_("Range information for <%s> not available"),
                          map_name);

        G_get_fp_range_min_max(&fprange, &dmin, &dmax);




but the max value should be the channel's max, not the observed
max, so I think the module option is better.

as for dull greys, the grey255 color map is there to force min=0
max=255. If you want grey66535 just copy the 255 file and edit
to suit.


Hamish



[i_rgb_his_depth.diff]

Index: imagery/i.rgb.his/r2hmain.c
===================================================================
--- imagery/i.rgb.his/r2hmain.c (revision 39354)
+++ imagery/i.rgb.his/r2hmain.c (working copy)
@@ -33,9 +33,11 @@
     struct Option *opt_hue, *opt_red;
     struct Option *opt_inten, *opt_green;
     struct Option *opt_sat, *opt_blue;
+    struct Option *opt_nlevels;
     struct GModule *module;
     int fd_input[3];
     int fd_output[3];
+    int nlevels;
 
     /* Initialize GIS engine */
     G_gisinit(argv[0]);
@@ -72,9 +74,21 @@
     opt_sat->key = "saturation_output";
     opt_sat->description = _("Name for output raster map (saturation)");
 
+    opt_nlevels = G_define_option();
+    opt_nlevels->key = "n_levels";
+    opt_nlevels->type = TYPE_INTEGER;
+    opt_nlevels->required = NO;
+    opt_nlevels->answer = "255";
+    opt_nlevels->description = _("Number of possible levels in base data");
+
     if (G_parser(argc, argv))
  exit(EXIT_FAILURE);
 
+
+    nlevels = atoi(opt_nlevels->answer);
+    if (nlevels <= 0)
+ G_fatal_error(_("Invalid number of levels"));
+
     /* get dimension of the image */
     rows = G_window_rows();
     cols = G_window_cols();
@@ -89,16 +103,16 @@
 
  for (band = 0; band < 3; band++)
     if (G_get_map_row(fd_input[band], rowbuffer[band], i) < 0)
- G_fatal_error(_("Unable to read raster map row %d"), i);
+ G_fatal_error(_("Unable to read raster map row %ld"), i);
 
  /* process this row of the map */
- rgb2his(rowbuffer, cols);
+ rgb2his(rowbuffer, cols, nlevels);
 
  /* write out the new row for each cell map */
  for (band = 0; band < 3; band++)
     if (G_put_raster_row(fd_output[band], rowbuffer[band], CELL_TYPE)
  < 0)
- G_fatal_error(_("Failed writing raster map row %d"), i);
+ G_fatal_error(_("Failed writing raster map row %ld"), i);
     }
 
     closefiles(opt_hue->answer, opt_inten->answer, opt_sat->answer,
Index: imagery/i.rgb.his/rgb2his.c
===================================================================
--- imagery/i.rgb.his/rgb2his.c (revision 39354)
+++ imagery/i.rgb.his/rgb2his.c (working copy)
@@ -17,9 +17,10 @@
    each band is processed and written out.   CWU GIS Lab: DBS 8/90 */
 
 #include <grass/gis.h>
+#include <grass/glocale.h>
 #include "globals.h"
 
-void rgb2his(CELL * rowbuffer[3], int columns)
+void rgb2his(CELL * rowbuffer[3], int columns, int nlevels)
 {
     int sample; /* sample indicator                      */
     double red; /* the red band output                   */
@@ -33,14 +34,17 @@
     double intens; /* intensity                             */
     double sat; /* saturation                            */
     double hue = 0.0L; /* hue                                   */
+    double nlevels_fp; /* expanded bitdepth (eg 255)            */
 
+    nlevels_fp = nlevels * 1.0;
+
     for (sample = 0; sample < columns; sample++) {
  scaler = (double)rowbuffer[0][sample];
- scaler /= 255.0;
+ scaler /= nlevels_fp;
  scaleg = (double)rowbuffer[1][sample];
- scaleg /= 255.0;
+ scaleg /= nlevels_fp;
  scaleb = (double)rowbuffer[2][sample];
- scaleb /= 255.0;
+ scaleb /= nlevels_fp;
 
  high = scaler;
  if (scaleg > high)
@@ -64,8 +68,8 @@
     /*        hue = -1.0; */
     hue = 0.0;
     rowbuffer[0][sample] = (unsigned char)hue;
-    rowbuffer[1][sample] = (unsigned char)(intens * 255.);
-    rowbuffer[2][sample] = (unsigned char)(sat * 255.);
+    rowbuffer[1][sample] = (unsigned char)(intens * nlevels_fp);
+    rowbuffer[2][sample] = (unsigned char)(sat * nlevels_fp);
  }
  /*
    else chromatic case
@@ -78,6 +82,7 @@
    sat = (high-low)/(2 - (high-low));
  */
  sat = (high - low) / (2 - high - low);
+
     red = (high - scaler) / (high - low);
     green = (high - scaleg) / (high - low);
     blue = (high - scaleb) / (high - low);
@@ -108,9 +113,9 @@
     /*
        set the HIS output values
      */
-    rowbuffer[0][sample] = (unsigned char)(255.0 * hue / 360.0 + 0.5);
-    rowbuffer[1][sample] = (unsigned char)(intens * 255. + 0.5);
-    rowbuffer[2][sample] = (unsigned char)(sat * 255. + 0.5);
+    rowbuffer[0][sample] = (unsigned char)(nlevels_fp * hue / 360.0 + 0.5);
+    rowbuffer[1][sample] = (unsigned char)(intens * nlevels_fp + 0.5);
+    rowbuffer[2][sample] = (unsigned char)(sat * nlevels_fp + 0.5);
  }
     }
 }
Index: imagery/i.rgb.his/description.html
===================================================================
--- imagery/i.rgb.his/description.html (revision 39354)
+++ imagery/i.rgb.his/description.html (working copy)
@@ -24,4 +24,5 @@
 with acknowledgements to Ali Vali, Space Research
 Center, for the core routine.
 
-<p><i>Last changed: $Date$</i>
+<p>
+<i>Last changed: $Date$</i>
Index: imagery/i.rgb.his/globals.h
===================================================================
--- imagery/i.rgb.his/globals.h (revision 39354)
+++ imagery/i.rgb.his/globals.h (working copy)
@@ -8,6 +8,6 @@
 void openfiles(char *, char *, char *, char *, char *, char *,
        int[3], int[3], CELL *[3]);
 /* rgb2his.c */
-void rgb2his(CELL *[3], int);
+void rgb2his(CELL *[3], int, int);
 
 #endif /* __GLOBALS_H__ */


_______________________________________________
grass-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/grass-dev
hamish-2

Re: Re: i.rgb.his/i.his.rgb and 16bit images

Reply Threaded More More options
Print post
Permalink
Hamish wrote:
> where is rgb2his.c, I don't see it in grass 6.5
>
> if that is a C module, ideally the 256 should be made a
> module option which defaults to 256.

[... time passes ... I found it ...]

> see attached patch x6.5,



H




_______________________________________________
grass-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/grass-dev
Glynn Clements

Re: Re: i.rgb.his/i.his.rgb and 16bit images

Reply Threaded More More options
Print post
Permalink
In reply to this post by Georg Kaspar-2

Georg Kaspar wrote:

> > this could be corrected by replacing the constant 255 with a variable
> > according to the encoding of the image.
> > i'm not quite shure how to do this (only did some scripting so far) -
> > can somebody help?
>
> to be more precise: how can i read-out the encoding of a raster file (or
> the maximum value) in c? I already took a look at the programmer's
> manual but didn't find what i'm looking for (i'm accustomed to javadoc...).

You can read the minimum and maximum values using G_read_range() or
G_read_fp_range() (these have been renamed from G_* to Rast_* in 7.0).

However, that tells you the minimum and maximum values which actually
occur, not the nominal 0 and 1 values which should be used for
colour-space conversion.

A more suitable approach is to use the colour tables, e.g. using
G_get_raster_row_colors() rather than G_get_raster_row(). This is the
mechanism used by r.composite.

Then, the user can apply grey-scale colour tables which match the
nominal range of the data (e.g. the predefined "grey255" colour table
maps 0 to black and 255 to white, while "grey1.0" maps 0 to black and
1.0 to white).

--
Glynn Clements <[hidden email]>
_______________________________________________
grass-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/grass-dev
Georg Kaspar-2

Re: i.rgb.his/i.his.rgb and 16bit images

Reply Threaded More More options
Print post
Permalink
In reply to this post by hamish-2
Hamish wrote:
> see attached patch x6.5, I'm not quite sure if the approach is
> right though so haven't applied it.

thanks for the effort. i compiled the module with the applied patch, but
the output is still encoded in 8 bit. can'ts see why though...

_______________________________________________
grass-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/grass-dev
hamish-2

Re: Re: i.rgb.his/i.his.rgb and 16bit images

Reply Threaded More More options
Print post
Permalink
[16bit quickbird images + i.rgb2his, i.his2rgb]

Hamish wrote:
> > see attached patch x6.5, I'm not quite sure if the approach is
> > right though so haven't applied it.

Georg Kaspar wrote:
> thanks for the effort. i compiled the module with the
> applied patch, but the output is still encoded in 8 bit.
> can'ts see why though...

Very sorry if this is a dumb question, but did you set n_levels=
to 65535? (it defaults to 8bit)
Does 'i.rgb2his --help' show the option?
what does 'r.info -r' say about the 3 r,g,b bands?

really that option name is misleading, it should be max_level=255
or n_levels=256 or bitdepth=8. I think to go with bitdepth= with
8,16 as the only options. Anyone know if 32bit or other bits
satellite/imagery data exist?

set colors with:

r.colors band.red color=rules
0 black
65535 white
end

etc.

note that i.his2rgb has not been modified; experimenting with
i.rgb2his first.

do you know of any free-for-download QB data for testing it
with?


Hamish




_______________________________________________
grass-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/grass-dev
Georg Kaspar-2

Re: i.rgb.his/i.his.rgb and 16bit images

Reply Threaded More More options
Print post
Permalink
Hamish wrote:
> Very sorry if this is a dumb question, but did you set n_levels= to
> 65535? (it defaults to 8bit)

actually i set it to 2048 but i guess i should have used 2047. the data
seems to be encoded using 11bits

> Does 'i.rgb2his --help' show the option? what does 'r.info -r' say about
> the 3 r,g,b bands?

yes, the option is shown.

r.info -r on initial datasets
min=0
max=2047

> really that option name is misleading, it should be max_level=255 or
> n_levels=256 or bitdepth=8. I think to go with bitdepth= with 8,16 as
> the only options. Anyone know if 32bit or other bits satellite/imagery
> data exist?

yes, quickbird seems to use 11bit ;)
but i guess grass will use 16bit to store the data anyway...

> set colors with:
>
> r.colors band.red color=rules
> 0 black
> 65535 white
> end
>
> etc.
>
> note that i.his2rgb has not been modified; experimenting with i.rgb2his
> first.
>
> do you know of any free-for-download QB data for testing it with?

http://glcf.umiacs.umd.edu/data/quickbird/

bests,
Georg


_______________________________________________
grass-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/grass-dev
hamish-2

Re: Re: i.rgb.his/i.his.rgb and 16bit images

Reply Threaded More More options
Print post
Permalink
Georg Kaspar wrote:
> > do you know of any free-for-download QuickBird data for testing it
> > with?
>
> http://glcf.umiacs.umd.edu/data/quickbird/

I have tried to load some of that and found a few things.
Now documented in the GRASS wiki:
  http://grass.osgeo.org/wiki/QuickBird

With that I can get a RGB image that looks mostly-pseudo-true-color.


* red and blue bands are imported backwards and must be renamed.

This post claims it is a data provider problem, but I quietly suspect
that it may be a GDAL problem after all. (?)
   http://osdir.com/ml/gis.gdal.devel/2004-03/msg00025.html


* data is excessively dark and green band is higher gain than rest.

You can use i.landsat.rgb to rebalance the RGB, but gains/saturation is
still a bit off. I'm not sure if you are supposed to use the Panchromatic
channel to set the brightness, or... ? ISTR that some commercial provider
intentionally degraded Freebie offerings, not sure if that is the case
here or there is some calibration issue that we are not aware of.

Was your desire to use i.rgb2his in order to fix the brightness issue, or
was it for some analysis purpose?


Hamish




_______________________________________________
grass-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/grass-dev
Georg Kaspar-2

Re: Re: i.rgb.his/i.his.rgb and 16bit images

Reply Threaded More More options
Print post
Permalink
Hamish wrote:
> Was your desire to use i.rgb2his in order to fix the brightness issue, or
> was it for some analysis purpose?

Actually the purpose was pansharpening. This could also be done with
principal components, but grass lacks an inverse-pca module as far as i
know...
_______________________________________________
grass-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/grass-dev
hamish-2

Re: Re: i.rgb.his/i.his.rgb and 16bit images

Reply Threaded More More options
Print post
Permalink
Georg wrote:
> Actually the purpose was pansharpening.

i.fusion.brovey -q

http://grass.osgeo.org/grass64/manuals/html64_user/i.fusion.brovey.html

example added on wiki page


> This could also be done with principal components, but grass
> lacks an inverse-pca module as far as i know...

maybe Nikos could comment.

Note that with the R-grass bridge you can use any of the many R
statistical methods + functions.


regards,
Hamish


ps- patch added in the trac system to allow i.rbg2his to work
with 11-bit data (I fixed the truncation to 255 you saw before),
but d.his and i.his2rgb are still 8-bit only for now. Waiting
on word that I'm on the right track before moving onto the other
modules.




_______________________________________________
grass-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/grass-dev
Georg Kaspar-2

Re: Re: i.rgb.his/i.his.rgb and 16bit images

Reply Threaded More More options
Print post
Permalink
Hamish wrote:
> Georg wrote:
>> Actually the purpose was pansharpening.
>
> i.fusion.brovey -q

yes, i know this module, but i wanted to compare different approaches ;)

>> This could also be done with principal components, but grass
>> lacks an inverse-pca module as far as i know...
>
> maybe Nikos could comment.
>
> Note that with the R-grass bridge you can use any of the many R
> statistical methods + functions.

R is great as long as your datasets are small. problems arise when you
try to process l a r g e image files in R...

> ps- patch added in the trac system to allow i.rbg2his to work
> with 11-bit data (I fixed the truncation to 255 you saw before),
> but d.his and i.his2rgb are still 8-bit only for now. Waiting
> on word that I'm on the right track before moving onto the other
> modules.

thanks for that. i'm shure this is a nice improvement and one reason
less to use erdas...;)
_______________________________________________
grass-dev mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/grass-dev