home products news downloads documentation support gallery online maps resellers search
TNTmips Downloads Menu

HOME

CONTACT US

CURRENT RELEASE
  TNT 2013

DEVELOPMENT VERSION
  TNT 2014

TNTmips Pro
PRIOR RELEASES
  TNT 2012

FREE SOFTWARE
  TNTmips Free
  TNTatlas
  TNTsdk

MORE DOWNLOADS
  HASP Key Driver
  Screen Recorder
  TNT Language Kits
  Sample Geodata
  TNT Scripts

DOCUMENTATION
  TNTmips Tutorials
  Tutorial Datasets
  Technical Guides
  Scripts
  Quick Guides

MORE INFO
  Download FAQs
  FTP
  Download Managers
  Find Reseller

SITE MAP


PipelineNDVIfromTIFF.sml


# PipelineNDVIfromTIFF.sml

# Sample standalone script to demonstrate an image pipeline application.

# Computes a Normalized Difference Vegetation Index (NDVI) raster from Red and
# Near-infrared bands directly from an input GeoTIFF file containing a 4-band multispectral
# QuickBird or Ikonos satellite image.  The GeoTIFF file does not need to have been previously linked
# or imported to TNTmips.  

# NDVI is calculated for each image cell using the formula:
# 				1000 * (Near Infrared - Red) / (Near Infrared + Red)
# Values in the resulting NDVI raster can range from -1000 to + 1000 (using Signed 16-bit raster type).

# If the input image is projected, there may be 0-value cells around the edges.  A ValidityNear filter
# is used to identify cells that have zero value in both bands; the filter creates a null mask
# for each band with such cells marked as null.

# Path radiance (atmospheric scattering / haze) is an additive effect that varies between
# bands, and so should be removed before calculating NDVI.  This script uses the minimum (non-null)
# raster value in each band as an approximation to the Path Radiance value for that band. This value
# is subtracted using the SCALEOFFSET filter (scale = 1.00, offset value negative).

# The LINEAR filter (linear combination of band values) is used to perform the addition and
# subtraction of the band values.

# The NDVI image is produced as a single 16-bit signed integer RVC raster in a Project File.     

# 8 January 2008
# Randy Smith, MicroImages, Inc.

# Requires Version 2008:74 or later of the TNT products.

numeric err;

# error checking procedure
proc ReportError(numeric linenum, numeric err) {
	printf("FAILED -line: %d, error: %d\n", linenum - 1, err);
	PopupError(err); 
	}


################################################################################
#################################  Main program  ###############################
clear();

# set context so script does not exit on error, allowing manual
# handling of errors.
_context.AbortOnError = 0;


# CHOOSE GEOTIFF FILE containing QuickBird or IKONOS 4-band multispectral image
class FILEPATH inFilePath(GetInputFileName("","Choose GeoTIFF file with source image:", ".tif"));

# CHOOSE OUTPUT RASTER
# DlgGetObject creates only an ObjItem for the output; the new raster will then be created
# by the TARGET_RVC with the desired compression.  The ObjectPath of the ObjItem is not
# valid until the output raster is actually created by the pipeline.
class RVC_OBJITEM ndviOutObjItem;
DlgGetObject("Choose new raster for NDVI result:", "Raster", ndviOutObjItem, "NewOnly");

# PIPELINE SOURCE
# set GeoTIFF file containing a four-band QuickBird or Ikonos image as source
class IMAGE_PIPELINE_SOURCE_TIFF source_tif( inFilePath );
err = source_tif.Initialize();
if (err < 0 )
	ReportError(_context.CurrentLineNum, err);
else {
	print("Source TIFF file initialized");
	}

if (source_tif.GetNumSamples() == 4) 
	printf("Number of bands in TIFF file = %d\n", source_tif.GetNumSamples() );
else {
	print("Selected TIFF file does not contain 4 bands; exiting now.");
	Exit(); 
	}

# Get georeference from the GeoTIFF file to print what CRS is used.
class IMAGE_PIPELINE_GEOREFERENCE georef;
georef = source_tif.GetGeoreference();

class SR_COORDREFSYS crs = georef.GetCRS();
printf("Coordinate reference system = %s\n", crs.Name );


# PIPELINE FILTER_SELECT to select red and near-infrared bands for processing (don't need to carry the rest
# forward through the pipeline).
# The source TIFF file consists of 4 bands (samples) per pixel, which have numeric indices 0 = blue,
# 1 = green, 2 = red, 3 = near-infrared.  These samples are selected by index number in this filter.
numeric numSamples = 2;		# number of bands from 4-band TIFF file to be used
array numeric srcSamples[2];	# array to contain the numeric indices of the bands to select
srcSamples[1] = 2;		# index for red band
srcSamples[2] = 3;		# index for near-infrared band

