最近在做基于RPC的像方改正模型,方便对数据进行测试,修改了GDAL库中的RPC纠正模型,使之可以支持RPC像方改正参数。

下面是RPC模型的公式,rn,cn为归一化之后的图像行列号坐标,PLH为归一化后的经度纬度高程。

将上面的公式变形,使用偏移系数和缩放系数带入,可以得到图像的行列号坐标与经纬度坐标之间的坐标转换关系。整理后的公式如下所示,下标带s的为缩放系数,下标为0的表示偏移系数,rc为图像行列号,此处的PLH为地面经纬度坐标,P1~P4为有理函数的多项式系数。

使用像方改正模型的公式如下所示,Line和Sample为图像的行列号,rc为通过RPC模型将地面点经纬度高程计算得到的行列号,deltaR和DeltaC为像方改正数。

deltaR和DeltaC像方改正数使用仿射变换模型,具体公式如下,A0~A2为行方向的改正系数,B0~B2为列方向改正系数。无改正时这六个系数均为0.

将上面两个公式合并之后,再将DeltaR和DeltaC移向等式坐标,合并同类项之后,就得到了最终的一个仿射变换系数,此时无改正时,六个系数变为0 1 0 0 0 1。该系数为下面是用的最终系数。

修改的代码很少,在GDAL源码中的alg文件夹里面的gdal_rpc.cpp中,具体修改三处地方。

第一处,GDALRPCTransformInfo结构体,在结构体中增加两个double [6]的数组,用于保存RPC像方改正系数。修改后的代码如下,最后两个参数adfAffineTransform和adfReverseAffineTransform分别表示RPC像方改正系数及其逆变换系数。

typedef struct {

    GDALTransformerInfo sTI;

    GDALRPCInfo sRPC;

    double      adfPLToLatLongGeoTransform[6];

    int         bReversed;

    double      dfPixErrThreshold;

    double      dfHeightOffset;

    double      dfHeightScale;

    char        *pszDEMPath;

    DEMResampleAlg eResampleAlg;

    int         bHasTriedOpeningDS;
GDALDataset *poDS; OGRCoordinateTransformation *poCT; double adfGeoTransform[6];
double adfReverseGeoTransform[6]; double adfAffineTransform[6]; //RPC adjustment affine transform
double adfReverseAffineTransform[6]; //RPC adjustment reverse affine transform
} GDALRPCTransformInfo;

第二处,在函数GDALCreateRPCTransformer()中,主要是将参数papszOptions中的像方改正系数进行解析,然后给结构体中新加的两个数组赋值。便于后续进行坐标转换的时候使用。修改后的代码如下,由于代码太长,只贴出我修改的部分代码。下面代码中The Affine transform parameters部分的代码由我新加,主要是通过一个RPC_AFFINE来指定像方改正的六个系数,六个系数中间用空格隔开。然后将解析后的六个系数计算逆变换系数。默认系数是0 1 0 0 0 1,表示不进行像方改正。

//前面的代码省略
/* -------------------------------------------------------------------- */
/* The DEM interpolation */
/* -------------------------------------------------------------------- */
const char *pszDEMInterpolation = CSLFetchNameValueDef( papszOptions, "RPC_DEMINTERPOLATION", "bilinear" );
if(EQUAL(pszDEMInterpolation, "near" ))
psTransform->eResampleAlg = DRA_NearestNeighbour;
else if(EQUAL(pszDEMInterpolation, "bilinear" ))
psTransform->eResampleAlg = DRA_Bilinear;
else if(EQUAL(pszDEMInterpolation, "cubic" ))
psTransform->eResampleAlg = DRA_Cubic;
else
psTransform->eResampleAlg = DRA_Bilinear; /* -------------------------------------------------------------------- */
/* The Affine transform parameters */
/* -------------------------------------------------------------------- */
const char *pszRpcAffine = CSLFetchNameValueDef( papszOptions, "RPC_AFFINE", "0 1 0 0 0 1" );
if(pszRpcAffine != NULL) //解析RPC像方改正仿射变换参数
{
char** papszTokens = CSLTokenizeString2( pszRpcAffine, " ", 0 );
int nTokens = CSLCount(papszTokens);
if(nTokens == 6) //must be 6
{
for (int i=0; i<6; i++)
psTransform->adfAffineTransform[i] = atof(papszTokens[i]);
}
else
{
psTransform->adfAffineTransform[1] = 1;
psTransform->adfAffineTransform[5] = 1;
} GDALInvGeoTransform( psTransform->adfAffineTransform, psTransform->adfReverseAffineTransform );
CSLDestroy(papszTokens);
} /* -------------------------------------------------------------------- */
/* Establish a reference point for calcualating an affine */
/* geotransform approximate transformation. */
/* -------------------------------------------------------------------- */
//后面的代码省略

