如何无需重采样重投影用GDAL定义图像四角?C语言实现疑问
问题解答
1. 能否用GDALWarp仅添加控制点而不重采样?
不行。GDALWarp的核心逻辑就是对图像做空间变换+像素重采样,它本质是通过变换重新计算像素位置,必然会修改像素数据、调整图像范围——你遇到的图像变大、角落黑边,就是TPS变换后为了覆盖所有变换像素扩展了输出范围导致的,这是Warp的固有特性,对大图像来说确实会带来性能和存储负担。
2. 是否必须Warp才能在Google Earth中使用?
完全不需要。Google Earth支持两种无需重采样的影像:
- 带有**GCP(地面控制点)**元数据的影像
- 带有正确仿射变换参数(包含平移、缩放、旋转)的影像
你用gdal_edit -a_ulurll的方式,本质是直接修改影像的仿射变换元数据(通过三个角的坐标计算出旋转、缩放参数),完全不碰像素数据,这种方式才是最适配你需求的,Google Earth可以直接识别使用。
3. C语言中如何实现gdal_edit -a_ulurll的功能?
gdal_edit底层是调用GDAL的C API修改影像元数据,你可以直接通过接口实现,步骤如下:
- 以更新模式打开目标影像
- 通过三个角的像素坐标+地理坐标,计算仿射变换矩阵
- 设置地理变换和坐标系
- 保存修改并关闭影像
以下是简化的代码示例:
#include "gdal.h" int main() { GDALAllRegister(); // 以更新模式打开影像 GDALDatasetH hDS = GDALOpenEx("test1-translated.tif", GDAL_OF_UPDATE, NULL, NULL, NULL); if (hDS == NULL) { return 1; } // 定义三个角的像素坐标(注意GDAL像素坐标从0开始)和对应地理坐标 // 左上(0,0) → (17.5, 57.5),右上(1050,0) → (17.7, 57.6),左下(0,714) → (17.6, 57.3) double px0 = 0, py0 = 0; double gx0 = 17.5, gy0 = 57.5; double px1 = 1050, py1 = 0; double gx1 = 17.7, gy1 = 57.6; double px2 = 0, py2 = 714; double gx2 = 17.6, gy2 = 57.3; // 计算仿射变换参数:[0]左上X, [1]X分辨率, [2]X旋转, [3]左上Y, [4]Y旋转, [5]Y分辨率 double adfGeoTransform[6]; adfGeoTransform[1] = (gx1 - gx0) / (px1 - px0); adfGeoTransform[2] = (gx2 - gx0) / (px2 - px0); adfGeoTransform[4] = (gy1 - gy0) / (px1 - px0); adfGeoTransform[5] = (gy2 - gy0) / (px2 - px0); adfGeoTransform[0] = gx0 - px0*adfGeoTransform[1] - py0*adfGeoTransform[2]; adfGeoTransform[3] = gy0 - px0*adfGeoTransform[4] - py0*adfGeoTransform[5]; // 设置地理变换 GDALSetGeoTransform(hDS, adfGeoTransform); // 设置EPSG:4326坐标系的WKT字符串 const char* pszWKT = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]"; GDALSetProjection(hDS, pszWKT); // 关闭影像,保存修改 GDALClose(hDS); return 0; }
注:实际开发中,建议用GDAL的GCP辅助函数计算仿射变换,避免手动计算的误差,比如通过GDALCreateGCPTransformer生成变换后再提取参数。
额外建议
- 如果你的影像只需要线性空间校正(旋转、缩放、平移),用三个控制点确定仿射变换是最优解,完全不修改像素数据
- 如果必须做非线性校正(比如TPS),那才需要用GDALWarp,但这种场景无法避免重采样,可以通过
-te参数指定输出范围来减少黑边
内容的提问来源于stack exchange,提问作者Maxxxxx
相关产品推荐
相关产品推荐

