又经过了几天的学习,完成了第二个实验,相较于第一个实验,第二个实验在进行的过程中确实遇到了一些问题,耗时也更长,不过总归是完成了。
任务
计算植被指数,并通过阈值法提取植被
代码
注:部分函数的注释由于在第一篇帖子里出现了,这里就不赘言了
程序的结构如下:
主函数proj2.cpp
/*
* 用于学习GDAL编程 实验二 计算植被指数,并通过阈值法提取植被
* 时间 20210705
* 本次实验采用的影像为四波段的影像
*/
#include<iostream>
#include "gdal.h"
#include "gdal_priv.h"
#include "Func.h"
using namespace std;
int main()
{
// 读取影像
char* openpath = "D:\\Practice\\org\\exp2.tif";
GDALDataset* mDataset;
GDALAllRegister();
// 只读方式打开
mDataset = (GDALDataset*)GDALOpen(openpath, GA_ReadOnly);
if (mDataset == NULL)
{
cout << "未能正确加载数据!!!" << endl;
system("pause");
GDALDestroyDriverManager();
}
// 获取影像数据
int mX = mDataset->GetRasterXSize();
int mY = mDataset->GetRasterYSize();
GDALDataType mImgDataType = mDataset->GetRasterBand(1)->GetRasterDataType();
// 获取影像的地理信息和投影信息
double geoInformation[6];
mDataset->GetGeoTransform(geoInformation);
const char* gdalProjection = mDataset->GetProjectionRef();
// 新建一个驱动,影像格式为GTiff
GDALDriver* hDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
// 调用CalcuNDVI 进行计算,需要先建立一个数据集保存NDVI结果,NDVI中的数据类型是float
char* savepath = "D:\\Practice\\res\\exp2_ndvi.tif";
GDALDataset* mNDVIset = hDriver->Create(savepath, mX, mY, 1, GDT_Float32, NULL);
cout << "正在计算NDVI" << endl;
CalcuNDVI(mDataset, mNDVIset);
// 将影像的地理信息写到NDVI数据集中
mNDVIset->SetGeoTransform(geoInformation);
mNDVIset->SetProjection(gdalProjection);
// 调用ExtractVegetation进行提取,需要先建立一个数据集保存提取结果
char* savepath2 = "D:\\Practice\\res\\exp2_vegetation.tif";
GDALDataset* mVegetationSet = hDriver->Create(savepath2, mX, mY, 4, mImgDataType, NULL);
cout << "正在提取植被区域!!!" << endl;
ExtractVegetation(mDataset, mNDVIset, mVegetationSet, 0.35, 0.7);
// 将影像的地理信息写到植被数据集中
mVegetationSet->SetGeoTransform(geoInformation);
mVegetationSet->SetProjection(gdalProjection);
// 关闭数据集,释放内存
GDALClose(mDataset);
GDALClose(mNDVIset);
GDALClose(mVegetationSet);
GDALDestroyDriverManager();
cout << "处理结束!!!" << endl;
getchar();
return 0;
}
头文件Func.h
#pragma once
#include <iostream>
#include "gdal.h"
#include "gdal_priv.h"
#include "ogr_spatialref.h"
using namespace std;
// 计算NDVI,mDataset为输入数据,mNDVI为计算结果
void CalcuNDVI(GDALDataset* mDataset,GDALDataset* &mNDVI);
// 利用NDVI,采用阈值分割的方式提取植被,mDataset为原始影像,
// mNDVIset为NDVI数据,其值在[-1,+1]之间,VegetationSet为提取出的植被数据,th1为低阈值,th2为高阈值
void ExtractVegetation(GDALDataset* mDataset, GDALDataset* mNDVIset, GDALDataset* &VegetationSet, float th1, float th2);
函数文件 Func.cpp
#include "Func.h"
void CalcuNDVI(GDALDataset* mDataset, GDALDataset* &mNDVIset)
{
// 获取影像的参数
int mX = mDataset->GetRasterXSize();
int mY = mDataset->GetRasterYSize();
int mDataType = mDataset->GetRasterBand(1)->GetRasterDataType();
// 将影像中的四个波段取出,分别为NIR,R,G,B
GDALRasterBand* mB = mDataset->GetRasterBand(1);
GDALRasterBand* mG = mDataset->GetRasterBand(2);
GDALRasterBand* mR = mDataset->GetRasterBand(3);
GDALRasterBand* mNIR = mDataset->GetRasterBand(4);
// 申请缓冲区
float* RedBuf = (float*)CPLMalloc(sizeof(float)*mX*mY);
float* NIRBuf = (float*)CPLMalloc(sizeof(float)*mX*mY);
float* mNDVIband = (float*)CPLMalloc(sizeof(float)*mX*mY);
// 从R和NIR波段中取出数据放到缓冲区
mR->RasterIO(GF_Read, 0, 0, mX, mY, RedBuf, mX, mY, GDT_UInt32, 0, 0);
mNIR->RasterIO(GF_Read, 0, 0, mX, mY, NIRBuf, mX, mY, GDT_UInt32, 0, 0);
// 计算NDVI
for (int i = 0; i < mY; i++)
{
for (int j = 0; j < mX; j++)
{
float r = RedBuf[i*mX + j];
float nir = NIRBuf[i*mX + j];
mNDVIband[i*mX + j] = (nir - r) / (nir + r);
}
}
// 将计算结果写入NDVI的数据集中
mNDVIset->GetRasterBand(1)->RasterIO(GF_Write, 0, 0, mX, mY, mNDVIband, mX, mY, GDT_Float32, 0, 0);
// 释放内存
CPLFree(RedBuf);
CPLFree(NIRBuf);
CPLFree(mNDVIband);
}
void ExtractVegetation(GDALDataset * mDataset, GDALDataset * mNDVIset, GDALDataset *& VegetationSet, float th1, float th2)
{
// 获取影像参数
int mX = mDataset->GetRasterXSize();
int mY = mDataset->GetRasterYSize();
GDALDataType mImgDataType = mDataset->GetRasterBand(1)->GetRasterDataType();
GDALDataType mNDVIDataType = mNDVIset->GetRasterBand(1)->GetRasterDataType();
// 获取原始影像的四个波段
GDALRasterBand* mBand1 = mDataset->GetRasterBand(1);
GDALRasterBand* mBand2 = mDataset->GetRasterBand(2);
GDALRasterBand* mBand3 = mDataset->GetRasterBand(3);
GDALRasterBand* mBand4 = mDataset->GetRasterBand(4);
// 获取NDVI的波段
GDALRasterBand* mNDVIBand = mNDVIset->GetRasterBand(1);
// 申请缓冲区,用来保存原始波段和NDVI的数据
unsigned short* mBandBuf1 = (unsigned short*)CPLMalloc(mX*mY * mImgDataType);
unsigned short* mBandBuf2 = (unsigned short*)CPLMalloc(mX*mY * mImgDataType);
unsigned short* mBandBuf3 = (unsigned short*)CPLMalloc(mX*mY * mImgDataType);
unsigned short* mBandBuf4 = (unsigned short*)CPLMalloc(mX*mY * mImgDataType);
float* mNDVIBandBuf = (float*)CPLMalloc(mX*mY * mNDVIDataType);
// 将各个波段的数据放入对应的缓冲区
mBand1->RasterIO(GF_Read, 0, 0, mX, mY, mBandBuf1, mX, mY, mImgDataType, 0, 0);
mBand2->RasterIO(GF_Read, 0, 0, mX, mY, mBandBuf2, mX, mY, mImgDataType, 0, 0);
mBand3->RasterIO(GF_Read, 0, 0, mX, mY, mBandBuf3, mX, mY, mImgDataType, 0, 0);
mBand4->RasterIO(GF_Read, 0, 0, mX, mY, mBandBuf4, mX, mY, mImgDataType, 0, 0);
mNDVIBand->RasterIO(GF_Read, 0, 0, mX, mY, mNDVIBandBuf, mX, mY, mNDVIDataType, 0, 0);
// 申请缓冲区,用来保存提取出的植被区域
unsigned short* mVegBand1 = (unsigned short*)CPLMalloc(mX*mY * mImgDataType);
unsigned short* mVegBand2 = (unsigned short*)CPLMalloc(mX*mY * mImgDataType);
unsigned short* mVegBand3 = (unsigned short*)CPLMalloc(mX*mY * mImgDataType);
unsigned short* mVegBand4 = (unsigned short*)CPLMalloc(mX*mY * mImgDataType);
// 通过阈值来提取植被区域
for (int i = 0; i < mX*mY; i++)
{
// 若在阈值范围内,赋对应的值,若不在,赋值为0
if (mNDVIBandBuf[i] >= th1&&mNDVIBandBuf[i] <= th2)
{
mVegBand1[i] = mBandBuf1[i];
mVegBand2[i] = mBandBuf2[i];
mVegBand3[i] = mBandBuf3[i];
mVegBand4[i] = mBandBuf4[i];
}
else
{
mVegBand1[i] = 0;
mVegBand2[i] = 0;
mVegBand3[i] = 0;
mVegBand4[i] = 0;
}
}
// 把提取结果放到数据集中
VegetationSet->GetRasterBand(1)->RasterIO(GF_Write, 0, 0, mX, mY, mVegBand1, mX, mY, mImgDataType, 0, 0);
VegetationSet->GetRasterBand(2)->RasterIO(GF_Write, 0, 0, mX, mY, mVegBand2, mX, mY, mImgDataType, 0, 0);
VegetationSet->GetRasterBand(3)->RasterIO(GF_Write, 0, 0, mX, mY, mVegBand3, mX, mY, mImgDataType, 0, 0);
VegetationSet->GetRasterBand(4)->RasterIO(GF_Write, 0, 0, mX, mY, mVegBand4, mX, mY, mImgDataType, 0, 0);
// 释放内存
CPLFree(mBandBuf1);
CPLFree(mBandBuf2);
CPLFree(mBandBuf3);
CPLFree(mBandBuf4);
CPLFree(mNDVIBandBuf);
CPLFree(mVegBand1);
CPLFree(mVegBand2);
CPLFree(mVegBand3);
CPLFree(mVegBand4);
}
运行结果
影像数据:
NDVI:
提取植被:
结语
这一个实验中间确实卡了好几次,中间也在弄其他东西,以上的代码里面确实还有一些不合适的地方,但,,,总之结果是跑出来了ㄟ(川.一ㄟ)。后面再慢慢改进吧!主要还是对于C语言的理解不够,很多东西都是边用边学,一知半解的,看官也请多包涵。总之,任重而道远,慢慢学吧~~
版权声明:本文为qq_45690046原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。