def clip_raster_to_extent(inraster, outraster, xmin, ymin, xextent, yextent): """ """ #TODO Docstring original = openImage(inraster) originalproperties = gdalProperties(original) newgeotransform = change_geotransform(originalproperties.geotransform, xmin, ymin) outds = copySchemaToNewImage(originalproperties, outraster, cols=xextent, rows=yextent, geotransform=newgeotransform) for i in range(1, originalproperties.bands + 1): band = original.GetRasterBand(i) outband = outds.GetRasterBand(i) nodatavalue = band.GetNoDataValue() data = band.ReadAsArray(xmin, ymin, xextent, yextent) outband.WriteArray(data, 0, 0) outband.SetNoDataValue(nodatavalue) outband.FlushCache() del data, outband, band original = "" outds = "" return outraster
def get_px_coords_from_shapefile(raster, shapefile): """ Takes geographic coordinates from a shapefile and finds the corresponding pixel coordinates on a raster. rst = "/Users/phoetrymaster/Documents/School/Geography/Thesis/Data/MODIS_KANSAS_2007-2012/reprojected/clips/KansasEVI_2012_clip1.tif" #rst = "/Users/phoetrymaster/Documents/School/Geography/Thesis/Data/polygonclip_20130929223024_325071991/resampled/newclips/2012clip1.tif" shp = "/Users/phoetrymaster/Documents/School/Geography/Thesis/Data/MODIS_KANSAS_2007-2012/SampleAreas/samplepoints2012_clip1_new.shp" print get_px_coords_from_shapefile(rst, shp) """ #TODO docstrings from imageFunctions import openImage # open, close image file and get properties raster = openImage(raster) imageproperties = gdalProperties(raster) rasterwkt = raster.GetProjectionRef() oSRSop = osr.SpatialReference() oSRSop.ImportFromWkt(rasterwkt) raster = None shppoints = load_points(shapefile, oSRSop) # get pixel coords from point coords pxcoords = get_px_coords_from_geographic_coords(imageproperties, shppoints) return pxcoords
def read_image_into_array(gdalimage): """ """ #TODO Docstring properties = gdalProperties(gdalimage) array = numpy.empty([properties.bands, properties.rows, properties.cols], dtype=int) for i in range(properties.bands): band = gdalimage.GetRasterBand(i + 1) array[i] = band.ReadAsArray(0, 0, properties.cols, properties.rows) array = array.transpose(1, 2, 0) # Turn the array to allow a single pixel to be isolated in the stack (x, y, time orientation) return array.squeeze() # Squeeze removes z-dimension if image only has one band
def fit_refs_to_image(imagetoprocess, outputdirectory, signaturecollection, startDOY, doyinterval, bestguess, threshold=None, ndvalue=-3000, fitmethod=None, subset=None, meantype=None, workers=4, timebounds=None, xbounds=None, ybounds=None): """ imagepath = "/Users/phoetrymaster/Documents/School/Geography/Thesis/Data/ARC_Testing/ClipTesting/ENVI_1/test_clip_envi_3.dat" outdir = "/Users/phoetrymaster/Documents/School/Geography/Thesis/Data/OutImages/" newfoldername = "Testing" drivercode1 = 'ENVI' #ndvalue = -3000 startDOY = 1 interval = 16 threshold = 500 bestguess = 0 fitmthd = 'SLSQP' mean = geometric # Acceptable values are geometric (geometric mean) and arithmetic (arithmetic mean). It is an optional argument for the classifier. refs = { 'soy': {1: 174.5, 97: 1252.25, 65: 1139.5, 209: 7659.0, 273: 4606.75, 337: 1371.75, 17: 1055.5, 33: 1098.0, 49: 1355.25, 129: 1784.75, 257: 6418.0, 321: 1644.5, 305: 1472.75, 193: 5119.75, 289: 1878.75, 177: 3439.5, 241: 7565.75, 81: 1205.5, 225: 7729.75, 145: 1736.25, 161: 1708.25, 353: 1358.25, 113: 1340.0}, 'corn': {1: 392.25, 97: 1433.25, 65: 1258.5, 209: 6530.0, 273: 1982.5, 337: 1658.5, 17: 1179.25, 33: 1196.75, 49: 1441.25, 129: 1885.25, 257: 2490.25, 321: 1665.75, 305: 1439.0, 193: 6728.25, 289: 1634.5, 177: 6356.75, 241: 4827.25, 81: 1355.75, 225: 5547.5, 145: 2196.5, 161: 3143.25, 353: 1704.75, 113: 1716.5}, 'wheat': {1: 719.75, 97: 6594.75, 65: 1935.25, 209: 2013.5, 273: 1493.5, 337: 1498.25, 17: 1816.5, 33: 1815.0, 49: 1985.25, 129: 6758.0, 257: 1685.75, 321: 1582.5, 305: 1163.25, 193: 2186.25, 289: 1264.5, 177: 2222.5, 241: 2301.0, 81: 4070.5, 225: 1858.0, 145: 6228.5, 161: 3296.5, 353: 1372.5, 113: 7035.25} } sys.exit(fit_refs_to_image(imagepath, outdir, newfoldername, refs, startDOY, interval, threshold, bestguess, fitmthd, meantype=mean)) """ #TODO docstrings start = dt.now() print(start) try: print("\nProcessing {0}...".format(imagetoprocess)) print("Outputting files to {0}\n".format(outputdirectory)) #Open multi-date image to analyze image = openImage(imagetoprocess) imageproperties = gdalProperties(image) print("Input image dimensions are {0} columns by {1} rows and contains {2} bands.".format(imageproperties.cols, imageproperties.rows, imageproperties.bands)) array = read_image_into_array(image) # Read all bands into a 3d array representing the image stack (x, y, time orientation) image = "" if timebounds: timebounds = (bestguess + timebounds[0], bestguess + timebounds[1]) else: timebounds = (bestguess - 10, bestguess + 10) if not xbounds: xbounds = (0.6, 1.4) if not ybounds: ybounds = (0.6, 1.4) bounds = (xbounds, ybounds, timebounds) print(bounds) if subset: subset = get_px_coords_from_shapefile(imagetoprocess, subset) processes = [] for signum, signature in enumerate(signaturecollection.signatures, start=1): p = multiprocessing.Process(target=process_reference, args=(outputdirectory, signature, array, imageproperties, startDOY, doyinterval, bestguess, ndvalue), kwargs={"subset": subset, "fitmthd": fitmethod, "meantype": meantype, "thresh": threshold, "bounds": bounds}) #TODO: Problem with joining/starting processes--original thread closes before others are completed -- believe this is now fixed. p.start() processes.append(p) if len(processes) == workers: for p in processes: p.join() processes.remove(p) for p in processes: p.join() except Exception as e: import traceback exc_type, exc_value, exc_traceback = sys.exc_info() print(e) traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout) finally: print(dt.now() - start)
def build_multiband_image(rootDIR, outName, newfoldername, find, drivercode, ndvalue, outputdir=None): """ ##Set Args## rootdirectory = "/Users/phoetrymaster/Documents/School/Geography/Thesis/Data/MODIS_KANSAS_2012/" outputfilename = "test" newfoldername = "kansas" VItofind = "EVI" drivercode = "ENVI" nodatavalue = -3000 #projection = "PROJCS[\"Sinusoidal\",GEOGCS[\"GCS_Undefined\",DATUM[\"D_Undefined\", SPHEROID[\"User_Defined_Spheroid\",6371007.181,0.0]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\", 0.017453292519943295]],PROJECTION[\"Sinusoidal\"],PARAMETER[\"False_Easting\",0.0], PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",0.0],UNIT[\"Meter\",1.0]]" sys.exit(build_multiband_image(rootdirectory, outputfilename, newfoldername, VItofind, drivercode, nodatavalue) """ #TODO docstrings if outputdir is None: outputdir = rootDIR outdir = create_output_dir(outputdir, newfoldername) print "\nOutputting files to : {0}".format(outdir) print "\nFinding HDF files in directory/subfolders: {0}".format(rootDIR) hdfs = find_files(rootDIR, ".hdf") print "\tFound {0} files.".format(len(hdfs)) print "\nGetting images to process of type {0}...".format(find) toprocess = [] for hdf in hdfs: sds = get_hdf_subdatasets(hdf) for ds in sds: if find.upper() in ds[1].upper(): toprocess.append(ds[0]) print "\t\t{0}".format(ds[0]) bands = len(toprocess) print "\tFound {0} images of type {1}.".format(bands, find) #print "\nGetting output parameters..." #rows, cols, datatype, geotransform, projection = open_image(toprocess[0]) #print "\tParameters: rows: {0}, cols: {1}, datatype: {2}, projection: {3}.".format(rows, cols, datatype, projection) outfile = os.path.join(outdir, outName) print "\nOutput file is: {0}".format(outfile) ## Create output file from first file to process ## template = openImage(toprocess[0]) templateproperties = gdalProperties(template) outds = copySchemaToNewImage(templateproperties, outfile, numberofbands=bands, drivername=drivercode) template = "" del template print "\tCreated output file." print"\nAdding bands to output file..." for i in range(0, bands): print "\tProcessing band {0} of {1}...".format(i + 1, bands) print toprocess[i] image = openImage(toprocess[i]) band = image.GetRasterBand(1) outband = outds.GetRasterBand(i + 1) print "\t\tReading band data to array..." data = band.ReadAsArray(0, 0, templateproperties.cols, templateproperties.rows) print "\t\tWriting band data to output band..." outband.WriteArray(data, 0, 0) outband.SetNoDataValue(ndvalue) outband.FlushCache() outband = "" del data, outband band = "" image = "" print "\tFinished adding bands to output file." outds = "" del outds print "\nProcess completed."
def clip_and_mask_raster_with_shapefile(inraster, shapefile, outraster): """ """ # TODO Docstring from PIL import Image, ImageDraw raster = openImage(inraster) raster_properties = gdalProperties(raster) rasterwkt = raster.GetProjectionRef() oSRSop = osr.SpatialReference() oSRSop.ImportFromWkt(rasterwkt) shpextent, shppoints = read_shapefile_to_points(shapefile, oSRSop) points = [] for p in xrange(shppoints.GetPointCount()): points.append(shppoints.GetPoint(p)) pnts = numpy.array(points).transpose() cornerpnts = [(shpextent[0], shpextent[3]), # top left (shpextent[1], shpextent[2])] # bottom right # TODO change this to use the function from vectorFunctions pixel, line = world2Pixel(raster_properties.geotransform, pnts[0], pnts[1]) rasterPoly = Image.new("L", (raster.RasterXSize, raster.RasterYSize), 1) rasterize = ImageDraw.Draw(rasterPoly) listdata = [(pixel[i], line[i]) for i in xrange(len(pixel))] rasterize.polygon(listdata, 0) mask = 1 - PIL_image_to_array(rasterPoly) # find extent of new image by getting corner coords in image and subtract mins from maxes pxcoords = get_px_coords_from_geographic_coords(raster_properties, cornerpnts) ymin, xmin = pxcoords[0] ymax, xmax = pxcoords[1] xextent = xmax - xmin yextent = ymax - ymin geotransform_coords = get_geographic_coords_from_px_coords(raster_properties, [pxcoords[0]])[0] newgeotransform = list(raster_properties.geotransform) newgeotransform[0], newgeotransform[3] = geotransform_coords[0], geotransform_coords[1] outds = copySchemaToNewImage(raster_properties, outraster, cols=xextent, rows=yextent, geotransform=newgeotransform) for i in range(1, raster_properties.bands + 1): band = raster.GetRasterBand(i) outband = outds.GetRasterBand(i) nodatavalue = band.GetNoDataValue() data = band.ReadAsArray(xmin, ymin, xextent, yextent) data[mask[ymin:ymax, xmin:xmax] == 0] = raster_properties.nodata outband.WriteArray(data, 0, 0) outband.SetNoDataValue(nodatavalue) outband.FlushCache() del data, outband, band raster = "" outds = "" return outraster
def classify_and_assess_accuracy(outputdir, cropimgpath, searchstringsvals, filevalist, nodata, thresholdsandlength, classifiedimagename=None, numberofprocesses=4): """ """ #TODO Docstring #from multiprocessing import Pool #pool = Pool(numberofprocesses) if classifiedimagename is None: today = dt.now() classifiedimagename = today.strftime("%Y-%m-%d_%H%M_") + os.path.splitext(os.path.basename(cropimgpath))[0] classificationimage = os.path.join(outputdir, classifiedimagename + ".tif") accuracyimage = os.path.join(outputdir, classifiedimagename + "_accuracy.tif") accuracyreport = os.path.join(outputdir, classifiedimagename + ".txt") #np.set_printoptions(threshold=np.nan) # For debug: Makes numpy print whole contents of an array. #Crop image is constant for all iterations cropimg = openImage(cropimgpath) cropimgproperties = gdalProperties(cropimg) croparray = read_image_into_array(cropimg) cropimg = None arraylist = [(read_image_into_array(openImage(f[0])), f[1]) for f in filevalist] # fit images with crop vals writestring = "The fit rasters and truth values used for this classification process are:\n" for f in filevalist: writestring = writestring + "\t{0}\t{1}\n".format(f[0], f[1]) writestring = writestring + "\n" bestacc = 0 bestthresh = None thresholdlist, lengthofthresholdlist = thresholdsandlength try: if lengthofthresholdlist == 1: writestring = writestring + "\n\n**Only using a single threshold value--not iterating.**\n\n" bestthresh = thresholdlist[0] else: #TODO: Refactor to allow use of multiprocessing.Pool.map -- need to reason about the output/logging for thresh in thresholdlist: start = dt.now() accuracy, classification, outstring = classify_with_threshold(croparray, arraylist, searchstringsvals, thresh, nodata, cropimgproperties.nodata) writestring = writestring + outstring if accuracy > bestacc: bestacc = accuracy bestthresh = thresh elapsed = dt.now() - start toprint = [thresh, "{}:{}".format(elapsed.seconds, str(elapsed.microseconds).zfill(6)), accuracy, bestacc, bestthresh] width = (6 * len(arraylist)) sys.stdout.write("Thresh: {: <{width}} Time: {} Acc: {: <14} Best: {: <14} at {}\r".format(*toprint, width=width)) sys.stdout.flush() except Exception as e: import traceback exc_type, exc_value, exc_traceback = sys.exc_info() print e traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout) finally: accuracy, classificationarray, outstring = classify_with_threshold(croparray, arraylist, searchstringsvals, bestthresh, nodata, cropimgproperties.nodata) writestring = writestring + outstring accuracyarray = find_correct_incorrect_array(croparray, classificationarray, ndvalue=nodata, truthndvalue=cropimgproperties.nodata) with open(accuracyreport, 'w') as text: text.write("Classification using fit images from {0}\n\n".format(os.path.dirname(filevalist[0][0]))) text.write("{0}\nBest:\n{1} {2}".format(writestring, bestthresh, accuracy)) print("\n{0}, {1}".format(bestthresh, accuracy)) driver = gdal.GetDriverByName("ENVI") driver.Register() write_output_image(cropimgproperties, classificationimage, classificationarray, nodata) write_output_image(cropimgproperties, accuracyimage, accuracyarray, nodata) print("outputted") return 0