0
votes

I have four separate images - 2-projected.tif, 3-projected.tif, 4-projected.tif and 5-projected.tif. These are four Landsat images. Image 2-projected.tif corresponds to blue channel, image 3-projected.tif - to green channel, image 4-projected.tif - to red channel, and 5-projected.tif - to infrared. Now I want to create NDVI image. To do this, I first create a combined RGB image, using ImageMagic:

$ convert 4-projected.tif 3-projected.tif 2-projected.tif -combine RGB.tif

So far, so good. And then I try to follow a command from this tutorial, which is supposed to create NDVI image. I do it like so:

$ convert 5-projected.tif RGB.tif -channel RGB -fx '(u.r-v.r)/(u.r+v.r+0.001)' -normalize NDVI.tif

But as a result, I get these error messages:

convert: unable to parse expression (u.r-1.0*v.r)' @ error/fx.c/FxGetSymbol/183 1. convert: divide by zero'(u.r-1.0*v.r)/(u.r+v.r+0.001)'' @ error/fx.c/FxEvaluat eSubexpression/2159.

I'm not sure how can I fix it.

1
BTW, NDVI formula in theory looks like (NIR-VIS)/(NIR+VIS) (according to wikipedia) and I've seen some other ImageMagic commands to create NDVI. For example, in this article - blog.sogeo.services/blog/2014/09/22/ndvi-orthofotos.html - they calculate it like -fx '(u.r - u.g) / (u.r + u.g + 0.001)'Jacobian

1 Answers

2
votes

The two bands of interest are the red and the NIR and the formula for NDVI is:

NDVI = (NIR-red)/(NIR+red)

You have two options. First off, if you have the red and the NIR in two separate, single channel images, you can do:

convert red.tif NIR.tif -fx '(u.r-v.r)/(u.r+v.r+0.001)' -normalize -compress lzw NDVI.tif

Here, I am using u.r to refer to the first channel of the first image and v.r to refer to the first channel of the second image.

enter image description here


Alternatively, if the red and NIR are the first two channels in an RGB image (i.e. ImageMagick would call them the red and green channels):

convert RGB.tif -fx '(u.r-u.g)/(u.r+u.g+0.001)' -normalize -compress lzw NDVI.tif

Here I am using u.r to refer to the first channel of the first image and u.g to refer to the second channel of the first image.


The -fx method is extremely powerful, but notoriously slow. This method below should give you the same answer, but I have not checked it too thoroughly:

convert 4-projected.tif -write MPC:red +delete           \
        5-projected.tif -write MPC:NIR +delete           \
       \( mpc:red mpc:NIR -evaluate-sequence subtract \) \
       \( mpc:red mpc:NIR -evaluate-sequence add      \) \
       -evaluate-sequence divide -normalize -compress lzw NDVI.tif

If you want to colourise the image with false colour, you could generate a Colour Lookup Table (CLUT) and map the grayscale values in the NDVI image to those colours. So, let's say you wanted to map the darkest blacks in your NDVI image to black, the quite dark values to red, the quite bright values to orange and the very brightest values to green, you could make a CLUT like this:

convert xc:black xc:red xc:orange xc:lime +append clut.png

enter image description here

and apply it the greyscale result from above like this:

convert NDVI.tif -normalize clut.png -clut falsecolour.jpg

enter image description here

If you want to make the orange and green tones longer (more prevalent), you can alter their lengths to make them longer in the CLUT:

convert -size 30x1 xc:black -size 40x1 xc:red -size 80x1 xc:orange -size 100x1 xc:lime +append clut.png

enter image description here

Then re-apply the CLUT:

convert NDVI.tif -normalize clut.png -clut result.jpg

enter image description here