在遥感中,常常会提到NDVI,它的全称是 Normalized Difference Vegetation Index,也就是归一化差分植被指数,是反映农作物长势和营养信息的重要参数之一,它的计算原理很简单,就是近红外波段的反射值与红光波段的反射值之差比上两者之和。
即 NDVI=(NIR-R)/(NIR+R),
NIR为近红外波段的反射值,R为红光波段的反射值。
1、NDVI的应用:检测植被生长状态、植被覆盖度和消除部分辐射误差等;
2、-1<=NDVI<=1,负值表示地面覆盖为云、水、雪等,对可见光高反射;0表示有岩石或裸土等,NIR和R近似相等;正值,表示有植被覆盖,且随覆盖度增大而增大;
3、NDVI的局限性表现在,用非线性拉伸的方式增强了NIR和R的反射率的对比度。对于同一幅图象,分别求RVI和NDVI时会发现,RVI值增加的速度高于NDVI增加速度,即NDVI对高植被区具有较低的灵敏度;
4、NDVI能反映出植物冠层的背景影响,如土壤、潮湿地面、雪、枯叶、粗糙度等,且与植被覆盖有关。
下面来看一个具体的事例。下面两张图分别是TM影像的三波段(红光,左图)和四波段(近红外,右图),将对应位置的像素值进行运算就行了。
经过计算后,按照得到的NDVI值进行重新赋值,让NDVI值越大的区域绿色越深,反之越浅,若NDVI小于0,则置为0。效果图如下:
下面是我从高德地图上截取的卫星影像,可以看到NDVI的结果与实际情况基本一致。
下面来看一下实现的代码:
环境:VS2017+OPENCV4
Mat NDVI(Mat tm3, Mat tm4) {
//tm3=imread("tm3.bmp"),tm4=imread("tm4.bmp");
int rows = tm3.rows, cols = tm3.cols;
Mat ndvi(rows, cols, CV_8UC3);
double band3, band4;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
band3 = (double)tm3.at<Vec3b>(i, j)[0];
band4 = (double)tm4.at<Vec3b>(i, j)[0];
ndvi.at<Vec3b>(i, j)[0] = 0;
ndvi.at<Vec3b>(i, j)[1] = (255 - 255 * (band4 - band3) / (band3 + band4));//绿色层,NDVI越大,绿色越深
ndvi.at<Vec3b>(i, j)[2] = 0;
if (band3 > band4)//NDVI小于0则显示白色
ndvi.at<Vec3b>(i, j)[0] = ndvi.at<Vec3b>(i, j)[1] = ndvi.at<Vec3b>(i, j)[2] = 255;
}
}
imwrite("NDVI.bmp", ndvi);
return ndvi;
}