class IMAGE_PIPELINE_FILTER_SELECT filter_select(source_tif, srcSamples, numSamples);
err = filter_select.Initialize();
if (err < 0 )
	ReportError(_context.CurrentLineNum, err);
else {
	print("Initialized band selection filter");
	}

# the result of this FILTER_SELECT is an "image" with two samples per pixel, with the red value as index 0
# and the near-infrared value as index 1.

class STRING pixelType = filter_select.GetPixelType();
printf("Pixel type in image = %s\n", pixelType);

class STRING datatypeRed$, datatypeNIR$;
class IMAGE_PIPELINE_PIXEL pixel;
pixel = filter_select.GetPixelValueMax();
datatypeRed$ = pixel.GetSample(0).GetDataType();
datatypeNIR$ = pixel.GetSample(1).GetDataType();
printf("Datatype of red band = %s\n", datatypeRed$ );
printf("Datatype of near-infrared band = %s\n", datatypeNIR$ );



# PIPELINE FILTER_VALIDITYNEAR
# Filter to set null for cells based on nearness (distance) to a specified value
# In this case test for zero value in both bands (assumed to be non-image cells) and set
# such cells to null (0 value in null mask created by the filter)

# validity flag 
numeric resultValid = 0;  # set 1 if pixels near test value should be valid, 0 if invalid;
									# we want 0 values to be invalid, so set this parameter to false (0)
numeric distance = 0.5;		# distance to test must be greater than 0; use a decimal value less
									# than 1 to test for exact match to an integer value
class IMAGE_PIPELINE_FILTER_VALIDITYNEAR validity(filter_select, "Orthogonal", resultValid); 

# define two 0-value samples to provide the set of values 
class IMAGE_PIPELINE_SAMPLE redNullSamp("Gray", "UINT16", 0);
class IMAGE_PIPELINE_SAMPLE nirNullSamp("Gray", "UINT16", 0);
# define a text pixel with the two 0-value samples to pass to the validity filter
class IMAGE_PIPELINE_PIXEL testPixel(redNullSamp, nirNullSamp);
# add the pixel value to test and the test distance to the validity filter;
validity.AddValue(testPixel, distance);  

array numeric samplesToTest[2];	# array to set which image samples to test (in this case, both)
samplesToTest[1] = 0;	# sample index for red
samplesToTest[2] = 1;	# sample index for near-infrared
validity.SetSamplesTest(samplesToTest, 2);

err = validity.Initialize();
if (err < 0 )
	ReportError(_context.CurrentLineNum, err);
else {
	print("Initialized ValidityNear filter.");
	}


# GET MINIMUM AND MAXIMUM VALUES of the red and near-infrared bands.
# First call method on stage to compute the range of values in the bands; using the "Exact"
# value for the RangeType parameter in this method to compute the actual range of values using the 
# rasters without sampling (i.e. computing using the pyramids, if any).  The "Default" value returns
# the range of the raster datatype.
validity.ComputePixelRange("Exact"); 
class IMAGE_PIPELINE_PIXEL minVals, maxVals;		# container to hold the minimum and maximum value for each band
minVals = validity.GetPixelValueMin();
maxVals = validity.GetPixelValueMax(); 

printf("Minimum value of red band = %d\n", minVals.GetSample(0).GetValue() );
printf("Maximum value of red band = %d\n", maxVals.GetSample(0).GetValue() );

printf("Minimum value of near-infrared band = %d\n", minVals.GetSample(1).GetValue() );
printf("Maximum value of near-infrared band = %d\n", maxVals.GetSample(1).GetValue() );



# PIPELINE FILTER_SCALEOFFSET applies scale (multiply by constant) and offset (add constant value) to each cell
# Use with scale = 1 and negative offset to subtract the minimum valid value from each of the bands
# as an approximate correction for path-radiance.
class IMAGE_PIPELINE_FILTER_SCALEOFFSET offsetMin(validity);

# set scale = 1 and negative offset equal to minimum value for red band (0) and near-infrared band (1)
offsetMin.SetScaleOffset(0, 1, minVals.GetSample(0).GetValue() * -1);
offsetMin.SetScaleOffset(1, 1, minVals.GetSample(1).GetValue() * -1);
err = offsetMin.Initialize();
if (err < 0 )
	ReportError(_context.CurrentLineNum, err);
