Example #1
0
def readImageFromVrt(inputfile, startSample, endSample, startLine, endLine):
    '''
    read a chunk of image
    the indexes (startSample, endSample, startLine, endLine) are included and start with zero

    memmap is not used, because it is much slower

    tested against readImage in runSwathMosaic.py
    '''
    import os
    from isceobj.Alos2Proc.Alos2ProcPublic import find_vrt_keyword
    from isceobj.Alos2Proc.Alos2ProcPublic import find_vrt_file

    inputimage = find_vrt_file(inputfile+'.vrt', 'SourceFilename', relative_path=True)
    byteorder = find_vrt_keyword(inputfile+'.vrt', 'ByteOrder')
    if byteorder == 'LSB':
        swapByte = False
    else:
        swapByte = True
    imageoffset = int(find_vrt_keyword(inputfile+'.vrt', 'ImageOffset'))
    lineoffset = int(find_vrt_keyword(inputfile+'.vrt', 'LineOffset'))

    data = np.zeros((endLine-startLine+1, endSample-startSample+1), dtype=np.complex64)
    with open(inputimage,'rb') as fp:
        #fp.seek(imageoffset, 0)
        #for i in range(endLine-startLine+1):
        for i in range(startLine, endLine+1):
            fp.seek(imageoffset+i*lineoffset+startSample*8, 0)
            if swapByte:
                tmp = np.fromfile(fp, dtype='>f', count=2*(endSample-startSample+1))
                cJ = np.complex64(1j)
                data[i-startLine] = tmp[0::2] + cJ * tmp[1::2]
            else:
                data[i-startLine] = np.fromfile(fp, dtype=np.complex64, count=endSample-startSample+1)
    return data
