X
PrevPrev Go to previous topic
NextNext Go to next topic
Last Post 19 Nov 2018 02:20 PM by  MariM
Color Slice Classification ENVItask
 10 Replies
Sort:
You are not authorized to post a reply.
Author Messages

Dulci Avouris



New Member


Posts:51
New Member


--
15 Nov 2018 09:25 AM
    Hello!

    I am trying to apply a color table to a geo-referenced single band image so I can export it as a GeoTIFF with the original pixel values intact using an ENVI task or ENVI API.

    So far, I have been able to stretch the image (in IDL using ENVITask 'linearpercentstretchraster') with a 2% linear stretch, but the data ignore value (-9999) is changed to 241. When I display the stretched raster in ENVI, even though the metadata says -9999 is the data ignore value, ENVI still ignores the pixels with a 241 value. OK so far - but when I use ENVITask 'colorsliceclassification' the pixels with a value of 241 (which are the original background pixels of -9999) are displayed as red (the top end of the rainbow color table).

    When I do this process in ENVI GUI, I load the raster, display with a 2% linear stretch, then change the color table and then chip the view to a tiff file. It works beautifully, but is not efficient for hundreds of images.

    Is there another processing stream that I am missing?

    Thanks so much!

    -dulci

    MariM



    Veteran Member


    Posts:2396
    Veteran Member


    --
    16 Nov 2018 08:31 AM
    I ran the example from the ENVI documentation for ENVILinearPercentStretchRaster and the sample data, qb_boulder_msi, which I rotated so there was background values. I set these background values to NoData using Edit Metadata. The result from ENVILinearPercentStretchRaster retained the NoData set in the image header. When I passed a band from this file to the ColorSliceClassification task, the resulting sliced data also retained the NoData value.

    Does your original image have the Data value to ignore set in the header? You can add a DIV using View Metadata->Edit Metadata and the 'add' button.

    Dulci Avouris



    New Member


    Posts:51
    New Member


    --
    16 Nov 2018 10:03 AM
    My original data does have an ignore data value in the header. That value (-9999) was passed from the original data, to the raster resulting from the ENVILinearPercentStretch. However, in the byte scaled, stretched raster, while the data ignore value was set to -9999, the actual value in the pixels that used to be -9999 was 241. So there was a discrepancy - the header file DIV = -9999; Pixel value = 241. I displayed this stretched raster in ENVI & while the pixels = 241, ENVI still read those pixels as No Data. That didn't make sense to me at all, because the -9999 DIV is MUCH more negative than my pixel values, and why does ENVI still recognize a pixel value of 241 as No Data when the DIV = -9999?

    When I applied the ColorSliceClassification, to the byte scaled stretched raster, the DIV in the metadata changed to be 0. And the pixels with a value of 241 remained 241. I then updated the metadata file so that the DIV = 241. I then displayed the re-colored raster in ENVI, and the pixels that should be No Data were red (the color of the slice with 241 in the values).

    I have tried a number of combinations for this process, as well as starting over, and wiping the cache for my computer, etc.

    I guess I have two questions:
    1) how do I get the DIV to actually ignore the background pixels, and color those black when applying the rainbow color table.
    2) can I do a stretch & change the color table and NOT byte scale the values in my raster?

    Thank you for the help!

    MariM



    Veteran Member


    Posts:2396
    Veteran Member


    --
    16 Nov 2018 12:09 PM
    ENVILinearPercentStretchRaster doesn't change the data values or create a new file. So it doesn't make sense that the DIV pixels changed value after stretching the data. The DIV should be set to whatever the actual background pixel values are in the raster that you are stretching. If it is 241,,then you should set the DIV to 241 in the header..
    My steps with a file that has background values of 0 set to the DIV:
    ENVI> file='C:\TEMP\qb_boulder_rotate.dat'
    ENVI> raster=e.openraster(file)
    ENVI> stretchRaster = ENVILinearPercentStretchRaster(raster, percent=2.0)
    ENVI> view = e.GetView()
    ENVI> layer = view.CreateLayer(stretchRaster)

    ENVI> Subset = ENVISubsetRaster(stretchRaster, bands=0)
    ENVI> Task = ENVITask('ColorSliceClassification')
    ENVI> task.input_raster=subset
    ENVI> Task.OUTPUT_RASTER_URI = e.GetTemporaryFilename()
    ENVI> task.execute
    ENVI> datacoll=e.data
    ENVI> datacoll.add, task.output_raster

    This produces a color sliced raster with the background still set to the DIV.


    Dulci Avouris



    New Member


    Posts:51
    New Member


    --
    16 Nov 2018 12:35 PM
    This is what I did:

    ENVI> vpca = e.openraster(file)
    ENVI> vpcastretch = envilinearpercentstretchraster(vpca, percent = 2.0)
    ENVI> view = e.getview()
    ENVI> layer = view.createlayer(vpcastretch)
    ENVI> vpca1 = envisubsetraster(vpcastretch, bands = 0)
    ENVI> task = envitask('colorsliceclassification')
    ENVI> task.input_raster = vpca1
    ENVI> task.output_raster_uri = e.gettemporaryfilename()
    ENVI> task.execute
    ENVI> vpca1stretchcolor = task.output_raster
    ENVI> layer = view.createlayer(vpca1stretchcolor)

    The displayed layer of vpca had the no data in the correct pixels. The displayed layer of vpca1stretchcolor was purple in the no data pixels.

    Here is the metadata for my original data: it is an ENVI.dat file with a DIV of -9999

    print, vpca
    AUXILIARY_SPATIALREF = !NULL
    AUXILIARY_URI = <Array[2]>
    DATA_TYPE = 'double'
    INTERLEAVE = 'bsq'
    METADATA = <ObjHeapVar249845(ENVIRASTERMETADATA)>
    NBANDS = 4
    NCOLUMNS = 163
    NROWS = 256
    PYRAMID_EXISTS = 1
    READ_ONLY = 1
    SPATIALREF = <ObjHeapVar249716(ENVISTANDARDRASTERSPATIALREF)>
    TIME = <ObjHeapVar249848(ENVITIME)>
    URI = '/Users/dulci/Documents/Sentinel3/SouthFL/2018/08_2018/080218_S3A_L2/080218_S3A_L2_GLTreproject_BB_4VPCA.dat'

    ENVI> print, vpca.metadata
    ENVIRASTERMETADATA <249845>
    BAND NAMES = 'IDL Var (VPCASCORES): Band 1', 'IDL Var (VPCASCORES): Band 2', 'IDL Var (VPCASCORES): Band 3', 'IDL Var (VPCASCORES): Band 4'
    DATA IGNORE VALUE = -9999.0000

    Here is the same info for the stretched data:

    print, vpcastretch
    ENVILINEARPERCENTSTRETCHRASTER <249715>
    AUXILIARY_SPATIALREF = !NULL
    AUXILIARY_URI = !NULL
    DATA_TYPE = 'byte'
    INTERLEAVE = 'bsq'
    METADATA = <ObjHeapVar340003(ENVIRASTERMETADATA)>
    NBANDS = 4
    NCOLUMNS = 163
    NROWS = 256
    PYRAMID_EXISTS = 1
    READ_ONLY = 1
    SPATIALREF = <ObjHeapVar251250(ENVISTANDARDRASTERSPATIALREF)>
    TIME = <ObjHeapVar251292(ENVITIME)>
    URI = !NULL

    print, vpcastretch.metadata
    ENVIRASTERMETADATA <340003>
    BAND NAMES = 'IDL Var (VPCASCORES): Band 1', 'IDL Var (VPCASCORES): Band 2', 'IDL Var (VPCASCORES): Band 3', 'IDL Var (VPCASCORES): Band 4'
    DATA IGNORE VALUE = -9999.0000
    DESCRIPTION = 'ENVI Stretch Raster [Fri Nov 16 14:20:00 2018]'

    The pixel value for the background is =9999 in the stretched data. Part worked this time. But why are the values byte instead of float?

    Here is the data for the single band subset of stretched data after the color slice classification was applied:

    print, vpca1stretchcolor
    ENVIRASTER <338884>
    AUXILIARY_SPATIALREF = !NULL
    AUXILIARY_URI = <Array[2]>
    DATA_TYPE = 'byte'
    INTERLEAVE = 'bsq'
    METADATA = <ObjHeapVar340004(ENVIRASTERMETADATA)>
    NBANDS = 1
    NCOLUMNS = 163
    NROWS = 256
    PYRAMID_EXISTS = 1
    READ_ONLY = 1
    SPATIALREF = <ObjHeapVar340010(ENVISTANDARDRASTERSPATIALREF)>
    TIME = <ObjHeapVar340011(ENVITIME)>
    URI = '/var/folders/_l/zvx7r4617nj18z19d_bk6cjc0000gp/T/envitempfileFriNov161424222018897767918.dat'

    print, vpca1stretchcolor.metadata
    ENVIRASTERMETADATA <340004>
    BAND NAMES = 'IDL Var (VPCASCORES): Band 1: Spectral Subset_2018-11-16T19-21-37Z'
    CLASS LOOKUP = 0, 0, 0, 124, 0, 255, ...
    CLASS NAMES = 'Background', '0 to 15', '16 to 31', '32 to 47', '48 to 63', '64 to 79', ...
    CLASSES = 17
    DATA IGNORE VALUE = 0

    Now the data ignore value = 0, but the pixels in my image that had a value of -9999 now have a value of 1.

    Dulci Avouris



    New Member


    Posts:51
    New Member


    --
    16 Nov 2018 12:42 PM
    One more step - I changed the metadata for the vpca1stretchcolor raster DIV = 1. This worked this time! However, this also removes pixels with real values because the data has been binned to apply the color table.

    Thank you for the help!

    MariM



    Veteran Member


    Posts:2396
    Veteran Member


    --
    16 Nov 2018 01:31 PM
    When using the stretch in the interface or using envilinearpercentstretchraster, you are always stretching the values for the display. It doesn't create a new file and display values are always byte-scaled. This is why the stretched result is byte. It is also why you are seeing different values for the stretched result background value since -9999 doesn't exist in byte-scaled data.. In my example, 0 is the smallest value and also my background.
    You could save your stretched data out to a new image and set a new DIV for the background before input to the classification using subset.export and the data_ignore_value keyword set to your actual background value, assuming the stretched background value is unique in the data.

    Dulci Avouris



    New Member


    Posts:51
    New Member


    --
    19 Nov 2018 11:14 AM
    Hello!

    OK. So this all worked - finally. And I exported the image as a GeoTIFF. The only issue remaining is that I lose some of my pixels with data. I don't know if that is when the image is byte scaled in the stretch? There are pixels that should not be background pixels that are assigned the background pixel value. So when I change the color scale, those pixels erroneously disappear from my image.

    Any thoughts on avoiding this?
    Here is my code:

    file = dialog_pickfile(filter = '*.hdr')
    vpca = e.openraster(file)

    stretchRaster = ENVILinearPercentStretchRaster(vpca, percent=2.0)
    metadata = stretchraster.metadata
    metadata.updateitem, 'data ignore value', [0]
    bands = vpca.nbands

    b = bands-1

    for n = 0,b do begin
    Subset = ENVISubsetRaster(stretchRaster, bands=n)
    Task = ENVITask('ColorSliceClassification')
    task.input_raster=subset
    Task.OUTPUT_RASTER_URI = e.GetTemporaryFilename()
    task.execute

    vpcascore = task.output_raster

    Y = ''
    read, Y, prompt='ENTER FILENAME FOR VPCAscore TIFF - I.E. DATE_INSTRUMENT_#VPCA#: ' ;NAME THE TIFF VPCA SCORE FILE
    vpcascore.export, Y, 'tiff'

    MariM



    Veteran Member


    Posts:2396
    Veteran Member


    --
    19 Nov 2018 01:24 PM
    When you do a 2% stretch, you are assigning the lower 2% of pixels to the value of 0 and the upper 2% to 254 and then a linear stretch is performed for the 2-98% of pixels in the histogram. Perhaps the pixels that are lost are those that are in the lower and upper 2%?

    Dulci Avouris



    New Member


    Posts:51
    New Member


    --
    19 Nov 2018 01:36 PM
    I am comparing the resultant stretched image to the one that I produced using the ENVI GUI, so both images are linearly stretched at 2%. Unless those processes are different?

    MariM



    Veteran Member


    Posts:2396
    Veteran Member


    --
    19 Nov 2018 02:20 PM
    No, they should be perform the same process. You could save out the stretched data and compare it to the image you get in the GUI that you pass to the Raster Color Slices. That might help you track down how those pixels are lost.
    You are not authorized to post a reply.