学习gdal的过程
![](https://www.osgeo.org/wp-content/uploads/GDAL-1_740x412_acf_cropped-370x206.png)
学习gdal的过程
ytkz代码片段1
#include <iostream>
#include "gdal_priv.h"
using namespace std;
int main()
{
printf("strat!\n");
//注册文件格式
GDALAllRegister();
const char* file = "D:\\img1_1_32.tif";
GDALDataset *ds = (GDALDataset*) GDALOpen (file, GA_ReadOnly);
//A* p则使用:p->play(); 左边是结构指针。
//A p 则使用:p.paly(); 左边是结构变量。
int Xsize = ds->GetRasterXSize();
int Ysize = ds->GetRasterYSize();
printf("Xsize =%d\n" , Xsize);
printf("影像长为%d,宽为%d,波段数为%d\n", ds->GetRasterXSize(), ds->GetRasterYSize(), ds->GetRasterCount());
//读取影像第一波段
GDALRasterBand* band = ds->GetRasterBand(1);
int min,max;
double minmax[2];
//char a;
//a = &min;
minmax[0] = band->GetMinimum(&min);
minmax[1] = band->GetMaximum(&max);
printf("\n最小值是:%fd\n最大值是%f\n", minmax[0],minmax[1]);
}
代码片段2
#include <iostream>
#include "gdal_priv.h" // GDAL核心库头文件
#include "cpl_conv.h" // 对于字符串处理函数
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " <raster-file>" << std::endl;
return 1;
}
// 注册驱动
GDALAllRegister();
// 打开栅格文件
GDALDataset *poDataset = static_cast<GDALDataset*>(GDALOpen(argv[1], GA_ReadOnly));
if (poDataset == nullptr) {
std::cerr << "Error: Cannot open raster file " << argv[1] << std::endl;
return 1;
}
// 获取空间参考
const OGRSpatialReference *spatialRef = poDataset->GetSpatialRef();
if (spatialRef != nullptr) {
char *pszWKT = nullptr;
spatialRef->exportToWkt(&pszWKT); # 这里不理解
std::cout << "WKT of the raster file:" << std::endl;
std::cout << pszWKT << std::endl;
// 释放分配的内存
CPLFree(pszWKT);
} else {
std::cout << "No spatial reference system found for this raster." << std::endl;
}
// 关闭数据集
GDALClose(poDataset);
return 0;
}
分块计算NDVI
#include <iostream>
#include "gdal_priv.h"
#include <vector>
#include <cmath>
#include <stdexcept>
#include <chrono> // 引入计时库
const int BLOCK_SIZE = 256; // 分块大小
void calculateNDVI(float* nirData, float* redData, float* ndviData, int blockWidth, int blockHeight) {
for (int y = 0; y < blockHeight; y++) {
for (int x = 0; x < blockWidth; x++) {
int index = y * blockWidth + x;
float nir = nirData[index];
float red = redData[index];
// 计算NDVI
if (nir + red != 0) {
ndviData[index] = (nir - red) / (nir + red);
} else {
ndviData[index] = -1.0f; // 无效值
}
}
}
}
int main() {
// 初始化计时
auto startTotal = std::chrono::high_resolution_clock::now(); // 总开始时间
// 初始化GDAL
GDALAllRegister();
// 打开输入影像
auto startOpen = std::chrono::high_resolution_clock::now(); // 打开文件开始时间
GDALDataset* poDataset = (GDALDataset*)GDALOpen("D:\\temp\\GF1C_miluo2.tif", GA_ReadOnly);
if (!poDataset) {
std::cerr << "无法打开影像文件!" << std::endl;
return 1;
}
auto endOpen = std::chrono::high_resolution_clock::now(); // 打开文件结束时间
std::chrono::duration<double> elapsedOpen = endOpen - startOpen;
std::cout << "打开文件耗时: " << elapsedOpen.count() << " 秒" << std::endl;
// 获取影像信息
int width = poDataset->GetRasterXSize();
int height = poDataset->GetRasterYSize();
int bandCount = poDataset->GetRasterCount();
if (bandCount < 4) {
std::cerr << "影像波段数不足,至少需要4个波段!" << std::endl;
GDALClose(poDataset);
return 1;
}
std::cout << "影像尺寸: " << width << "x" << height << std::endl;
std::cout << "波段数: " << bandCount << std::endl;
// 创建输出影像(单波段,存储NDVI)
auto startCreate = std::chrono::high_resolution_clock::now(); // 创建输出文件开始时间
GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
GDALDataset* poDstDataset = poDriver->Create("ndvi_output.tif", width, height, 1, GDT_Float32, nullptr);
// 设置NDVI影像的地理参考和投影信息
double geoTransform[6];
if (poDataset->GetGeoTransform(geoTransform) == CE_None) {
poDstDataset->SetGeoTransform(geoTransform);
}
const char* projection = poDataset->GetProjectionRef();
if (projection && strlen(projection) > 0) {
poDstDataset->SetProjection(projection);
}
auto endCreate = std::chrono::high_resolution_clock::now(); // 创建输出文件结束时间
std::chrono::duration<double> elapsedCreate = endCreate - startCreate;
std::cout << "创建输出文件耗时: " << elapsedCreate.count() << " 秒" << std::endl;
// 分块处理
auto startProcess = std::chrono::high_resolution_clock::now(); // 分块处理开始时间
for (int y = 0; y < height; y += BLOCK_SIZE) {
for (int x = 0; x < width; x += BLOCK_SIZE) {
// 计算当前块的实际大小
int blockWidth = std::min(BLOCK_SIZE, width - x);
int blockHeight = std::min(BLOCK_SIZE, height - y);
// 分配内存
std::vector<float> nirData(blockWidth * blockHeight);
std::vector<float> redData(blockWidth * blockHeight);
std::vector<float> ndviData(blockWidth * blockHeight);
// 读取NIR波段(第4波段)
GDALRasterBand* nirBand = poDataset->GetRasterBand(4);
nirBand->RasterIO(GF_Read, x, y, blockWidth, blockHeight,
nirData.data(), blockWidth, blockHeight, GDT_Float32, 0, 0);
// 读取Red波段(第3波段)
GDALRasterBand* redBand = poDataset->GetRasterBand(3);
redBand->RasterIO(GF_Read, x, y, blockWidth, blockHeight,
redData.data(), blockWidth, blockHeight, GDT_Float32, 0, 0);
// 计算NDVI
calculateNDVI(nirData.data(), redData.data(), ndviData.data(), blockWidth, blockHeight);
// 写入NDVI数据
GDALRasterBand* ndviBand = poDstDataset->GetRasterBand(1);
ndviBand->RasterIO(GF_Write, x, y, blockWidth, blockHeight,
ndviData.data(), blockWidth, blockHeight, GDT_Float32, 0, 0);
}
std::cout << "已处理行: " << y << std::endl;
}
auto endProcess = std::chrono::high_resolution_clock::now(); // 分块处理结束时间
std::chrono::duration<double> elapsedProcess = endProcess - startProcess;
std::cout << "分块处理耗时: " << elapsedProcess.count() << " 秒" << std::endl;
// 关闭数据集
auto startClose = std::chrono::high_resolution_clock::now(); // 关闭文件开始时间
GDALClose(poDataset);
GDALClose(poDstDataset);
auto endClose = std::chrono::high_resolution_clock::now(); // 关闭文件结束时间
std::chrono::duration<double> elapsedClose = endClose - startClose;
std::cout << "关闭文件耗时: " << elapsedClose.count() << " 秒" << std::endl;
// 总耗时
auto endTotal = std::chrono::high_resolution_clock::now(); // 总结束时间
std::chrono::duration<double> elapsedTotal = endTotal - startTotal;
std::cout << "总耗时: " << elapsedTotal.count() << " 秒" << std::endl;
std::cout << "NDVI计算完成!结果已保存到 ndvi_output.tif" << std::endl;
return 0;
}
对应的python代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2025/2/11 14:38
# @File : block_compute_ndvi.py
'''
'''
import osgeo.gdal as gdal
import numpy as np
from time import perf_counter
BLOCK_SIZE = 512 # 分块大小
def calculate_ndvi(nir_data, red_data):
"""计算NDVI"""
ndvi = np.zeros_like(nir_data, dtype=np.float32)
ndvi = (nir_data - red_data) / (nir_data + red_data)
ndvi[np.isnan(ndvi)] = -1.0 # 处理无效值
return ndvi
def main():
start_total = perf_counter() # 总开始时间
# 打开输入影像
start_open = perf_counter() # 打开文件开始时间
dataset = gdal.Open("D:\\temp\\GF1C_miluo2.tif", gdal.GA_ReadOnly)
if not dataset:
print("无法打开影像文件!")
return 1
end_open = perf_counter() # 打开文件结束时间
print(f"打开文件耗时: {end_open - start_open:.2f} 秒")
# 获取影像信息
width = dataset.RasterXSize
height = dataset.RasterYSize
band_count = dataset.RasterCount
if band_count < 4:
print("影像波段数不足,至少需要4个波段!")
dataset = None
return 1
print(f"影像尺寸: {width}x{height}")
print(f"波段数: {band_count}")
# 创建输出影像(单波段,存储NDVI)
start_create = perf_counter() # 创建输出文件开始时间
driver = gdal.GetDriverByName("GTiff")
out_dataset = driver.Create("ndvi_output.tif", width, height, 1, gdal.GDT_Float32)
# 设置NDVI影像的地理参考和投影信息
geo_transform = dataset.GetGeoTransform()
if geo_transform:
out_dataset.SetGeoTransform(geo_transform)
projection = dataset.GetProjection()
if projection:
out_dataset.SetProjection(projection)
end_create = perf_counter() # 创建输出文件结束时间
print(f"创建输出文件耗时: {end_create - start_create:.2f} 秒")
# 分块处理
start_process = perf_counter() # 分块处理开始时间
for y in range(0, height, BLOCK_SIZE):
for x in range(0, width, BLOCK_SIZE):
block_width = min(BLOCK_SIZE, width - x)
block_height = min(BLOCK_SIZE, height - y)
# 读取NIR波段(第4波段)
nir_band = dataset.GetRasterBand(4)
nir_data = nir_band.ReadAsArray(x, y, block_width, block_height).astype(np.float32)
# 读取Red波段(第3波段)
red_band = dataset.GetRasterBand(3)
red_data = red_band.ReadAsArray(x, y, block_width, block_height).astype(np.float32)
# 计算NDVI
ndvi_data = calculate_ndvi(nir_data, red_data)
# 写入NDVI数据
out_band = out_dataset.GetRasterBand(1)
out_band.WriteArray(ndvi_data, x, y)
print(f"已处理行: {y}")
end_process = perf_counter() # 分块处理结束时间
print(f"分块处理耗时: {end_process - start_process:.2f} 秒")
# 关闭数据集
start_close = perf_counter() # 关闭文件开始时间
dataset = None # 关闭输入影像
out_dataset = None # 关闭输出影像
end_close = perf_counter() # 关闭文件结束时间
print(f"关闭文件耗时: {end_close - start_close:.2f} 秒")
end_total = perf_counter() # 总结束时间
print(f"总耗时: {end_total - start_total:.2f} 秒")
print("NDVI计算完成!结果已保存到 ndvi_output.tif")
if __name__ == "__main__":
main()