第三处修改的地方就是在进行坐标转换的函数中,即函数GDALRPCTransform()中,这里面主要修改两部分,第一个部分就是坐标正变换的时候,第二个是坐标逆变换的时候,在坐标正变换的时候,也就是从经纬度坐标换算到原始图像行列号坐标时,等使用RPC模型转换完成后,再使用仿射变换的逆变换系数进行改正;在坐标逆变换的时候,也就是从原始图像行列号换算到经纬度坐标时,先使用仿射变换的正变换系数进行改正,然后将改正后的行列号带入RPC模型进行转换到经纬度。修改的代码就两行,但是原始的代码太多,就贴出来我新增的部分。

//此处是坐标正变换的时候新增的代码
GDALApplyGeoTransform(psTransform->adfReverseAffineTransform, padfX[i], padfY[i], padfX + i, padfY + i );
panSuccess[i] = TRUE; //此处是坐标逆变换的时候新增的代码
GDALApplyGeoTransform(psTransform->adfAffineTransform, padfX[i], padfY[i], padfX + i, padfY + i );
double dfResultX, dfResultY;

修改完之后,保存,然后重新编译GDAL库即可。之后我们就可以使用gdalwarp.exe这个超牛的工具来进行校正了。具体的命令就是在原来使用-rpc的命令基础上,增加一个-to “RPC_AFFINE=0 1 0 0 0 1”即可。当然这六个系数需要自己写程序使用控制点来进行反算,只要三个控制点即可,使用1个或两个控制点只能计算一个平移模型,即上面公式中的A0和B0。完整的命令行为:

gdalwarp.exe -rpc -to "RPC_AFFINE=-32.714672501057066 0.999199897235577 0.000158731686899 28.720843336473692 0.000589585516339 1.000068008511035" D:\rpctest\banda.tif D:\rpctest\banda_affine.tif

修改GDAL库支持RPC像方改正模型的更多相关文章

  1. 改动GDAL库支持RPC像方改正模型

    近期在做基于RPC的像方改正模型.方便对数据进行測试,改动了GDAL库中的RPC纠正模型,使之能够支持RPC像方改正參数. 以下是RPC模型的公式,rn,cn为归一化之后的图像行列号坐标,PLH为归一 ...

  2. 修改GDAL库支持IRSP6数据

    使用GDAL库发现不能打开IRSP6的数据,不过看GDAL提供的文件格式里面却是支持IRSP6的数据的,具体可以参考网页http://www.gdal.org/frmt_fast.html.下面图1是 ...

  3. 使GDAL库支持中文路径或中文文件名的处理方法

    之前生成的gdal 2.1.1动态库,在通过命令行执行时,遇到有中文路径或中文图像名时,GDALOpen函数不能正确的被调用,如下图: 解决方法: 1.      在所有使用GDALAllRegist ...

  4. 使用GDAL库中的RPC校正问题

    最近将GDAL库更新至1.11版本之后,发现之前写的RPC像方改正模型校正的结果偏差特别大(更新版本之前结果和PCI处理的结果一致).所以初步判断是GDAL库的bug,经过各个参数修改发现原来是指定的 ...

  5. 扩展GDAL,支持CNSDTF格式(一)

    扩展GDAL,支持CNSDTF格式(一) 一.        简介 本文主要根据<中华人民共和国国家标准GB/T17798-2007--地理空间数据交换格式(Geospatialdata tra ...

  6. GDAL库——读取图像并提取基本信息

    GDAL库是一个跨平台的栅格地理数据格式库,包括读取.写入.转换.处理各种栅格数据格式(有些特定的格式对一些操作如写入等不支持).它使用了一个单一的抽象数据模型就支持了大多数的栅格数据.这里有GDAL ...

  7. 浅析GDAL库C#版本支持中文路径问题(续)

    上篇博客中主要说了GDAL库C#版本中存在的问题,其表现形式主要是:"文件名中的汉字个数是偶数,完全没有影响,读取和创建都正常,如果文件名中的汉字个数是奇数,读取和创建都会报错." ...

  8. GDAL库扩展Landsat系列MTL文件格式支持

    Landsat系列卫星提供的数据,一般都是每个波段一个tif文件,然后外加一个MTL.txt的元数据文件,使用gdal可以直接打开每个波段的tif文件,但是有时候想在打开tif数据的同时能够自动读取M ...

  9. 浅析GDAL库C#版本支持中文路径问题

    GDAL库对于C#的支持问题还是蛮多的,对于中文路径的支持就是其中之一(另一个就是通过OGR库获取图形的坐标信息). 关于C#支持中文路径,看过我之前博客的应该都不陌生,如果使用的是我修改过的GDAL ...

随机推荐

  1. python实现购物车

    一. 功能: 1. 用户充值余额 判断余额输入格式是否正确,正确则转换成float型. 2. 显示商品列表 根据已有商品显示所有商品的序号.商品名称.和价格供用户选择 3. 用户选择商品 判断用户输入 ...

  2. session.save()返回值问题

    正常都应该返回插入的主键 但是 如果你用sessionFactory来写就一定返回0 先科普下持久化数据库的三个状态方便下面理解 一次会话状态中,持久化对象经历以下三种状态:1 transient:对 ...

  3. C# IE浏览器

    引用Microsoft HTML Object Library 引用 -> com -> Microsoft HTML Object Library 引用后,显示如图 1.判断ie浏览器是 ...

  4. 日历类和日期类转换 并发修改异常 泛型的好处 *各种排序 成员和局部变量 接口和抽象类 多态 new对象内存中的变化

    day07 ==和equals的区别? ==用于比较两个数值 或者地址值是否相同.  equals 用于比较两个对象的内容是否相同   String,StringBuffer.StringBuilde ...

  5. R语言中函数调试

    有时候会用R语言写一下简单的脚本处理函数,加入需要调试的话可以按照下面的步骤进行: fun <- function(x , y){ x + y x - y x * y x / y } debug ...

  6. 无忧代理免费ip爬取(端口js加密)

    起因 为了训练爬虫技能(其实主要还是js技能-),翻了可能有反爬的网站挨个摧残,现在轮到这个网站了:http://www.data5u.com/free/index.shtml 解密过程 打开网站,在 ...

  7. Java中使用CountDownLatch进行多线程同步

    CountDownLatch介绍 在前面的Java学习笔记中,总结了Java中进行多线程同步的几个方法: 1.synchronized关键字进行同步. 2.Lock锁接口及其实现类ReentrantL ...

  8. CentOS7下安装GitLab

    三步在CentOS7系统下,完成GitLab的安装. 1.安装和配置必须的依赖 sudo yum install curl policycoreutils openssh-server openssh ...

  9. IntelliJ IDEA在Local模式下Spark程序消除日志中INFO输出

    在使用Intellij IDEA,local模式下运行Spark程序时,会在Run窗口打印出很多INFO信息,辅助信息太多可能会将有用的信息掩盖掉.如下所示 要解决这个问题,主要是要正确设置好log4 ...

  10. Unity UGUI实现分段式血条

    我们可以看到像英雄联盟等游戏里英雄头顶的血条显示并非是纯色的,而是根据血量的多少而显示一定量的格子,这种方式明显是比较友好.比较美观的,事实上我们的游戏里面也想实现这样的效果,那该怎么办呢?根据血量的 ...