Creating an NDVI

A Normalized Difference Vegetation Index (NDVI) is one of the oldest remote sensing algorithms used to detect green vegetation in an area of interest, using the red and near-infrared bands of an image. The chlorophyll in plants absorbs visible light, including the red band, while the cell structures of plants reflect near-infrared light. The NDVI formula provides a ratio of near-infrared light to the total incoming radiation, which serves as an indicator of vegetation density. This recipe will use Python to control the QGIS raster calculator in order to create an NDVI using a multispectral image of a farm field.

Getting ready

Download the image from https://geospatialpython.googlecode.com/svn/farm-field.tif and place it in your qgis_data to a directory named rasters.

How to do it...

We will load the raster as a QGIS raster layer, perform the NDVI algorithm, and finally apply a color ramp to the raster so that we can easily visualize the green vegetation in the image. To do this, we need to perform the following steps:

  1. In the QGIS Python Console, import the following libraries:
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *
    from qgis.analysis import *
    
  2. Now, load the raster image as a layer using the following code:
    rasterName = "farm"
    raster = QgsRasterLayer("/Users/joellawhead/qgis_data/
    rasters/farm-field.tif", rasterName)
    
  3. Then, create entries in the QGIS raster calculator for the two bands using the following code:
    ir = QgsRasterCalculatorEntry()
    r = QgsRasterCalculatorEntry()
    
  4. Now, using the following lines of code, assign the raster layer as the raster component of each calculator entry:
    ir.raster = raster
    r.raster = raster
    
  5. Select the appropriate band for each entry, so the calculator will use the data we need for the NDVI. The red and infrared band numbers are typically listed in the raster's metadata:
    ir.bandNumber = 2
    r.bandNumber = 1
    
  6. Next, assign a reference ID to each entry using the special QGIS naming convention, as shown here, with the name of the layer as a prefix followed by an @ symbol and the band number as a suffix:
    ir.ref = rasterName + "@2"
    r.ref = rasterName + "@1"
    
  7. Build the raster calculator expression with the following code:
    references = (ir.ref, r.ref, ir.ref, r.ref)
    exp = "1.0 * (%s - %s) / 1.0 + (%s + %s)" % references
    
  8. Then, specify the output name of the NDVI image:
    output = "/Users/joellawhead/qgis_data/rasters/ndvi.tif"
    
  9. Set up the variables for the rest of the raster calculator call by defining the raster's extent, its width and height in columns and rows, and the raster entries we defined in the previous steps:
    e = raster.extent()
    w = raster.width()
    h = raster.height()
    entries = [ir,r]
    
  10. Now, create the NDVI using our expression:
    ndvi =  QgsRasterCalculator(exp, output, "GTiff", e, w, h, entries)
    ndvi.processCalculation()
    
  11. Next, load the NDVI output as a raster layer:
    lyr = QgsRasterLayer(output, "NDVI")
    
  12. We must perform a histogram stretch on the image, otherwise the differences in values will be difficult to see. A stretch is performed using a QGIS contrast enhancement algorithm:
    algorithm = QgsContrastEnhancement.StretchToMinimumMaximum
    limits = QgsRaster.ContrastEnhancementMinMax
    lyr.setContrastEnhancement(algorithm, limits)
    
  13. Next, build a color ramp shader to colorize the NDVI, as follows:
    s = QgsRasterShader()
    c = QgsColorRampShader()
    c.setColorRampType(QgsColorRampShader.INTERPOLATED)
    
  14. Then, add entries for each color in the image. Each entry consists of a lower value range, a color, and a label. The color in an entry will continue from the lower value until it encounters a higher value or the maximum value. Note that we will use a variable alias for the extremely long name of the QGIS ColorRampItem object:
    i = []
    qri = QgsColorRampShader.ColorRampItem
    i.append(qri(0, QColor(0,0,0,0), 'NODATA')) 
    i.append(qri(214, QColor(120,69,25,255), 'Lowest Biomass'))
    i.append(qri(236, QColor(255,178,74,255), 'Lower Biomass'))
    i.append(qri(258, QColor(255,237,166,255), 'Low Biomass'))
    i.append(qri(280, QColor(173,232,94,255), 'Moderate Biomass'))
    i.append(qri(303, QColor(135,181,64,255), 'High Biomass'))
    i.append(qri(325, QColor(3,156,0,255), 'Higher Biomass'))
    i.append(qri(400, QColor(1,100,0,255), 'Highest Biomass'))
    
  15. Now, we can add the entries to the shader and apply it to the image:
    c.setColorRampItemList(i)
    s.setRasterShaderFunction(c)
    ps = QgsSingleBandPseudoColorRenderer(lyr.dataProvider(), 1, s)
    lyr.setRenderer(ps)
    
  16. Finally, add the classified NDVI image to the map in order to visualize it:
    QgsMapLayerRegistry.instance().addMapLayer(lyr)
    

How it works...

The QGIS raster calculator is exactly what its name implies. It allows you to perform array math on images. Both the QGIS raster menu and the Processing Toolbox have several raster processing tools, but the raster calculator can perform custom analysis that can be defined in a single mathematical equation. The NDVI algorithm is the infrared band minus the red band divided by the infrared band plus the red band, or (IR-R)/(IR+R). In our calculator expression, we multiply each side of the equation by 1.0 to avoid division-by-zero errors. Your output should look similar to the following image if you load the result into QGIS. In this screenshot, NODATA values are represented as black; however, your QGIS installation may default to using white:

How it works...
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset