Python+GDAL生成数字表面模型全流程(持续更新中)

   在卫星摄影测量中,在没有控制点的情况下生成DEM,可以利用卫星影像附带的RPC文件来辅助生成DEM。其主要分为

1、核线影像生成(各种各样的方法)

2、密集匹配(一般采用SGM)

3、RPC模型平差

在第一步的核线影像生成中,在不知道卫星参数的情况下,一般利用RPC辅助生成核线影像。

首先要读取卫星原始数据中的RPC参数,本次利用python+GDAL读取了卫星影像的RPC参数。

具体代码如下:

import os
import re
import numpy as np
import string
from osgeo import gdal
import time

# the class of RPC, including the par and function of rpc
class RPC():
    lineNumCoef = []
    lineDenCoef = []
    sampNumCoef = []
    sampDenCoef = []
    errBias = 0
    errRand = 0
    lineOffset = 0
    sampOffset = 0
    latOffset = 0
    longOffset = 0
    heightOffset = 0
    lineScale = 0
    sampScale = 0
    latScale = 0
    longScale = 0
    heightScale = 0

def pre_process_RPC(rpc):
    sample = RPC()
    sample.errBias = rpc['ERR_BIAS']
    sample.errRand = rpc['ERR_RAND']
    sample.lineOffset = rpc['LINE_OFF']
    sample.sampOffset = rpc['SAMP_OFF']
    sample.latOffset = rpc['LAT_OFF']
    sample.longOffset = rpc['LONG_OFF']
    sample.heightOffset = rpc['HEIGHT_OFF']
    sample.lineScale = rpc['LINE_SCALE']
    sample.sampScale = rpc['SAMP_SCALE']
    sample.latScale = rpc['LAT_SCALE']
    sample.longScale = rpc['LONG_SCALE']
    sample.heightScale = rpc['HEIGHT_SCALE']

    string1 = rpc['SAMP_DEN_COEFF'].split()
    string2 = rpc['SAMP_NUM_COEFF'].split()
    string3 = rpc['LINE_DEN_COEFF'].split()
    string4 = rpc['LINE_NUM_COEFF'].split()

    for i in range(20):
        sample.sampDenCoef.append(float(string1[i]))
        sample.sampNumCoef.append(float(string2[i]))
        sample.lineDenCoef.append(float(string3[i]))
        sample.lineNumCoef.append(float(string4[i]))

    return sample

input = "**************"    # path of the rpc file
dataset = gdal.Open(input, gdal.GA_Update)
rpc = dataset.GetMetadata("RPC")
result = pre_process_RPC(rpc)



在利用投影轨迹法计算核线轨迹的时候需要用到RPC模型,具体公式如下

RPC 模型正解公式

 具体的Python代码如下:

# Get l and s by RPC model
def RPC_Positive(lat, long, height, rpc):
    U = (lat - rpc.latOffset) / rpc.latScale
    V = (lon - rpc.lonOffset) / rpc.longScale
    W = (height - rpc.heightOffset) / rpc.heightScale

    u = np.mat('1, V, U, W, V*U, V*W, U*W, V*V, U*U, W*W,\
     U*V*W, V*V*V, V*U*U, V*W*W, V*V*U,\
     U*U*U, U*W*W, V*V*W, U*U*W, W*W*W')
    a = np.mat(rpc.lineNumCoef)
    b = np.mat(rpc.lineDenCoef)
    c = np.mat(rpc.sampleNumCoef)
    d = np.mat(rpc.sampleDenCoef)

    X = np.matmul(a, u.T) / np.matmul(b, U.t)
    Y = np.matmul(c, u.T) / np.matmul(d, u.T)

    l = rpc.lineOffset + rpc.lineScale * X
    s = rpc.sampleOffset + rpc.sampleScale * Y

    return l, s

下面还需要RPC反解算公式(由行列号计算经纬度)

直接放代码:

def RPC_Negative_inverse(samp, line , height, rpc):

    Xf = np.vstack([line, samp]).T

    long = -line ** 0
    lat = -samp ** 0

    EPS = 2
    x0 = cal_rfm(rpc.lineNumCoef, rpc.lineDenCoef, lat, long, height)
    y0 = cal_rfm(rpc.sampNumCoef, rpc.sampDenCoef, lat, long, height)
    x1 = cal_rfm(rpc.lineNumCoef, rpc.lineDenCoef, lat, long + EPS, height)
    y1 = cal_rfm(rpc.sampNumCoef, rpc.sampDenCoef, lat, long + EPS, height)
    x2 = cal_rfm(rpc.lineNumCoef, rpc.lineDenCoef, lat + EPS, long, height)
    y2 = cal_rfm(rpc.sampNumCoef, rpc.sampDenCoef, lat + EPS, long, height)

    n = 0
    while not np.all((x0 - line) ** 2 + (y0 - samp) ** 2 < 1e-20):

        if n > 1000:
            print("error,exceed 1000 times RPC_Negative")
            pass
        X0 = np.vstack([x0, y0]).T
        X1 = np.vstack([x1, y1]).T
        X2 = np.vstack([x2, y2]).T
        e1 = X1 - X0
        e2 = X2 - X0
        u = Xf - X0

        num = np.sum(np.multiply(u, e1), axis=1)
        den = np.sum(np.multiply(e1, e1), axis=1)
        a1 = np.divide(num, den).squeeze()
        num = np.sum(np.multiply(u, e2), axis=1)
        den = np.sum(np.multiply(e2, e2), axis=1)
        a2 = np.divide(num, den).squeeze()

        long = long + a1 * EPS
        lat = lat + a2 * EPS

        EPS = .1
        x0 = cal_rfm(rpc.lineNumCoef, rpc.lineDenCoef, lat, long, height)
        y0 = cal_rfm(rpc.sampNumCoef, rpc.sampDenCoef, lat, long, height)
        x1 = cal_rfm(rpc.lineNumCoef, rpc.lineDenCoef, lat, long + EPS, height)
        y1 = cal_rfm(rpc.sampNumCoef, rpc.sampDenCoef, lat, long + EPS, height)
        x2 = cal_rfm(rpc.lineNumCoef, rpc.lineDenCoef, lat + EPS, long, height)
        y2 = cal_rfm(rpc.sampNumCoef, rpc.sampDenCoef, lat + EPS, long, height)

        n += 1
    return long, lat


def RPC_Negative(line, samp, height, rpc):
    line = (line - rpc.lineOffset) / rpc.lineScale
    samp = (samp - rpc.sampOffset) / rpc.sampScale
    height = (height - rpc.heightOffset) / rpc.heightScale

    long, lat = RPC_Negative_inverse(samp, line, height, rpc)

    long = long * rpc.longScale + rpc.longOffset
    lat = lat * rpc.latScale + rpc.latOffset

    return float(long), float(lat)

最近发现一个事情,GDAL库里面提供了rpc正反算,我自己编写似乎没太大意义。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值