Example #2
0
def cropSlc(orbit, swath, slc, orbit2, swath2, edge=0, useVirtualFile=True):
    from isceobj.Alos2Proc.Alos2ProcPublic import find_vrt_keyword
    from isceobj.Alos2Proc.Alos2ProcPublic import create_xml
    '''
    orbit:  orbit of the image to be cropped
    swath:  swath of the image to be cropped
    slc:    image to be cropped
    orbit2: orbit of the other image
    swath2: swath of the other image
    '''

    #find topleft and lowerright corners
    #all indices start with 0
    corner = []
    for x in [[0, 0], [swath2.numberOfLines - 1, swath2.numberOfSamples - 1]]:
        line2 = x[0]
        sample2 = x[1]
        rg2 = swath2.startingRange + swath2.rangePixelSize * sample2
        az2 = swath2.sensingStart + datetime.timedelta(seconds=line2 /
                                                       swath2.prf)
        llh2 = orbit2.rdr2geo(az2, rg2)
        az, rg = orbit.geo2rdr(llh2)
        line = (az - swath.sensingStart).total_seconds() * swath.prf
        sample = (rg - swath.startingRange) / swath.rangePixelSize
        corner.append([line, sample])

    #image (to be cropped) bounds
    firstLine = 0
    lastLine = swath.numberOfLines - 1
    firstSample = 0
    lastSample = swath.numberOfSamples - 1

    #the othe image bounds in image (to be cropped)
    #add edge
    #edge = 9
    firstLine2 = int(corner[0][0] - edge)
    lastLine2 = int(corner[1][0] + edge)
    firstSample2 = int(corner[0][1] - edge)
    lastSample2 = int(corner[1][1] + edge)

    #image (to be cropped) output bounds
    firstLine3 = max(firstLine, firstLine2)
    lastLine3 = min(lastLine, lastLine2)
    firstSample3 = max(firstSample, firstSample2)
    lastSample3 = min(lastSample, lastSample2)
    numberOfSamples3 = lastSample3 - firstSample3 + 1
    numberOfLines3 = lastLine3 - firstLine3 + 1

    #check if there is overlap
    if lastLine3 - firstLine3 + 1 < 1000:
        raise Exception(
            'azimuth overlap < 1000 lines, not enough area for InSAR\n')
    if lastSample3 - firstSample3 + 1 < 1000:
        raise Exception(
            'range overlap < 1000 samples, not enough area for InSAR\n')

    #check if there is a need to crop image
    if abs(firstLine3-firstLine) < 100 and abs(lastLine3-lastLine) < 100 and \
       abs(firstSample3-firstSample) < 100 and abs(lastSample3-lastSample) < 100:
        print('no need to crop {}. nothing is done by crop.'.format(slc))
        return

    #crop image
    if useVirtualFile:
        #vrt
        SourceFilename = find_vrt_keyword(slc + '.vrt', 'SourceFilename')
        ImageOffset = int(find_vrt_keyword(slc + '.vrt', 'ImageOffset'))
        PixelOffset = int(find_vrt_keyword(slc + '.vrt', 'PixelOffset'))
        LineOffset = int(find_vrt_keyword(slc + '.vrt', 'LineOffset'))

        #overwrite vrt and xml
        img = isceobj.createImage()
        img.load(slc + '.xml')
        img.width = numberOfSamples3
        img.length = numberOfLines3
        img.renderHdr()

        #overrite vrt
        with open(slc + '.vrt', 'w') as fid:
            fid.write('''<VRTDataset rasterXSize="{0}" rasterYSize="{1}">
    <VRTRasterBand band="1" dataType="CFloat32" subClass="VRTRawRasterBand">
        <SourceFilename relativeToVRT="0">{2}</SourceFilename>
        <ByteOrder>MSB</ByteOrder>
        <ImageOffset>{3}</ImageOffset>
        <PixelOffset>8</PixelOffset>
        <LineOffset>{4}</LineOffset>
    </VRTRasterBand>
</VRTDataset>'''.format(
                numberOfSamples3, numberOfLines3, SourceFilename,
                ImageOffset + firstLine3 * LineOffset + firstSample3 * 8,
                LineOffset))
    else:
        #read and crop data
        with open(slc, 'rb') as f:
            f.seek(
                firstLine3 * swath.numberOfSamples *
                np.dtype(np.complex64).itemsize, 0)
            data = np.fromfile(f, dtype=np.complex64, count=numberOfLines3 * swath.numberOfSamples)\
                               .reshape(numberOfLines3,swath.numberOfSamples)
            data2 = data[:, firstSample3:lastSample3 + 1]
        #overwrite original
        data2.astype(np.complex64).tofile(slc)

        #creat new vrt and xml
        os.remove(slc + '.xml')
        os.remove(slc + '.vrt')
        create_xml(slc, numberOfSamples3, numberOfLines3, 'slc')

    #update parameters
    #update doppler and azfmrate first
    dop = np.polyval(swath.dopplerVsPixel[::-1],
                     np.arange(swath.numberOfSamples))
    dop3 = dop[firstSample3:lastSample3 + 1]
    p = np.polyfit(np.arange(numberOfSamples3), dop3, 3)
    swath.dopplerVsPixel = [p[3], p[2], p[1], p[0]]

    azfmrate = np.polyval(swath.azimuthFmrateVsPixel[::-1],
                          np.arange(swath.numberOfSamples))
    azfmrate3 = azfmrate[firstSample3:lastSample3 + 1]
    p = np.polyfit(np.arange(numberOfSamples3), azfmrate3, 3)
    swath.azimuthFmrateVsPixel = [p[3], p[2], p[1], p[0]]

    swath.numberOfSamples = numberOfSamples3
    swath.numberOfLines = numberOfLines3

    swath.startingRange += firstSample3 * swath.rangePixelSize
    swath.sensingStart += datetime.timedelta(seconds=firstLine3 / swath.prf)
