def main(): usage = ''' Usage: ----------------------------------------------------------------------- python %s [-d spatialDimensions] [-p bandPositions [-r resolution ratio] [-b registration band] msfilename panfilename ----------------------------------------------------------------------- bandPositions and spatialDimensions are lists, e.g., -p [1,2,3] -d [0,0,400,400] Outfile name is msfilename_pan_atwt with same format as msfilename Note: PAN image must completely overlap MS image subset chosen -----------------------------------------------------''' %sys.argv[0] options, args = getopt.getopt(sys.argv[1:],'hd:p:r:b:') ratio = 4 dims1 = None pos1 = None k1 = 1 for option, value in options: if option == '-h': print usage return elif option == '-r': ratio = eval(value) elif option == '-d': dims1 = eval(value) elif option == '-p': pos1 = eval(value) elif option == '-b': k1 = eval(value) if len(args) != 2: print 'Incorrect number of arguments' print usage sys.exit(1) gdal.AllRegister() file1 = args[0] file2 = args[1] path = os.path.dirname(file1) basename1 = os.path.basename(file1) root1, ext1 = os.path.splitext(basename1) outfile = '%s/%s_pan_atwt%s'%(path,root1,ext1) # MS image inDataset1 = gdal.Open(file1,GA_ReadOnly) try: cols = inDataset1.RasterXSize rows = inDataset1.RasterYSize bands = inDataset1.RasterCount except Exception as e: print 'Error: %e --Image could not be read'%e sys.exit(1) if pos1 is None: pos1 = range(1,bands+1) num_bands = len(pos1) if dims1 is None: dims1 = [0,0,cols,rows] x10,y10,cols1,rows1 = dims1 # PAN image inDataset2 = gdal.Open(file2,GA_ReadOnly) try: bands = inDataset2.RasterCount except Exception as e: print 'Error: %e --Image could not be read'%e sys.exit(1) if bands>1: print 'PAN image must be a single band' sys.exit(1) geotransform1 = inDataset1.GetGeoTransform() geotransform2 = inDataset2.GetGeoTransform() if (geotransform1 is None) or (geotransform2 is None): print 'Image not georeferenced, aborting' sys.exit(1) print '=========================' print ' ATWT Pansharpening' print '=========================' print time.asctime() print 'MS file: '+file1 print 'PAN file: '+file2 # read in MS image band = inDataset1.GetRasterBand(1) tmp = band.ReadAsArray(0,0,1,1) dt = tmp.dtype MS = np.asarray(np.zeros((num_bands,rows1,cols1)),dtype = dt) k = 0 for b in pos1: band = inDataset1.GetRasterBand(b) MS[k,:,:] = band.ReadAsArray(x10,y10,cols1,rows1) k += 1 # if integer assume 11-bit quantization, otherwise must be byte if MS.dtype == np.int16: fact = 8.0 MS = auxil.byteStretch(MS,(0,2**11)) else: fact = 1.0 # read in corresponding spatial subset of PAN image gt1 = list(geotransform1) gt2 = list(geotransform2) ulx1 = gt1[0] + x10*gt1[1] uly1 = gt1[3] + y10*gt1[5] x20 = int(round(((ulx1 - gt2[0])/gt2[1]))) y20 = int(round(((uly1 - gt2[3])/gt2[5]))) cols2 = cols1*ratio rows2 = rows1*ratio band = inDataset2.GetRasterBand(1) PAN = band.ReadAsArray(x20,y20,cols2,rows2) # if integer assume 11-bit quantization, otherwise must be byte if PAN.dtype == np.int16: PAN = auxil.byteStretch(PAN,(0,2**11)) # out array sharpened = np.zeros((num_bands,rows2,cols2),dtype=np.float32) # compress PAN to resolution of MS image using DWT panDWT = auxil.DWTArray(PAN,cols2,rows2) r = ratio while r > 1: panDWT.filter() r /= 2 bn0 = panDWT.get_quadrant(0) # register (and subset) MS image to compressed PAN image using selected MSband lines0,samples0 = bn0.shape bn1 = MS[k1-1,:,:] # register (and subset) MS image to compressed PAN image (scale,angle,shift) = auxil.similarity(bn0,bn1) tmp = np.zeros((num_bands,lines0,samples0)) for k in range(num_bands): bn1 = MS[k,:,:] bn2 = ndii.zoom(bn1, 1.0/scale) bn2 = ndii.rotate(bn2, angle) bn2 = ndii.shift(bn2, shift) tmp[k,:,:] = bn2[0:lines0,0:samples0] MS = tmp smpl = np.random.randint(cols2*rows2,size=100000) print 'Wavelet correlations:' # loop over MS bands for k in range(num_bands): msATWT = auxil.ATWTArray(PAN) r = ratio while r > 1: msATWT.filter() r /= 2 # sample PAN wavelet details X = msATWT.get_band(msATWT.num_iter) X = X.ravel()[smpl] # resize the ms band to scale of the pan image ms_band = ndii.zoom(MS[k,:,:],ratio) # sample details of MS band tmpATWT = auxil.ATWTArray(ms_band) r = ratio while r > 1: tmpATWT.filter() r /= 2 Y = tmpATWT.get_band(msATWT.num_iter) Y = Y.ravel()[smpl] # get band for injection bnd = tmpATWT.get_band(0) tmpATWT = None aa,bb,R = auxil.orthoregress(X,Y) print 'Band '+str(k+1)+': %8.3f'%R # inject the filtered MS band msATWT.inject(bnd) # normalize wavelet components and expand msATWT.normalize(aa,bb) r = ratio while r > 1: msATWT.invert() r /= 2 sharpened[k,:,:] = msATWT.get_band(0) sharpened *= fact # rescale dynamic range msATWT = None # write to disk driver = inDataset1.GetDriver() outDataset = driver.Create(outfile,cols2,rows2,num_bands,GDT_Float32) gt1[0] += x10*ratio gt1[3] -= y10*ratio gt1[1] = gt2[1] gt1[2] = gt2[2] gt1[4] = gt2[4] gt1[5] = gt2[5] outDataset.SetGeoTransform(tuple(gt1)) projection1 = inDataset1.GetProjection() if projection1 is not None: outDataset.SetProjection(projection1) for k in range(num_bands): outBand = outDataset.GetRasterBand(k+1) outBand.WriteArray(sharpened[k,:,:],0,0) outBand.FlushCache() outDataset = None print 'Result written to %s'%outfile inDataset1 = None inDataset2 = None
def main(): usage = ''' Usage: ------------------------------------------------ Automatic radiometric normalization python %s [OPTIONS] iMadFile [fullSceneFile] Options: -h this help -t <float> P-value threshold (default 0.95) -d <list> spatial subset e.g. -d [0,0,500,500] -p <list> band positions e.g. -d [1,2,3] Spatial subset MUST match that of iMadFile Spectral dimension of fullSceneFile, if present, MUST match those of target and reference images iMadFile is assumed to be of form path/MAD(filename1-filename2).ext and the output file is named path/filename2_norm.ext. That is, it is assumed that filename1 is reference and filename2 is target and the output retains the format of the imMadFile. A similar convention is used to name the normalized full scene, if present: fullSceneFile_norm.ext Note that, for ENVI format, ext is the empty string. -------------------------------------------------------'''%sys.argv[0] options, args = getopt.getopt(sys.argv[1:],'hnp:d:t:') pos = None dims = None ncpThresh = 0.95 fsfn = None graphics = True for option, value in options: if option == '-h': print usage return elif option == '-n': graphics = False elif option == '-p': pos = eval(value) elif option == '-d': dims = eval(value) elif option == '-t': ncpThresh = eval(value) if (len(args) != 1) and (len(args) != 2): print 'Incorrect number of arguments' print usage sys.exit(1) imadfn = args[0] if len(args) == 2: fsfn = args[1] path = os.path.dirname(fsfn) basename = os.path.basename(fsfn) root, ext = os.path.splitext(basename) fsoutfn = path+'/'+root+'_norm_all'+ext path = os.path.dirname(imadfn) basename = os.path.basename(imadfn) root, ext = os.path.splitext(basename) b = root.find('(') e = root.find(')') referenceroot, targetbasename = root[b+1:e].split('-') referencefn = path + '/' + referenceroot + ext targetfn = path + '/' + targetbasename + ext targetroot, targetext = os.path.splitext(targetbasename) outfn = path + '/' + targetroot + '_norm' + targetext imadDataset = gdal.Open(imadfn,GA_ReadOnly) try: imadbands = imadDataset.RasterCount cols = imadDataset.RasterXSize rows = imadDataset.RasterYSize except Exception as e: print 'Error: %s --Image could not be read'%e sys.exit(1) referenceDataset = gdal.Open(referencefn,GA_ReadOnly) targetDataset = gdal.Open(targetfn,GA_ReadOnly) if pos is None: pos = range(1,referenceDataset.RasterCount+1) if dims is None: x0 = 0; y0 = 0 else: x0,y0,cols,rows = dims chisqr = imadDataset.GetRasterBand(imadbands).ReadAsArray(0,0,cols,rows).ravel() ncp = 1 - stats.chi2.cdf(chisqr,[imadbands-1]) idx = np.where(ncp>ncpThresh)[0] m = len(idx) idx1 = np.random.permutation(m) idxall = idx[idx1] idxtrain = idxall[0:2*m//3] idxtest = idxall[2*m//3:] mtrain = len(idxtrain) mtest = len(idxtest) print time.asctime() print 'reference: '+referencefn print 'target : '+targetfn print 'P-value threshold: '+str(ncpThresh) print 'no-change pixels for training: %i, for testing: %i' %(mtrain,mtest) start = time.time() driver = targetDataset.GetDriver() outDataset = driver.Create(outfn,cols,rows,len(pos),GDT_Float32) projection = imadDataset.GetProjection() geotransform = imadDataset.GetGeoTransform() if geotransform is not None: outDataset.SetGeoTransform(geotransform) if projection is not None: outDataset.SetProjection(projection) aa = [] bb = [] if graphics: plt.figure(1,(10,7)) j = 1 bands = len(pos) print 'band slope intercept correlation P(t-test) P(F-test)' for k in pos: x = referenceDataset.GetRasterBand(k).ReadAsArray(x0,y0,cols,rows).astype(float).ravel() y = targetDataset.GetRasterBand(k).ReadAsArray(x0,y0,cols,rows).astype(float).ravel() b,a,R = orthoregress(y[idxtrain],x[idxtrain]) my = max(y[idxtrain]) if (j<7) and graphics: plt.subplot(2,3,j) plt.plot(y[idxtrain],x[idxtrain],'.') plt.plot([0,my],[a,a+b*my]) plt.title('Band %i'%k) if ((j<4) and (bands<4)) or j>3: plt.xlabel('Target') if (j==1) or (j==4): plt.ylabel('Reference') aa.append(a) bb.append(b) outBand = outDataset.GetRasterBand(j) _,Pt = stats.ttest_ind(x[idxtest],a+b*y[idxtest]) f = np.var(x[idxtest])/np.var(a+b*y[idxtest]) if f < 1.0: f = 1/f Pf = stats.f.sf(f,mtest-1,mtest-1) print ' %i %f %f %f %f %f' %(k,b,a,R,Pt,Pf) outBand.WriteArray(np.resize(a+b*y,(rows,cols)),0,0) outBand.FlushCache() j += 1 if graphics: plt.show() plt.close() referenceDataset = None targetDataset = None outDataset = None print 'result written to: '+outfn if fsfn is not None: print 'normalizing '+fsfn+'...' fsDataset = gdal.Open(fsfn,GA_ReadOnly) try: cols = fsDataset.RasterXSize rows = fsDataset.RasterYSize except Exception as e: print 'Error %s -- Image could not be read in' sys.exit(1) driver = fsDataset.GetDriver() outDataset = driver.Create(fsoutfn,cols,rows,len(pos),GDT_Float32) projection = fsDataset.GetProjection() geotransform = fsDataset.GetGeoTransform() if geotransform is not None: outDataset.SetGeoTransform(geotransform) if projection is not None: outDataset.SetProjection(projection) j = 1 for k in pos: inBand = fsDataset.GetRasterBand(k) outBand = outDataset.GetRasterBand(j) for i in range(rows): y = inBand.ReadAsArray(0,i,cols,1) outBand.WriteArray(aa[j-1]+bb[j-1]*y,0,i) outBand.FlushCache() j += 1 outDataset = None fsDataset = None print 'full result written to: '+fsoutfn print 'elapsed time: %s'%str(time.time()-start)
def main(): usage = ''' Usage: ----------------------------------------------------------------------- python %s [-d spatialDimensions] [-p bandPositions [-r resolution ratio] [-b registration band] msfilename panfilename ----------------------------------------------------------------------- bandPositions and spatialDimensions are lists, e.g., -p [1,2,3] -d [0,0,400,400] Outfile name is msfilename_pan_dwt with same format as msfilename Note: PAN image must completely overlap MS image subset chosen -----------------------------------------------------''' %sys.argv[0] options, args = getopt.getopt(sys.argv[1:],'hd:p:r:b:') ratio = 4 dims1 = None pos1 = None k1 = 0 for option, value in options: if option == '-h': print usage return elif option == '-r': ratio = eval(value) elif option == '-d': dims1 = eval(value) elif option == '-p': pos1 = eval(value) elif option == '-b': k1 = eval(value)-1 if len(args) != 2: print 'Incorrect number of arguments' print usage sys.exit(1) gdal.AllRegister() file1 = args[0] file2 = args[1] path = os.path.dirname(file1) basename1 = os.path.basename(file1) root1, ext1 = os.path.splitext(basename1) outfile = '%s/%s_pan_dwt%s'%(path,root1,ext1) # MS image inDataset1 = gdal.Open(file1,GA_ReadOnly) try: cols = inDataset1.RasterXSize rows = inDataset1.RasterYSize bands = inDataset1.RasterCount except Exception as e: print 'Error: %e --Image could not be read'%e sys.exit(1) if pos1 is None: pos1 = range(1,bands+1) num_bands = len(pos1) if dims1 is None: dims1 = [0,0,cols,rows] x10,y10,cols1,rows1 = dims1 # PAN image inDataset2 = gdal.Open(file2,GA_ReadOnly) try: bands = inDataset2.RasterCount except Exception as e: print 'Error: %e --Image could not be read'%e sys.exit(1) if bands>1: print 'PAN image must be a single band' sys.exit(1) geotransform1 = inDataset1.GetGeoTransform() geotransform2 = inDataset2.GetGeoTransform() if (geotransform1 is None) or (geotransform2 is None): print 'Image not georeferenced, aborting' sys.exit(1) print '=========================' print ' DWT Pansharpening' print '=========================' print time.asctime() print 'MS file: '+file1 print 'PAN file: '+file2 # image arrays band = inDataset1.GetRasterBand(1) tmp = band.ReadAsArray(0,0,1,1) dt = tmp.dtype MS = np.asarray(np.zeros((num_bands,rows1,cols1)),dtype=dt) k = 0 for b in pos1: band = inDataset1.GetRasterBand(b) MS[k,:,:] = band.ReadAsArray(x10,y10,cols1,rows1) k += 1 # if integer assume 11bit quantization otherwise must be byte if MS.dtype == np.int16: fact = 8.0 MS = auxil.byteStretch(MS,(0,2**11)) else: fact = 1.0 # read in corresponding spatial subset of PAN image if (geotransform1 is None) or (geotransform2 is None): print 'Image not georeferenced, aborting' return # upper left corner pixel in PAN gt1 = list(geotransform1) gt2 = list(geotransform2) ulx1 = gt1[0] + x10*gt1[1] uly1 = gt1[3] + y10*gt1[5] x20 = int(round(((ulx1 - gt2[0])/gt2[1]))) y20 = int(round(((uly1 - gt2[3])/gt2[5]))) cols2 = cols1*ratio rows2 = rows1*ratio band = inDataset2.GetRasterBand(1) PAN = band.ReadAsArray(x20,y20,cols2,rows2) # if integer assume 11-bit quantization, otherwise must be byte if PAN.dtype == np.int16: PAN = auxil.byteStretch(PAN,(0,2**11)) # compress PAN to resolution of MS image panDWT = auxil.DWTArray(PAN,cols2,rows2) r = ratio while r > 1: panDWT.filter() r /= 2 bn0 = panDWT.get_quadrant(0) lines0,samples0 = bn0.shape bn1 = MS[k1,:,:] # register (and subset) MS image to compressed PAN image (scale,angle,shift) = auxil.similarity(bn0,bn1) tmp = np.zeros((num_bands,lines0,samples0)) for k in range(num_bands): bn1 = MS[k,:,:] bn2 = ndii.zoom(bn1, 1.0/scale) bn2 = ndii.rotate(bn2, angle) bn2 = ndii.shift(bn2, shift) tmp[k,:,:] = bn2[0:lines0,0:samples0] MS = tmp # compress pan once more, extract wavelet quadrants, and restore panDWT.filter() fgpan = panDWT.get_quadrant(1) gfpan = panDWT.get_quadrant(2) ggpan = panDWT.get_quadrant(3) panDWT.invert() # output array sharpened = np.zeros((num_bands,rows2,cols2),dtype=np.float32) aa = np.zeros(3) bb = np.zeros(3) print 'Wavelet correlations:' for i in range(num_bands): # make copy of panDWT and inject ith ms band msDWT = copy.deepcopy(panDWT) msDWT.put_quadrant(MS[i,:,:],0) # compress once more msDWT.filter() # determine wavelet normalization coefficents ms = msDWT.get_quadrant(1) aa[0],bb[0],R = auxil.orthoregress(fgpan.ravel(), ms.ravel()) Rs = 'Band '+str(i+1)+': %8.3f'%R ms = msDWT.get_quadrant(2) aa[1],bb[1],R = auxil.orthoregress(gfpan.ravel(), ms.ravel()) Rs += '%8.3f'%R ms = msDWT.get_quadrant(3) aa[2],bb[2],R = auxil.orthoregress(ggpan.ravel(), ms.ravel()) Rs += '%8.3f'%R print Rs # restore once and normalize wavelet coefficients msDWT.invert() msDWT.normalize(aa,bb) # restore completely and collect result r = 1 while r < ratio: msDWT.invert() r *= 2 sharpened[i,:,:] = msDWT.get_quadrant(0) sharpened *= fact # write to disk driver = inDataset1.GetDriver() outDataset = driver.Create(outfile,cols2,rows2,num_bands,GDT_Float32) projection1 = inDataset1.GetProjection() if projection1 is not None: outDataset.SetProjection(projection1) gt1 = list(geotransform1) gt1[0] += x10*ratio gt1[3] -= y10*ratio gt1[1] = gt2[1] gt1[2] = gt2[2] gt1[4] = gt2[4] gt1[5] = gt2[5] outDataset.SetGeoTransform(tuple(gt1)) for k in range(num_bands): outBand = outDataset.GetRasterBand(k+1) outBand.WriteArray(sharpened[k,:,:],0,0) outBand.FlushCache() outDataset = None print 'Result written to %s'%outfile inDataset1 = None inDataset2 = None