Show your support for community science. Donate to Public Lab »

Question:How to verify generated NDVI Images?

ccpandhare asked on July 08, 2017 12:50

I am a Google Summer of Code Student working with Public Lab. I am working on the Image Sequencer Project.

In one JavaScript Module, I was required to generate the NDVI version of a given image. How do I know if the generated image is correct? I am surprised because my result varies from what I get on Infragram.

I replace every pixel of the image using this algorithm:

input pixel => (r,g,b,a)
ndvi = (b - r) / (b + r)
x = 255 * (1 + ndvi) / 2
output pixel => (x,x,x,a)


Is this correct?

cfastie 6 months ago

The algorithm looks good. I guess the next question is does Infragram use the exact same algorithm? (only coders know for sure)

The test image you are using has very similar histograms for blue and red which might be more likely to produce artifacts. You might want to use an RGN photo instead so most blue values are higher than red values. There is a good one here: https://publiclab.org/notes/Claytonb/08-13-2016/plant-health-ndvi-white-balance

Too bad I can't drag a photo into this comment.

ccpandhare 6 months ago

Wow Thanks a lot! This is the output I got: https://preview.ibb.co/dLEw5F/vegetation_01_ndvired.jpg Hope this is what it should look like. It even matched the output of Infragram.

warren 6 months ago

Part of the exciting part of this test suite (that we posted a request for here: https://publiclab.org/questions/warren/06-21-2017/test-images-for-multispectral-image-processing) is that we shouldn't have to trust coders to know for sure -- we can ensure these things empirically.

@ananyo2012 - I think Chris would like to be able to drag images into comments -- the function already exists in https://github.com/publiclab/plots2/blob/master/app/views/comments/_form.html.erb -- do you think you two could open an issue on github to use that form in the Question comments area?

It'd replace this section here: https://github.com/publiclab/plots2/blob/master/app/views/questions/_comment.html.erb#L22

https://github.com/publiclab/plots2/issues/new

ccpandhare 6 months ago

Hi @cfastie,

For the algorithm Which I have put up above, I get a pretty faint image

http://preview.ibb.co/eFnfza/vegetation_01_ndvired_new.jpg

But for for the following algorithm, I get a contrastful image, Like in Infragram:

https://preview.ibb.co/dLEw5F/vegetation_01_ndvired.jpg

Algorithm:

  input pixel => (r,g,b,a)

ndvi = 255 * (b - r) / (1.00 * b + r)

output pixel => (ndvi, ndvi, ndvi, a)


warren 6 months ago

My hunch is that since we can't display negative values for pixels, all negative values in the "high-contrast" image are being zeroed out, but in the "low-contrast" version the NDVI value of zero is being displayed as 50% brightness. But that's just a theory!

warren 6 months ago

Also note connection to this question: https://publiclab.org/questions/warren/06-21-2017/test-images-for-multispectral-image-processing

ccpandhare 6 months ago

Yes @warren, Thanks for the link. I have noted that. But we had a problem with these algorithms not working fairly with the other image... What can we do about that? I mean the consistency. Or maybe the output is correct. But then what about Infragram's output?

ananyo2012 6 months ago

cfastie 6 months ago

These two sets of equations do not do the same thing.

Set 1. var ndvi = 255 * (b - r) / (1.00 * b + r);

Set 2. var ndvi = (b - r) / (b + r); var x = 255 * (ndvi+1) / 2;

For example Set 1 can produce negative values. I assume you want all values between 0 and 255 and not between -255 and +255 as Set 1 seems to do. But the display of Set 1 seems to be correct, and the display of Set 2 seems to be wrong. I don't know anything about how these values get displayed.

However, the test photo I recommended is a weird one. It produces only positive NDVI values. They are all between 0 and 1 instead of between -1 and +1. So maybe try this photo instead:

ccpandhare 6 months ago

Hi Chris! I tested this image. Had the same results. I them made an improvement to the older algorithm

 var ndvi = 255 * (b - r) / (1.00 * b + r);


 var ndvi = 255 * (b - r) / (1.00 * b + r);
var x = (ndvi > 0) ? ndvi : 0;


Basically, it's just the old algorithm, and I map the negative values to 0;

This produced the same results as infragram. Maybe this is a unique case.

Is mapping all negative ndvi points to black correct? I really doubt that.

Can you please have a look at https://github.com/publiclab/image-sequencer/issues/34#issuecomment-315081822 ?