专栏首页给永远比拿愉快GDAL入门-使用GDAL进行遥感影像NDVI的计算(C++版本)

GDAL入门-使用GDAL进行遥感影像NDVI的计算(C++版本)

不知道该怎么详细地写,直接上代码算了! (开发环境的搭建参考我的博文:GDAL开发环境搭建(VS2010 C++版)

#include <iostream>
#include <array>
#include "gdal_priv.h"
#include "ogr_spatialref.h"


using std::cout;
using std::endl;
using std::array;

/*
    @beief 计算NDVI NDVI=(Red-NIR)/(Red+NIR)=(Band3-Band4)/(Band3+Band4)
    @param inputFileNames 输入参数,红波段和红外波段的两幅遥感影像的全路径。 如果影像是合成影像,则程序需要做相应的修改。
    @param outputFileName 输出参数,输出NDVI影像的全路径
*/
int NDVI(array<const char*, 2>& inputFileNames, const char* outputFileName)
{
    array<GDALDataset*, 2> inputDatasets;
    GDALDataset* outputDataset;

    GDALAllRegister();

    cout << "正在读取影像..." << endl;
    for (int i = 0; i < 2; i++)
    {
        inputDatasets[i] = (GDALDataset *)GDALOpen(inputFileNames[i], GA_ReadOnly);
        if (inputDatasets[i] == NULL)
        {
            cout << "影像读取失败:(" << inputFileNames[i] << ")!" << '\n';
            return EXIT_FAILURE;
        }
    }


    int imgSizeX = inputDatasets[0]->GetRasterXSize(); // 影像的宽度(像元数目)
    int imgSizeY = inputDatasets[0]->GetRasterYSize(); // 影像的高度(像元数目)

    const char* imageFormat = "GTiff";
    GDALDriver* gdalDriver = GetGDALDriverManager()->GetDriverByName(imageFormat);
    if (gdalDriver == NULL)
    { 
        cout << "创建输出影像失败!" << '\n';
        return EXIT_FAILURE;
    }

    outputDataset = gdalDriver->Create(outputFileName, imgSizeX, imgSizeY, 1, GDT_Float32, NULL);

    // 获取输入数据的地理变化信息
    double goeInformation[6];
    inputDatasets[0]->GetGeoTransform(goeInformation);
    // 读取输入数据的地理信息并写入输出文件
    const char* gdalProjection = inputDatasets[0]->GetProjectionRef();
    outputDataset->SetGeoTransform(goeInformation);
    outputDataset->SetProjection(gdalProjection);

    cout << "正在进行数据处理..." << '\n';
    // 取得红波段和近红外波段
    // 读取数据,因为只有一个波段,所以Get第一波段的数据。如果是合成影像,这里依次读取各个波段的值(计数从1开始)。
    GDALRasterBand* raseterBandRed = inputDatasets[0]->GetRasterBand(1);
    GDALRasterBand* raseterBandNIR = inputDatasets[1]->GetRasterBand(1);
    GDALRasterBand* outputRasterBand = outputDataset->GetRasterBand(1);
    // 申请存储空间,为一行的大小
    float* bufferBlockRed = (float*)CPLMalloc(sizeof(float) * imgSizeX);
    float* bufferBlockNIR = (float*)CPLMalloc(sizeof(float) * imgSizeX);
    float* outputBufferBlock = (float*)CPLMalloc(sizeof(float) * imgSizeX);

    // 进行NDWI的计算
    for (int i = 0; i < imgSizeY; i++)
    {
        raseterBandRed->RasterIO(GF_Read, 0, i, imgSizeX, 1, bufferBlockRed, imgSizeX, 1, GDT_UInt32, 0, 0);
        raseterBandNIR->RasterIO(GF_Read, 0, i, imgSizeX, 1, bufferBlockNIR, imgSizeX, 1, GDT_UInt32, 0, 0);
        for (int j = 0; j < imgSizeX; j++)
            outputBufferBlock[j] = (bufferBlockRed[j] - bufferBlockNIR[j]) / (bufferBlockRed[j] + bufferBlockNIR[j]);
        outputRasterBand->RasterIO(GF_Write, 0, i, imgSizeX, 1, outputBufferBlock, imgSizeX, 1, GDT_Float32, 0, 0); // 写入数据
    }

    // 释放资源
    CPLFree(bufferBlockRed);
    CPLFree(bufferBlockNIR);
    CPLFree(outputBufferBlock);
    GDALClose(inputDatasets[0]);
    GDALClose(inputDatasets[1]);
    GDALClose(outputDataset);

    cout << "处理结束!" << endl;

    return EXIT_SUCCESS;
}

int main()
{
    array<const char*, 2> inputs = {
        "C:/Users/theone/Desktop/LT51240392010131BKT01_B3.TIF",
        "C:/Users/theone/Desktop/LT51240392010131BKT01_B4.TIF" };
    const char* outputs = "C:/Users/theone/Desktop/LT51240392010131BKT01_NDVI.TIF";
    int isSuccess = NDVI(inputs, outputs);
    getchar(); // 防止控制台一闪而过
    return isSuccess;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Leetcode: Climbing Stairs

    题目: You are climbing a stair case. It takes n steps to reach to the top.

    卡尔曼和玻尔兹曼谁曼
  • 希尔排序

    希尔排序是对直接插入排序的改进,其实质就是分组插入排序,该方法又称缩小增量排序。 该算法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增...

    卡尔曼和玻尔兹曼谁曼
  • 二叉树的初始化

    比如我们给定这样的一组数据:{ 1, 2, 3, 4, 0, 5, 6, 0, 7 }(假设0代表空),则我们构建的二叉树是这样的:

    卡尔曼和玻尔兹曼谁曼
  • 二叉树遍历问题-LeetCode 144、94、145、102、987(前序,中序,后序,层次,垂序)

    来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/binary-tree-preorder-travers...

    算法工程师之路
  • 考虑用静态工厂方法代替构造器

    《Effective Java》这本书的第一条建议就是考虑用静态工厂方法代替构造器。刚读的时候一脸懵逼,什么是静态工厂方法,于是继续往下读,给出了一个简单实例:

    一觉睡到小时候
  • 我想给你介绍一个假的苹果网站

    网站的 URL 地址显示的是苹果官网,网址旁边是安全字样和绿色小锁,表示网站信息基于 https 加密传输,完全没什么问题,然而它就是一个钓鱼网站(演示网站)。

    疯狂的技术宅
  • Python | 掌握 Lambda 函数,四不要!

    Lambda 函数是 Python 中的匿名函数。当你需要完成一件小工作时,在本地环境中使用它们可以让工作得心应手。有些人将它们简称为 lambdas,它们的语...

    昱良
  • Robot Framework(3)- 基本概念

    https://www.cnblogs.com/poloyy/category/1770899.html

    小菠萝测试笔记
  • Python_内建高阶函数

      返回一个新列表,对一个可迭代对象的所有元素排序,排序规则为key定义的函数,reverse表示是否排序翻转

    py3study
  • 【前端】CSS : 入门

    CSS (Cascading Style Sheets) 用于渲染HTML元素标签的样式。

    Gavin-ZYX

扫码关注云+社区

领取腾讯云代金券