2019-01-16 19:40:08 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
2019-11-22 01:23:49 +00:00
|
|
|
# author: Minyan Zhong
|
2019-01-16 19:40:08 +00:00
|
|
|
|
2019-11-22 01:23:49 +00:00
|
|
|
import numpy as np
|
2019-01-16 19:40:08 +00:00
|
|
|
import argparse
|
|
|
|
import os
|
|
|
|
import isce
|
|
|
|
import isceobj
|
|
|
|
import shelve
|
|
|
|
import datetime
|
|
|
|
from isceobj.Location.Offset import OffsetField
|
|
|
|
from iscesys.StdOEL.StdOELPy import create_writer
|
|
|
|
#from mroipac.ampcor.DenseAmpcor import DenseAmpcor
|
|
|
|
|
2019-11-22 01:23:49 +00:00
|
|
|
from contrib.PyCuAmpcor import PyCuAmpcor
|
2019-01-16 19:40:08 +00:00
|
|
|
from grossOffsets import grossOffsets
|
|
|
|
|
|
|
|
#from isceobj.Utils.denseoffsets import denseoffsets
|
|
|
|
from isceobj.Util.decorators import use_api
|
|
|
|
|
|
|
|
from pprint import pprint
|
|
|
|
|
|
|
|
def createParser():
|
|
|
|
'''
|
|
|
|
Command line parser.
|
|
|
|
'''
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser( description='Generate offset field between two Sentinel slc')
|
2020-07-02 19:40:49 +00:00
|
|
|
parser.add_argument('-m','--reference', type=str, dest='reference', required=True,
|
|
|
|
help='Reference image')
|
|
|
|
parser.add_argument('-s', '--secondary',type=str, dest='secondary', required=True,
|
|
|
|
help='Secondary image')
|
2019-01-16 19:40:08 +00:00
|
|
|
parser.add_argument('-l', '--lat',type=str, dest='lat', required=False,
|
|
|
|
help='Latitude')
|
|
|
|
parser.add_argument('-L', '--lon',type=str, dest='lon', required=False,
|
|
|
|
help='Longitude')
|
|
|
|
parser.add_argument('--los',type=str, dest='los', required=False,
|
|
|
|
help='Line of Sight')
|
2020-07-02 19:40:49 +00:00
|
|
|
parser.add_argument('--referencexml',type=str, dest='referencexml', required=False,
|
|
|
|
help='Reference Image Xml File')
|
2019-01-16 19:40:08 +00:00
|
|
|
parser.add_argument('--ww', type=int, dest='winwidth', default=64,
|
|
|
|
help='Window Width')
|
|
|
|
parser.add_argument('--wh', type=int, dest='winhgt', default=64,
|
|
|
|
help='Window height')
|
|
|
|
parser.add_argument('--sw', type=int, dest='srcwidth', default=20,
|
|
|
|
help='Search window width')
|
|
|
|
parser.add_argument('--sh', type=int, dest='srchgt', default=20,
|
|
|
|
help='Search window height')
|
|
|
|
parser.add_argument('--mm', type=int, dest='margin', default=50,
|
|
|
|
help='Margin')
|
|
|
|
parser.add_argument('--kw', type=int, dest='skipwidth', default=64,
|
|
|
|
help='Skip across')
|
|
|
|
parser.add_argument('--kh', type=int, dest='skiphgt', default=64,
|
|
|
|
help='Skip down')
|
|
|
|
|
|
|
|
parser.add_argument('--nwa', type=int, dest='numWinAcross', default=-1,
|
|
|
|
help='Number of Window Across')
|
|
|
|
parser.add_argument('--nwd', type=int, dest='numWinDown', default=-1,
|
|
|
|
help='Number of Window Down')
|
|
|
|
|
|
|
|
parser.add_argument('-op','--outprefix', type=str, dest='outprefix', default='dense_ampcor',
|
|
|
|
help='Output prefix')
|
|
|
|
|
|
|
|
parser.add_argument('-os','--outsuffix', type=str, dest='outsuffix', default='dense_ampcor',
|
|
|
|
help='Output suffix')
|
|
|
|
|
|
|
|
parser.add_argument('-g','--gross', type=int, dest='gross', default=0,
|
|
|
|
help='Use gross offset or not')
|
|
|
|
|
|
|
|
parser.add_argument('--aa', type=int, dest='azshift', default=0,
|
|
|
|
help='Gross azimuth offset')
|
|
|
|
|
|
|
|
parser.add_argument('--rr', type=int, dest='rgshift', default=0,
|
|
|
|
help='Gross range offset')
|
|
|
|
|
|
|
|
parser.add_argument('--oo', type=int, dest='oversample', default=32,
|
|
|
|
help = 'Oversampling factor')
|
|
|
|
|
|
|
|
parser.add_argument('-r', '--redo', dest='redo', type=int, default=0
|
|
|
|
, help='To redo or not')
|
|
|
|
|
|
|
|
parser.add_argument('-drmp', '--deramp', dest='deramp', type=int, default=0
|
|
|
|
, help='deramp method (0: mag, 1: complex)')
|
|
|
|
|
|
|
|
parser.add_argument('-gid', '--gpuid', dest='gpuid', type=int, default=-1
|
|
|
|
, help='GPU ID')
|
|
|
|
|
|
|
|
|
|
|
|
return parser
|
|
|
|
|
|
|
|
def cmdLineParse(iargs = None):
|
|
|
|
parser = createParser()
|
|
|
|
inps = parser.parse_args(args=iargs)
|
|
|
|
|
|
|
|
return inps
|
|
|
|
|
|
|
|
@use_api
|
2020-07-02 19:40:49 +00:00
|
|
|
def estimateOffsetField(reference, secondary, inps=None):
|
2019-01-16 19:40:08 +00:00
|
|
|
|
2020-07-02 19:40:49 +00:00
|
|
|
###Loading the secondary image object
|
2019-01-16 19:40:08 +00:00
|
|
|
sim = isceobj.createSlcImage()
|
2020-07-02 19:40:49 +00:00
|
|
|
sim.load(secondary+'.xml')
|
2019-01-16 19:40:08 +00:00
|
|
|
sim.setAccessMode('READ')
|
|
|
|
sim.createImage()
|
|
|
|
|
|
|
|
|
2020-07-02 19:40:49 +00:00
|
|
|
###Loading the reference image object
|
2019-01-16 19:40:08 +00:00
|
|
|
sar = isceobj.createSlcImage()
|
2020-07-02 19:40:49 +00:00
|
|
|
sar.load(reference + '.xml')
|
2019-01-16 19:40:08 +00:00
|
|
|
sar.setAccessMode('READ')
|
|
|
|
sar.createImage()
|
|
|
|
|
|
|
|
|
|
|
|
width = sar.getWidth()
|
|
|
|
length = sar.getLength()
|
|
|
|
|
2019-11-22 17:53:26 +00:00
|
|
|
objOffset = PyCuAmpcor.PyCuAmpcor()
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
objOffset.algorithm = 0
|
|
|
|
objOffset.deviceID = inps.gpuid # -1:let system find the best GPU
|
2019-11-22 01:23:49 +00:00
|
|
|
objOffset.nStreams = 2 #cudaStreams
|
2019-01-16 19:40:08 +00:00
|
|
|
objOffset.derampMethod = inps.deramp
|
|
|
|
print(objOffset.derampMethod)
|
|
|
|
|
2020-07-02 19:40:49 +00:00
|
|
|
objOffset.referenceImageName = reference + '.vrt'
|
|
|
|
objOffset.referenceImageHeight = length
|
|
|
|
objOffset.referenceImageWidth = width
|
|
|
|
objOffset.secondaryImageName = secondary + '.vrt'
|
|
|
|
objOffset.secondaryImageHeight = length
|
|
|
|
objOffset.secondaryImageWidth = width
|
2019-01-16 19:40:08 +00:00
|
|
|
|
|
|
|
print("image length:",length)
|
|
|
|
print("image width:",width)
|
|
|
|
|
|
|
|
objOffset.numberWindowDown = (length-2*inps.margin-2*inps.srchgt-inps.winhgt)//inps.skiphgt
|
|
|
|
objOffset.numberWindowAcross = (width-2*inps.margin-2*inps.srcwidth-inps.winwidth)//inps.skipwidth
|
|
|
|
|
|
|
|
if (inps.numWinDown != -1):
|
|
|
|
objOffset.numberWindowDown = inps.numWinDown
|
|
|
|
|
|
|
|
if (inps.numWinAcross != -1):
|
|
|
|
objOffset.numberWindowAcross = inps.numWinAcross
|
|
|
|
|
|
|
|
|
|
|
|
print("nlines: ",objOffset.numberWindowDown)
|
|
|
|
print("ncolumns: ",objOffset.numberWindowAcross)
|
|
|
|
|
|
|
|
|
|
|
|
# window size
|
|
|
|
objOffset.windowSizeHeight = inps.winhgt
|
|
|
|
objOffset.windowSizeWidth = inps.winwidth
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
print(objOffset.windowSizeHeight)
|
|
|
|
print(objOffset.windowSizeWidth)
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
# search range
|
|
|
|
objOffset.halfSearchRangeDown = inps.srchgt
|
|
|
|
objOffset.halfSearchRangeAcross = inps.srcwidth
|
|
|
|
print(inps.srchgt,inps.srcwidth)
|
|
|
|
|
|
|
|
# starting pixel
|
2020-07-02 19:40:49 +00:00
|
|
|
objOffset.referenceStartPixelDownStatic = inps.margin
|
|
|
|
objOffset.referenceStartPixelAcrossStatic = inps.margin
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
# skip size
|
|
|
|
objOffset.skipSampleDown = inps.skiphgt
|
|
|
|
objOffset.skipSampleAcross = inps.skipwidth
|
|
|
|
|
|
|
|
# oversampling
|
|
|
|
objOffset.corrSufaceOverSamplingMethod = 0
|
|
|
|
objOffset.corrSurfaceOverSamplingFactor = inps.oversample
|
|
|
|
#objOffset.rawDataOversamplingFactor = 4
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
# output filenames
|
|
|
|
objOffset.offsetImageName = str(inps.outprefix) + str(inps.outsuffix) + '.bip'
|
|
|
|
objOffset.grossOffsetImageName = str(inps.outprefix) + str(inps.outsuffix) + '_gross.bip'
|
|
|
|
objOffset.snrImageName = str(inps.outprefix) + str(inps.outsuffix) + '_snr.bip'
|
|
|
|
|
|
|
|
print("offsetfield: ",objOffset.offsetImageName)
|
|
|
|
print("gross offsetfield: ",objOffset.grossOffsetImageName)
|
|
|
|
print("snr: ",objOffset.snrImageName)
|
|
|
|
|
|
|
|
offsetImageName = objOffset.offsetImageName.decode('utf8')
|
|
|
|
#print(type(offsetImageName))
|
|
|
|
#print(offsetImageName)
|
|
|
|
#print(type(objOffset.numberWindowAcross))
|
|
|
|
grossOffsetImageName = objOffset.grossOffsetImageName.decode('utf8')
|
|
|
|
snrImageName = objOffset.snrImageName.decode('utf8')
|
|
|
|
|
|
|
|
print(offsetImageName)
|
|
|
|
print(inps.redo)
|
|
|
|
if os.path.exists(offsetImageName) and inps.redo==0:
|
|
|
|
print('offsetfield file exists')
|
|
|
|
else:
|
|
|
|
# generic control
|
|
|
|
objOffset.numberWindowDownInChunk = 5
|
|
|
|
objOffset.numberWindowAcrossInChunk = 5
|
|
|
|
objOffset.mmapSize = 16
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
objOffset.setupParams()
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
## Set Gross Offset ###
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
if inps.gross == 0:
|
|
|
|
objOffset.setConstantGrossOffset(0, 0)
|
|
|
|
else:
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
print("Setting up grossOffset...")
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
objGrossOff = grossOffsets()
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
objGrossOff.setXSize(width)
|
|
|
|
objGrossOff.setYize(length)
|
|
|
|
objGrossOff.setMargin(inps.margin)
|
|
|
|
objGrossOff.setWinSizeHgt(inps.winhgt)
|
|
|
|
objGrossOff.setWinSizeWidth(inps.winwidth)
|
|
|
|
objGrossOff.setSearchSizeHgt(inps.srchgt)
|
|
|
|
objGrossOff.setSearchSizeWidth(inps.srcwidth)
|
|
|
|
objGrossOff.setSkipSizeHgt(inps.skiphgt)
|
|
|
|
objGrossOff.setSkipSizeWidth(inps.skipwidth)
|
|
|
|
objGrossOff.setLatFile(inps.lat)
|
|
|
|
objGrossOff.setLonFile(inps.lon)
|
|
|
|
objGrossOff.setLosFile(inps.los)
|
2020-07-02 19:40:49 +00:00
|
|
|
objGrossOff.setReferenceFile(inps.referencexml)
|
2019-01-16 19:40:08 +00:00
|
|
|
objGrossOff.setbTemp(inps.bTemp)
|
|
|
|
|
2019-11-22 01:23:49 +00:00
|
|
|
|
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
grossDown, grossAcross = objGrossOff.runGrossOffsets()
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
# change nan to 0
|
|
|
|
grossDown = np.nan_to_num(grossDown)
|
|
|
|
grossAcross = np.nan_to_num(grossAcross)
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
print("Before plotting the gross offsets (min and max): ", np.nanmin(grossDown),np.nanmax(grossDown))
|
|
|
|
print("Before plotting the gross offsets (min and max): ", np.rint(np.nanmin(grossDown)),np.rint(np.nanmax(grossDown)))
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
grossDown = np.int32(np.rint(grossDown.ravel()))
|
|
|
|
grossAcross = np.int32(np.rint(grossAcross.ravel()))
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
print(np.amin(grossDown), np.amax(grossDown))
|
|
|
|
print(np.amin(grossAcross), np.amax(grossAcross))
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
print(grossDown.shape)
|
|
|
|
print(grossDown.shape)
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
objOffset.setVaryingGrossOffset(grossDown, grossAcross)
|
|
|
|
#objOffset.setVaryingGrossOffset(np.zeros(shape=grossDown.shape,dtype=np.int32), np.zeros(shape=grossAcross.shape,dtype=np.int32))
|
2019-11-22 01:23:49 +00:00
|
|
|
|
|
|
|
# check
|
2019-01-16 19:40:08 +00:00
|
|
|
objOffset.checkPixelInImageRange()
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
# Run the code
|
|
|
|
print('Running PyCuAmpcor')
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
objOffset.runAmpcor()
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
print('Finished')
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
sar.finalizeImage()
|
|
|
|
sim.finalizeImage()
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
# Finalize the results
|
|
|
|
# offsetfield
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
outImg = isceobj.createImage()
|
|
|
|
outImg.setDataType('FLOAT')
|
|
|
|
outImg.setFilename(offsetImageName)
|
|
|
|
outImg.setBands(2)
|
|
|
|
outImg.scheme = 'BIP'
|
|
|
|
outImg.setWidth(objOffset.numberWindowAcross)
|
|
|
|
outImg.setLength(objOffset.numberWindowDown)
|
|
|
|
outImg.setAccessMode('read')
|
|
|
|
outImg.renderHdr()
|
2019-11-22 01:23:49 +00:00
|
|
|
|
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
# gross offsetfield
|
|
|
|
outImg = isceobj.createImage()
|
|
|
|
outImg.setDataType('FLOAT')
|
|
|
|
outImg.setFilename(grossOffsetImageName)
|
|
|
|
outImg.setBands(2)
|
|
|
|
outImg.scheme = 'BIP'
|
|
|
|
outImg.setWidth(objOffset.numberWindowAcross)
|
|
|
|
outImg.setLength(objOffset.numberWindowDown)
|
|
|
|
outImg.setAccessMode('read')
|
|
|
|
outImg.renderHdr()
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
# snr
|
|
|
|
snrImg = isceobj.createImage()
|
|
|
|
snrImg.setFilename(snrImageName)
|
|
|
|
snrImg.setDataType('FLOAT')
|
|
|
|
snrImg.setBands(1)
|
|
|
|
snrImg.setWidth(objOffset.numberWindowAcross)
|
|
|
|
snrImg.setLength(objOffset.numberWindowDown)
|
|
|
|
snrImg.setAccessMode('read')
|
|
|
|
snrImg.renderHdr()
|
|
|
|
|
|
|
|
return objOffset
|
2019-11-22 01:23:49 +00:00
|
|
|
|
|
|
|
def main(iargs=None):
|
2019-01-16 19:40:08 +00:00
|
|
|
|
|
|
|
inps = cmdLineParse(iargs)
|
|
|
|
outDir = os.path.dirname(inps.outprefix)
|
|
|
|
print(inps.outprefix)
|
2020-04-13 19:40:32 +00:00
|
|
|
os.makedirs(outDir, exist_ok=True)
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2020-07-02 19:40:49 +00:00
|
|
|
objOffset = estimateOffsetField(inps.reference, inps.secondary, inps)
|
2019-01-16 19:40:08 +00:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2019-11-22 01:23:49 +00:00
|
|
|
|
2019-01-16 19:40:08 +00:00
|
|
|
main()
|