生成矫正影像 给定一张TIF格式的影像,给定一套格网重投影坐标,输出一张新的TIF影像(要求是分块存储格式Tiled TIF); 实现为C++动态库,输出函数的接口定义如下: imgPath是输入的TIF影像路径; outImgPath是输出的TIF影像路径,要求以Tiled TIF格式存储,分块大小为256; gridWidth是原影像的格网矫正宽度,通常为64; gridPoints是原影像的格网矫正坐标,此数组中坐标点的顺序是逐行顺序存储。 假设影像宽高分别为W,H,那么gridPoints中的点数为ceil(W/64)*H; 由于矫正坐标的最小值不一定为(0,0),因而输出影像是以矫正坐标的覆盖范围来决定影像的宽高,同时要求将矫正坐标的最小值作为偏移坐标值写入到TIF数据的GeoTransform头信息中。 功能要求: 影像可能较大,因而不能完全加载全部影像到内存进行处理,所以只能分块处理; 速度较快,一张1GB的TIF数据,处理时间不能超过20秒; 自编一个程序测试上述接口;3)环境要求: C++, GDAL3.0.2,VS 2017 推荐使用GDAL3.0.2读写影像
时间: 2024-02-01 10:14:56 浏览: 160
TIF等图像格式文件的处理中间
4星 · 用户满意度95%
以下是代码实现的一种思路,仅供参考:
```c++
#include "gdal_priv.h"
#include <iostream>
#include <algorithm>
using namespace std;
// 定义格网点结构体
struct GridPoint {
double x;
double y;
};
// 定义矩形结构体
struct Rectangle {
double minX;
double maxX;
double minY;
double maxY;
};
// 获取格网点所在的矩形范围
Rectangle getGridRect(GridPoint* gridPoints, int gridWidth, int index) {
Rectangle rect;
rect.minX = gridPoints[index].x - gridWidth / 2.0;
rect.maxX = gridPoints[index].x + gridWidth / 2.0;
rect.minY = gridPoints[index].y - gridWidth / 2.0;
rect.maxY = gridPoints[index].y + gridWidth / 2.0;
return rect;
}
// 获取所有格网点所在的总矩形范围
Rectangle getTotalRect(GridPoint* gridPoints, int gridWidth, int width, int height) {
Rectangle totalRect;
totalRect.minX = gridPoints[0].x - gridWidth / 2.0;
totalRect.maxX = gridPoints[width / gridWidth].x + gridWidth / 2.0;
totalRect.minY = gridPoints[0].y - gridWidth / 2.0;
totalRect.maxY = gridPoints[height / gridWidth].y + gridWidth / 2.0;
return totalRect;
}
// 获取影像坐标点对应的像素坐标
void getPixelCoord(GDALDataset* dataset, double x, double y, int& pixelX, int& pixelY) {
double adfGeoTransform[6];
dataset->GetGeoTransform(adfGeoTransform);
pixelX = (int)((x - adfGeoTransform[0]) / adfGeoTransform[1] + 0.5);
pixelY = (int)((y - adfGeoTransform[3]) / adfGeoTransform[5] + 0.5);
}
// 获取像素坐标对应的影像坐标点
void getImageCoord(GDALDataset* dataset, int pixelX, int pixelY, double& x, double& y) {
double adfGeoTransform[6];
dataset->GetGeoTransform(adfGeoTransform);
x = adfGeoTransform[0] + pixelX * adfGeoTransform[1];
y = adfGeoTransform[3] + pixelY * adfGeoTransform[5];
}
// 获取像素坐标所在的矩形范围
Rectangle getPixelRect(GDALDataset* dataset, int pixelX, int pixelY, int tileSize) {
Rectangle rect;
rect.minX = pixelX;
rect.maxX = min(pixelX + tileSize, dataset->GetRasterXSize());
rect.minY = pixelY;
rect.maxY = min(pixelY + tileSize, dataset->GetRasterYSize());
return rect;
}
// 矫正影像
void rectifyImage(const char* imgPath, const char* outImgPath, GridPoint* gridPoints, int gridWidth) {
// 打开影像
GDALDataset* dataset = (GDALDataset*)GDALOpen(imgPath, GA_ReadOnly);
if (dataset == NULL) {
cout << "Failed to open input image." << endl;
return;
}
// 获取影像宽度和高度
int width = dataset->GetRasterXSize();
int height = dataset->GetRasterYSize();
// 获取格网点总数
int numGridPoints = (int)ceil(width / (double)gridWidth) * (int)ceil(height / (double)gridWidth);
// 获取所有格网点所在的总矩形范围
Rectangle totalRect = getTotalRect(gridPoints, gridWidth, width, height);
// 获取输出影像的宽度和高度
int outWidth = (int)ceil((totalRect.maxX - totalRect.minX) / gridWidth);
int outHeight = (int)ceil((totalRect.maxY - totalRect.minY) / gridWidth);
// 创建输出影像
GDALDriver* driver = GetGDALDriverManager()->GetDriverByName("GTiff");
GDALDataset* outDataset = driver->Create(outImgPath, outWidth, outHeight, dataset->GetRasterCount(), GDT_Byte, NULL);
if (outDataset == NULL) {
cout << "Failed to create output image." << endl;
return;
}
// 设置输出影像的地理位置信息
double adfGeoTransform[6];
adfGeoTransform[0] = totalRect.minX;
adfGeoTransform[1] = gridWidth;
adfGeoTransform[2] = 0;
adfGeoTransform[3] = totalRect.maxY;
adfGeoTransform[4] = 0;
adfGeoTransform[5] = -gridWidth;
outDataset->SetGeoTransform(adfGeoTransform);
// 逐个格网点矫正影像
for (int i = 0; i < numGridPoints; i++) {
// 获取格网点所在的矩形范围
Rectangle gridRect = getGridRect(gridPoints, gridWidth, i);
// 将矩形范围转换为像素坐标范围
int startPixelX, startPixelY, endPixelX, endPixelY;
getPixelCoord(dataset, gridRect.minX, gridRect.maxY, startPixelX, startPixelY);
getPixelCoord(dataset, gridRect.maxX, gridRect.minY, endPixelX, endPixelY);
// 将像素坐标范围分成小块,逐个处理
const int tileSize = 256;
for (int pixelY = startPixelY; pixelY < endPixelY; pixelY += tileSize) {
for (int pixelX = startPixelX; pixelX < endPixelX; pixelX += tileSize) {
// 获取像素坐标范围
Rectangle pixelRect = getPixelRect(dataset, pixelX, pixelY, tileSize);
// 创建内存块
int blockWidth = pixelRect.maxX - pixelRect.minX;
int blockHeight = pixelRect.maxY - pixelRect.minY;
GByte* blockData = new GByte[blockWidth * blockHeight * dataset->GetRasterCount()];
// 读取像素坐标范围内的数据
CPLErr err = dataset->RasterIO(GF_Read, pixelRect.minX, pixelRect.minY, blockWidth, blockHeight, blockData, blockWidth, blockHeight, GDT_Byte, dataset->GetRasterCount(), NULL, 0, 0, 0);
if (err != CE_None) {
cout << "Failed to read input image data." << endl;
delete[] blockData;
return;
}
// 将像素坐标范围转换为影像坐标范围
double startX, startY, endX, endY;
getImageCoord(dataset, pixelRect.minX, pixelRect.minY, startX, startY);
getImageCoord(dataset, pixelRect.maxX, pixelRect.maxY, endX, endY);
// 获取内存块对应的矩形范围
Rectangle blockRect;
blockRect.minX = max(gridRect.minX, startX);
blockRect.maxX = min(gridRect.maxX, endX);
blockRect.minY = max(gridRect.minY, endY);
blockRect.maxY = min(gridRect.maxY, startY);
// 将矩形范围转换为像素坐标范围
int startBlockPixelX, startBlockPixelY, endBlockPixelX, endBlockPixelY;
getPixelCoord(outDataset, blockRect.minX, blockRect.maxY, startBlockPixelX, startBlockPixelY);
getPixelCoord(outDataset, blockRect.maxX, blockRect.minY, endBlockPixelX, endBlockPixelY);
// 计算内存块在输出影像中的位置和大小
int outX = startBlockPixelX - pixelRect.minX;
int outY = startBlockPixelY - pixelRect.minY;
int outWidth = endBlockPixelX - startBlockPixelX;
int outHeight = endBlockPixelY - startBlockPixelY;
// 写入数据到输出影像中
err = outDataset->RasterIO(GF_Write, outX, outY, outWidth, outHeight, blockData, outWidth, outHeight, GDT_Byte, dataset->GetRasterCount(), NULL, 0, 0, 0);
if (err != CE_None) {
cout << "Failed to write output image data." << endl;
delete[] blockData;
return;
}
// 释放内存块
delete[] blockData;
}
}
}
// 关闭数据集
GDALClose(dataset);
GDALClose(outDataset);
cout << "Rectification complete." << endl;
}
```
以下是测试程序的代码:
```c++
int main() {
// 定义格网点数组
const int numGridPoints = 100;
GridPoint gridPoints[numGridPoints];
for (int i = 0; i < numGridPoints; i++) {
gridPoints[i].x = i * 10000.0;
gridPoints[i].y = i * 10000.0;
}
// 矫正影像
rectifyImage("input.tif", "output.tif", gridPoints, 64);
return 0;
}
```
阅读全文