Ask Your Question

Math on every pixel to Calculate NDVI?

asked 2016-04-04 14:54:58 -0500

barronlroth gravatar image

I'm very new to OpenCV and attempting to do something which seems simple, but execution for an amateur is difficult.

I have to iterate through every pixel in an image, perform some math on the current pixel's RGB values (Red-Blue/Red+Blue), and output an image (in HSL) with a hue:

newHue = (ndvi-.5)*(-360)

and a saturation & brightness of 1 (constant across the output image).

Any tips on getting started with something like this?

edit retag flag offensive close merge delete


what have you tried so far?

strann gravatar imagestrann ( 2016-04-05 02:16:28 -0500 )edit

It looks like this thread

LBerger gravatar imageLBerger ( 2016-04-05 02:34:13 -0500 )edit

3 answers

Sort by ยป oldest newest most voted

answered 2016-04-05 03:22:31 -0500

strann gravatar image

You can perform band math using element-wise operations like this

    vector<Mat> channels;
    split(imageBGR, channels);
    Mat numeratorMat = channels[2] - channels[0]; // red - blue
    Mat denominatorMat = channels[2] + channels[0]; // red + blue
    Mat ratio;
    cv::divide(denominatorMat, numeratorMat, ratio, 1., 5); // here 5 specifies type of ratio (CV_32FC1)

Then you can do something like

   Mat newHue = (ratio.clone() - 0.5 ) * (-360); // float 32
   Mat newLigthness = Mat::ones(imageBGR.rows, imageBGR.cols, CV_32FC1);
   Mat newSaturation = Mat::ones(imageBGR.rows, imageBGR.cols, CV_32FC1);

   vector<Mat> newChannels;
   Mat newHSL;
   cv::merge(newChannels, newHSL);
edit flag offensive delete link more

answered 2016-04-05 02:56:15 -0500

If you want to convert your image in HSL, the proper way to do it in OpenCV is:

cv::cvtColor( src, dst, cv::COLOR_BGR2HLS );

If your intent is to do it manually, then you can iterate through the pixel that way:

for(int r = 0 ; r < src.rows ; ++r) {
    for(int c = 0 ; c < src.cols ; ++c) {<cv::Vec3b>(r,c) = cv::Vec3b(newHue, /*newLigthness*/1, /*newSaturation*/1);

This is the most standard (and slow way) to iterate through pixels, but also the most obvious. If you want to have a look at how to speed-up the pixel iteration, I suggest you have a look at this tutorial or even, this tutorial for a very basic (but yet helpful) introduction to OpenCV images..

edit flag offensive delete link more

answered 2016-04-05 04:44:00 -0500

kbarni gravatar image

updated 2016-04-05 04:48:03 -0500

There are several problems in your approach that the other answers didn't adress:

  • in OpenCV HSV space the Hue angle is between 0-180! (not 360)
  • to get the HSV color map, the saturation/lightness should be 255, not 1!
  • they all forgot to convert back the hsv image to RGB: cvtColor(hsvimage,color,COLOR_HSV2BGR);
  • probably it's easier to use color mapping than HSV conversion.

So the second part of strann's answer using color mapping would be:

// Normalize NDVI between 0 and 255 and convert to byte type (CV_8UC1)
normalize(ratio, ratio, 0, 255, NORM_MINMAX, CV_8UC1);
//or: normalize(ratio, ratio, 127,127,NORM_L2,CV_8UC1);
// Apply a color map 
applyColorMap(ratio, cm_img0, COLORMAP_HSV);
// Show the result:
imshow("NDVI color map", cm_img0);

Some more information about color maps:

BTW, it seems that you try to use Public lab's method of calculating NDVI using a camera without IR filter. According to my experiences it's results aren't very accurate, but it's a good start for experimenting.

edit flag offensive delete link more

Question Tools

1 follower


Asked: 2016-04-04 14:54:58 -0500

Seen: 2,364 times

Last updated: Apr 05 '16