Ask Your Question
0

Math on every pixel to Calculate NDVI?

asked Apr 4 '16

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?

Preview: (hide)

Comments

what have you tried so far?

strann gravatar imagestrann (Apr 5 '16)edit
1

It looks like this thread

LBerger gravatar imageLBerger (Apr 5 '16)edit

3 answers

Sort by » oldest newest most voted
1

answered Apr 5 '16

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;
   newChannels.push_back(newHue);
   newChannels.push_back(newSaturation);
   newChannels.push_back(newLigthness);
   Mat newHSL;
   cv::merge(newChannels, newHSL);
Preview: (hide)
1

answered Apr 5 '16

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) {
        dst.at<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..

Preview: (hide)
0

answered Apr 5 '16

kbarni gravatar image

updated Apr 5 '16

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: http://docs.opencv.org/3.1.0/d3/d50/g...

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.

Preview: (hide)

Question Tools

1 follower

Stats

Asked: Apr 4 '16

Seen: 3,149 times

Last updated: Apr 05 '16