else {
	print("Initialized Scale-offset filter for path-radiance correction.");
	}
 

# PIPELINE FILTER_LINEAR produces a linear combination of the band values using a coefficient for each band
# Cell Value = a * Band1value  +  b * Band2value + ...
# Use here to subtract band values to provide dividend for the NDVI expression: NIR - Red; 
# Set number of samples in target to 1; coefficient for NIR = 1 and for Red = -1
numeric numTargetSamples = 1;
numeric targetSampleNum = 0;	# 0th target sample
numeric sourceSampleNum = 0;	# 0th source sample (red)
numeric coefValue;		# value of the coefficient

class IMAGE_PIPELINE_FILTER_LINEAR linearSubtract(offsetMin, numTargetSamples);
coefValue = -1;	# set coefficient value = -1 for red 
linearSubtract.SetCoefficient(targetSampleNum, sourceSampleNum, coefValue); 
sourceSampleNum = 1;	# 1st (near-infrared) source sample
coefValue = 1;		# set coefficient value = 1 for near-infrared
linearSubtract.SetCoefficient(targetSampleNum, sourceSampleNum, coefValue);
err = linearSubtract.Initialize();
if (err < 0 )
	ReportError(_context.CurrentLineNum, err);
else {
	print("Initialized linear filter for subtracting red from near-infrared.");
	}	 


# PIPELINE FILTER_LINEAR
# Use here to add band values to provide divisor for the NDVI expression: NIR + Red;
# Set number of samples in target to 1; coefficient for both NIR and Red = 1;
class IMAGE_PIPELINE_FILTER_LINEAR linearAdd(offsetMin, numTargetSamples);
sourceSampleNum = 0;	# 0th source sample (red)
linearAdd.SetCoefficient(targetSampleNum, sourceSampleNum, coefValue);
sourceSampleNum = 1;	# 1st source sample (near-infrared)
linearAdd.SetCoefficient(targetSampleNum, sourceSampleNum, coefValue);
err = linearAdd.Initialize();
if (err < 0 )
	ReportError(_context.CurrentLineNum, err);
else {
	print("Initialized linear filter for adding red and near-infrared.");
	}


# PIPELINE FILTER_DIVIDE: filter to divide two images
# Use to perform the final NDVI division using the results from the two Linear filters
# The stage takes two source stages, the dividend stage followed by the divisor stage,
# Output of this filter is a single 64-bit floating-point image with possible range -1.00 to + 1.00
class IMAGE_PIPELINE_FILTER_DIVIDE divide(linearSubtract, linearAdd);
err = divide.Initialize();
if (err < 0 )
	ReportError(_context.CurrentLineNum, err);
else {
	print("Initialized divide filter to compute NDVI.");
	}


# PIPELINE FILTER_SCALEOFFSET
# Scale floating-point values to range -1000 to + 1000 using scale factor = 1000 and offset = 0
class IMAGE_PIPELINE_FILTER_SCALEOFFSET scale1000(divide);
scale1000.SetScaleOffset(0, 1000, 0);
err = scale1000.Initialize();
if (err < 0 )
	ReportError(_context.CurrentLineNum, err);
else {
	print("Initialized scale-offset filter to rescale NDVI.");
	}



# PIPELINE FILTER_DATATYPE: filter to change datatype
# Change rescaled NDVI from 64-bit floating point to 16-bit signed integer
class IMAGE_PIPELINE_FILTER_DATATYPE changeToSINT16(scale1000, "SINT16", "Invalidate");
err = changeToSINT16.Initialize();
if (err < 0 )
	ReportError(_context.CurrentLineNum, err);
else {
	print("Initialized datatype filter to convert to signed 16-bit.");
	}


# PIPELINE TARGET
class IMAGE_PIPELINE_TARGET_RVC target_rvc(changeToSINT16, ndviOutObjItem);
target_rvc.Initialize();
if (err < 0 )
	ReportError(_context.CurrentLineNum, err);
else {
	print("Initialized NDVI target.");
	}


# EXECUTE the pipeline process
print("Processing...");
target_rvc.Process();

print("Done.");









 







Back Home ©MicroImages, Inc. 2013 Published in the United States of America
11th Floor - Sharp Tower, 206 South 13th Street, Lincoln NE 68508-2010   USA
Business & Sales: (402)477-9554  Support: (402)477-9562  Fax: (402)477-9559
Business info@microimages.com  Support support@microimages.com  Web webmaster@microimages.com

25 March 2009

page update: 26 May 11