Example #3
0
def frameMosaic(track,
                inputFiles,
                outputfile,
                rangeOffsets,
                azimuthOffsets,
                numberOfRangeLooks,
                numberOfAzimuthLooks,
                updateTrack=False,
                phaseCompensation=False,
                resamplingMethod=0):
    '''
    mosaic frames
    
    track:                 track
    inputFiles:            input file list
    output file:           output mosaic file
    rangeOffsets:          range offsets
    azimuthOffsets:        azimuth offsets
    numberOfRangeLooks:    number of range looks of the input files
    numberOfAzimuthLooks:  number of azimuth looks of the input files
    updateTrack:           whether update track parameters
    phaseCompensation:     whether do phase compensation for each frame
    resamplingMethod:      0: amp resampling. 1: int resampling. 2: slc resampling
    '''
    import numpy as np

    from contrib.alos2proc_f.alos2proc_f import rect_with_looks
    from contrib.alos2proc.alos2proc import resamp
    from isceobj.Alos2Proc.runSwathMosaic import readImage
    from isceobj.Alos2Proc.runSwathMosaic import findNonzero
    from isceobj.Alos2Proc.Alos2ProcPublic import create_xml
    from isceobj.Alos2Proc.Alos2ProcPublic import find_vrt_file
    from isceobj.Alos2Proc.Alos2ProcPublic import find_vrt_keyword

    numberOfFrames = len(track.frames)
    frames = track.frames

    rectWidth = []
    rectLength = []
    for i in range(numberOfFrames):
        infImg = isceobj.createImage()
        infImg.load(inputFiles[i] + '.xml')
        rectWidth.append(infImg.width)
        rectLength.append(infImg.length)

    #convert original offset to offset for images with looks
    #use list instead of np.array to make it consistent with the rest of the code
    rangeOffsets1 = [i / numberOfRangeLooks for i in rangeOffsets]
    azimuthOffsets1 = [i / numberOfAzimuthLooks for i in azimuthOffsets]

    #get offset relative to the first frame
    rangeOffsets2 = [0.0]
    azimuthOffsets2 = [0.0]
    for i in range(1, numberOfFrames):
        rangeOffsets2.append(0.0)
        azimuthOffsets2.append(0.0)
        for j in range(1, i + 1):
            rangeOffsets2[i] += rangeOffsets1[j]
            azimuthOffsets2[i] += azimuthOffsets1[j]

    #resample each frame
    rinfs = []
    for i, inf in enumerate(inputFiles):
        rinfs.append("{}_{}{}".format(
            os.path.splitext(os.path.basename(inf))[0], i,
            os.path.splitext(os.path.basename(inf))[1]))
        #do not resample first frame
        if i == 0:
            rinfs[i] = inf
        else:
            infImg = isceobj.createImage()
            infImg.load(inf + '.xml')
            rangeOffsets2Frac = rangeOffsets2[i] - int(rangeOffsets2[i])
            azimuthOffsets2Frac = azimuthOffsets2[i] - int(azimuthOffsets2[i])

            if resamplingMethod == 0:
                rect_with_looks(inf, rinfs[i], infImg.width, infImg.length,
                                infImg.width, infImg.length, 1.0, 0.0, 0.0,
                                1.0, rangeOffsets2Frac, azimuthOffsets2Frac, 1,
                                1, 1, 1, 'COMPLEX', 'Bilinear')
                if infImg.getImageType() == 'amp':
                    create_xml(rinfs[i], infImg.width, infImg.length, 'amp')
                else:
                    create_xml(rinfs[i], infImg.width, infImg.length, 'int')

            elif resamplingMethod == 1:
                #decompose amplitude and phase
                phaseFile = 'phase'
                amplitudeFile = 'amplitude'
                data = np.fromfile(inf, dtype=np.complex64).reshape(
                    infImg.length, infImg.width)
                phase = np.exp(np.complex64(1j) * np.angle(data))
                phase[np.nonzero(data == 0)] = 0
                phase.astype(np.complex64).tofile(phaseFile)
                amplitude = np.absolute(data)
                amplitude.astype(np.float32).tofile(amplitudeFile)

                #resampling
                phaseRectFile = 'phaseRect'
                amplitudeRectFile = 'amplitudeRect'
                rect_with_looks(phaseFile, phaseRectFile, infImg.width,
                                infImg.length, infImg.width, infImg.length,
                                1.0, 0.0, 0.0, 1.0, rangeOffsets2Frac,
                                azimuthOffsets2Frac, 1, 1, 1, 1, 'COMPLEX',
                                'Sinc')
                rect_with_looks(amplitudeFile, amplitudeRectFile, infImg.width,
                                infImg.length, infImg.width, infImg.length,
                                1.0, 0.0, 0.0, 1.0, rangeOffsets2Frac,
                                azimuthOffsets2Frac, 1, 1, 1, 1, 'REAL',
                                'Bilinear')

                #recombine amplitude and phase
                phase = np.fromfile(phaseRectFile, dtype=np.complex64).reshape(
                    infImg.length, infImg.width)
                amplitude = np.fromfile(amplitudeRectFile,
                                        dtype=np.float32).reshape(
                                            infImg.length, infImg.width)
                (phase * amplitude).astype(np.complex64).tofile(rinfs[i])

                #tidy up
                os.remove(phaseFile)
                os.remove(amplitudeFile)
                os.remove(phaseRectFile)
                os.remove(amplitudeRectFile)
                if infImg.getImageType() == 'amp':
                    create_xml(rinfs[i], infImg.width, infImg.length, 'amp')
                else:
                    create_xml(rinfs[i], infImg.width, infImg.length, 'int')
            else:
                resamp(inf, rinfs[i], 'fake', 'fake', infImg.width,
                       infImg.length, frames[i].swaths[0].prf,
                       frames[i].swaths[0].dopplerVsPixel, [
                           rangeOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                           0.0, 0.0, 0.0
                       ], [
                           azimuthOffsets2Frac, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
                           0.0, 0.0, 0.0
                       ])
                create_xml(rinfs[i], infImg.width, infImg.length, 'slc')

    #determine output width and length
    #actually no need to calculate in azimuth direction
    xs = []
    xe = []
    ys = []
    ye = []
    for i in range(numberOfFrames):
        if i == 0:
            xs.append(0)
            xe.append(rectWidth[i] - 1)
            ys.append(0)
            ye.append(rectLength[i] - 1)
        else:
            xs.append(0 - int(rangeOffsets2[i]))
            xe.append(rectWidth[i] - 1 - int(rangeOffsets2[i]))
            ys.append(0 - int(azimuthOffsets2[i]))
            ye.append(rectLength[i] - 1 - int(azimuthOffsets2[i]))

    (xmin, xminIndex) = min((v, i) for i, v in enumerate(xs))
    (xmax, xmaxIndex) = max((v, i) for i, v in enumerate(xe))
    (ymin, yminIndex) = min((v, i) for i, v in enumerate(ys))
    (ymax, ymaxIndex) = max((v, i) for i, v in enumerate(ye))

    outWidth = xmax - xmin + 1
    outLength = ymax - ymin + 1

    #prepare for mosaicing using numpy
    xs = [x - xmin for x in xs]
    xe = [x - xmin for x in xe]
    ys = [y - ymin for y in ys]
    ye = [y - ymin for y in ye]

    #compute phase offset
    if phaseCompensation:
        phaseOffsetPolynomials = [np.array([0.0])]
        for i in range(1, numberOfFrames):
            upperframe = np.zeros((ye[i - 1] - ys[i] + 1, outWidth),
                                  dtype=np.complex128)
            lowerframe = np.zeros((ye[i - 1] - ys[i] + 1, outWidth),
                                  dtype=np.complex128)
            #upper frame
            if os.path.isfile(rinfs[i - 1]):
                upperframe[:, xs[i - 1]:xe[i - 1] + 1] = readImage(
                    rinfs[i - 1], rectWidth[i - 1], rectLength[i - 1], 0,
                    rectWidth[i - 1] - 1, ys[i] - ys[i - 1],
                    ye[i - 1] - ys[i - 1])
            else:
                upperframe[:, xs[i - 1]:xe[i - 1] + 1] = readImageFromVrt(
                    rinfs[i - 1], 0, rectWidth[i - 1] - 1, ys[i] - ys[i - 1],
                    ye[i - 1] - ys[i - 1])
            #lower frame
            if os.path.isfile(rinfs[i]):
                lowerframe[:, xs[i]:xe[i] + 1] = readImage(
                    rinfs[i], rectWidth[i], rectLength[i], 0, rectWidth[i] - 1,
                    0, ye[i - 1] - ys[i])
            else:
                lowerframe[:, xs[i]:xe[i] + 1] = readImageFromVrt(
                    rinfs[i], 0, rectWidth[i] - 1, 0, ye[i - 1] - ys[i])
            #get a polynomial
            diff = np.sum(upperframe * np.conj(lowerframe), axis=0)
            (firstLine, lastLine, firstSample,
             lastSample) = findNonzero(np.reshape(diff, (1, outWidth)))
            #here i use mean value(deg=0) in case difference is around -pi or pi.
            deg = 0
            p = np.polyfit(np.arange(firstSample, lastSample + 1),
                           np.angle(diff[firstSample:lastSample + 1]), deg)
            phaseOffsetPolynomials.append(p)

            #check fit result
            DEBUG = False
            if DEBUG:
                #create a dir and work in this dir
                diffDir = 'frame_mosaic'
                os.makedirs(diffDir, exist_ok=True)
                os.chdir(diffDir)

                #dump phase difference
                diffFilename = 'phase_difference_frame{}-frame{}.int'.format(
                    i, i + 1)
                (upperframe * np.conj(lowerframe)).astype(
                    np.complex64).tofile(diffFilename)
                create_xml(diffFilename, outWidth, ye[i - 1] - ys[i] + 1,
                           'int')

                #plot phase difference vs range
                import matplotlib.pyplot as plt
                x = np.arange(firstSample, lastSample + 1)
                y = np.angle(diff[firstSample:lastSample + 1])
                plt.plot(x, y, label='original phase difference')
                plt.plot(x, np.polyval(p, x), label='fitted phase difference')
                plt.legend()

                plt.minorticks_on()
                plt.tick_params('both', length=10, which='major')
                plt.tick_params('both', length=5, which='minor')

                plt.xlabel('Range Sample Number [Samples]')
                plt.ylabel('Phase Difference [Rad]')
                plt.savefig('phase_difference_frame{}-frame{}.pdf'.format(
                    i, i + 1))

                os.chdir('../')

    #mosaic file
    outFp = open(outputfile, 'wb')
    for i in range(numberOfFrames):
        print('adding frame: {}'.format(i + 1))

        #phase offset in the polynomials
        if phaseCompensation:
            cJ = np.complex64(1j)
            phaseOffset = np.ones(outWidth, dtype=np.complex64)
            for j in range(i + 1):
                phaseOffset *= np.exp(
                    cJ *
                    np.polyval(phaseOffsetPolynomials[j], np.arange(outWidth)))

        #get start line number (starts with zero)
        if i == 0:
            ys1 = 0
        else:
            ys1 = int((ye[i - 1] + ys[i]) / 2.0) + 1 - ys[i]
        #get end line number (start with zero)
        if i == numberOfFrames - 1:
            ye1 = rectLength[i] - 1
        else:
            ye1 = int((ye[i] + ys[i + 1]) / 2.0) - ys[i]

        #get image format
        inputimage = find_vrt_file(rinfs[i] + '.vrt',
                                   'SourceFilename',
                                   relative_path=True)
        byteorder = find_vrt_keyword(rinfs[i] + '.vrt', 'ByteOrder')
        if byteorder == 'LSB':
            swapByte = False
        else:
            swapByte = True
        imageoffset = int(find_vrt_keyword(rinfs[i] + '.vrt', 'ImageOffset'))
        lineoffset = int(find_vrt_keyword(rinfs[i] + '.vrt', 'LineOffset'))

        #read image
        with open(inputimage, 'rb') as fp:
            for j in range(ys1, ye1 + 1):
                fp.seek(imageoffset + j * lineoffset, 0)
                data = np.zeros(outWidth, dtype=np.complex64)
                if swapByte:
                    tmp = np.fromfile(fp, dtype='>f', count=2 * rectWidth[i])
                    cJ = np.complex64(1j)
                    data[xs[i]:xe[i] + 1] = tmp[0::2] + cJ * tmp[1::2]
                else:
                    data[xs[i]:xe[i] + 1] = np.fromfile(fp,
                                                        dtype=np.complex64,
                                                        count=rectWidth[i])
                if phaseCompensation:
                    data *= phaseOffset
                data.astype(np.complex64).tofile(outFp)
    outFp.close()

    #delete files. DO NOT DELETE THE FIRST ONE!!!
    for i in range(numberOfFrames):
        if i == 0:
            continue
        os.remove(rinfs[i])
        os.remove(rinfs[i] + '.vrt')
        os.remove(rinfs[i] + '.xml')

    #update frame parameters
    if updateTrack:
        #mosaic size
        track.numberOfSamples = outWidth
        track.numberOfLines = outLength
        #NOTE THAT WE ARE STILL USING SINGLE LOOK PARAMETERS HERE
        #range parameters
        track.startingRange = frames[0].startingRange + (
            int(rangeOffsets2[0]) - int(rangeOffsets2[xminIndex])
        ) * numberOfRangeLooks * frames[0].rangePixelSize
        track.rangeSamplingRate = frames[0].rangeSamplingRate
        track.rangePixelSize = frames[0].rangePixelSize
        #azimuth parameters
        track.sensingStart = frames[0].sensingStart
        track.prf = frames[0].prf
        track.azimuthPixelSize = frames[0].azimuthPixelSize
        track.azimuthLineInterval = frames[0].azimuthLineInterval