def matchLocally(mission, roll, frame, cursor, georefDb, sourceImagePath): '''Performs image alignment to an already aligned ISS image''' # Load new frame info targetFrameData = source_database.FrameInfo() targetFrameData.loadFromDb(cursor, mission, roll, frame) targetFrameData = computeFrameInfoMetersPerPixel(targetFrameData) # Find candidate names to match to possibleNearbyMatches = findNearbyResults(targetFrameData, cursor, georefDb) if not possibleNearbyMatches: print 'Did not find any potential local matches!' for (otherFrame, ourResult) in possibleNearbyMatches: print 'Trying local match with frame: ' + str(otherFrame.frame) # Get path to other frame image otherImagePath, exifSourcePath = source_database.getSourceImage(otherFrame) source_database.clearExif(exifSourcePath) otherTransform = ourResult[0] # This is still in the google projected format #print 'otherTransform = ' + str(otherTransform.matrix) print 'New image mpp = ' + str(targetFrameData.metersPerPixel) print 'Local match image mpp = ' + str(otherFrame.metersPerPixel) # If we could not estimate the MPP value of the new image, guess that it is the same as # the local reference image we are about to try. thisMpp = targetFrameData.metersPerPixel if not thisMpp: thisMpp = otherFrame.metersPerPixel print 'Attempting to register image...' (imageToProjectedTransform, imageToGdcTransform, confidence, imageInliers, gdcInliers, refMetersPerPixel) = \ register_image.register_image(sourceImagePath, otherFrame.centerLon, otherFrame.centerLat, thisMpp, targetFrameData.date, refImagePath =otherImagePath, referenceGeoTransform=otherTransform, refMetersPerPixelIn =otherFrame.metersPerPixel, debug=options.debug, force=True, slowMethod=False) if not options.debug: os.remove(otherImagePath) # Clean up the image we matched against # Quit once we get a good match if confidence == registration_common.CONFIDENCE_HIGH: print 'High confidence match!' # Convert from the image-to-image GCPs to the reference image GCPs # located in the new image. refFrameGdcInliers = ourResult[3] # TODO: Clean this up! (width, height) = IrgGeoFunctions.getImageSize(sourceImagePath) print '\n\n' print refFrameGdcInliers print '\n\n' (imageInliers, gdcInliers) = registration_common.convertGcps(refFrameGdcInliers, imageToProjectedTransform, width, height) print imageInliers print '\n\n' # If none of the original GCPs fall in the new image, don't use this alignment result. # - We could use this result, but we don't in order to maintain accuracy standards. if imageInliers: print 'Have inliers' print otherFrame return (imageToProjectedTransform, imageToGdcTransform, confidence, imageInliers, gdcInliers, refMetersPerPixel, otherFrame) else: print 'Inliers out of bounds!' # Match failure, return junk values return (registration_common.getIdentityTransform(), registration_common.getIdentityTransform(), registration_common.CONFIDENCE_NONE, [], [], 9999, None)
def register_image(imagePath, centerLon, centerLat, metersPerPixel, imageDate, refImagePath=None, referenceGeoTransform=None, refMetersPerPixelIn=None, debug=False, force=False, slowMethod=False): '''Attempts to geo-register the provided image. Returns a transform from image coordinates to projected meters coordinates. Also returns an evaluation of how likely the registration is to be correct.''' if not (os.path.exists(imagePath)): raise Exception('Input image path does not exist!') with TemporaryDirectory() as myWorkDir: # Set up paths in a temporary directory if not debug: workDir = myWorkDir else: # In debug mode, create a more permanent work location. workDir = os.path.splitext(imagePath)[0] if not os.path.exists(workDir): os.mkdir(workDir) workPrefix = workDir + '/work' #print workDir if not refImagePath: # Fetch the reference image refImagePath = os.path.join(workDir, 'ref_image.tif') refImageLogPath = os.path.join(workDir, 'ref_image_info.tif') if not os.path.exists(refImagePath): (percentValid, refMetersPerPixel) = ImageFetcher.fetchReferenceImage.fetchReferenceImage( centerLon, centerLat, metersPerPixel, imageDate, refImagePath) # Log the metadata handle = open(refImageLogPath, 'w') handle.write(str(percentValid) + '\n' + str(refMetersPerPixel)) handle.close() else: # Load the reference image metadata that we logged earlier handle = open(refImageLogPath, 'r') fileText = handle.read() handle.close() lines = fileText.split('\n') percentValid = float(lines[0]) refMetersPerPixel = float(lines[1]) else: # The user provided a reference image refMetersPerPixel = refMetersPerPixelIn # In this case the user must provide an accurate value! if not os.path.exists(refImagePath): raise Exception('Provided reference image path does not exist!') # TODO: Reduce the input image to the resolution of the reference image! # The reference image may be lower resolution than the input image, in which case # we will need to perform image alignment at the lower reference resolution. inputScaling = metersPerPixel / refMetersPerPixel print 'metersPerPixel = ' + str(metersPerPixel) print 'refMetersPerPixel = ' + str(refMetersPerPixel) print 'inputScaling = ' + str(inputScaling) # Try to align to the reference image # - The transform is from image to refImage (imageToRefImageTransform, confidence, imageInliers, refInliers) = \ registration_common.alignScaledImages(imagePath, refImagePath, inputScaling, workPrefix, force, debug, slowMethod) # If we failed, just return dummy information with zero confidence. if (confidence == registration_common.CONFIDENCE_NONE): return (registration_common.getIdentityTransform(), registration_common.getIdentityTransform(), registration_common.CONFIDENCE_NONE, [], [], 0) # Convert the transform into a pixel-->Projected coordinate transform (imageToProjectedTransform, imageToGdcTransform, refImageToGdcTransform) = \ convertTransformToGeo(imageToRefImageTransform, imagePath, refImagePath, referenceGeoTransform) # For each input image inlier, generate the world coordinate. gdcInliers = [] for pix in refInliers: gdcCoordinate = refImageToGdcTransform.forward(pix) gdcInliers.append(gdcCoordinate) return (imageToProjectedTransform, imageToGdcTransform, confidence, imageInliers, gdcInliers, refMetersPerPixel)
def processFrame(options, frameDbData, searchNearby=False): '''Process a single specified frame. Returns True if we attempted to perform image alignment and did not hit an exception.''' try: georefDb = georefDbWrapper.DatabaseLogger() # Increase the error slightly for chained image transforms LOCAL_TRANSFORM_ERROR_ADJUST = 1.10 sourceImagePath, exifSourcePath = source_database.getSourceImage(frameDbData, overwrite=True) if not options.debug: source_database.clearExif(exifSourcePath) try: # If requested, get nearby previously matched frames to compare to. if searchNearby: sourceDb = sqlite3.connect(settings.DB_PATH) sourceDbCursor = sourceDb.cursor() (imageToProjectedTransform, imageToGdcTransform, confidence, imageInliers, gdcInliers, refMetersPerPixel, otherFrame) = \ matchLocally(frameDbData.mission, frameDbData.roll, frameDbData.frame, sourceDbCursor, georefDb, sourceImagePath) if otherFrame: matchedImageId = otherFrame.getIdString() else: matchedImageId = 'None' sourceDb.close() else: # Try to register the image to Landsat print 'Attempting to register image...' (imageToProjectedTransform, imageToGdcTransform, confidence, imageInliers, gdcInliers, refMetersPerPixel) = \ register_image.register_image(sourceImagePath, frameDbData.centerLon, frameDbData.centerLat, frameDbData.metersPerPixel, frameDbData.date, refImagePath=None, debug=False, force=True, slowMethod=True) matchedImageId = 'Landsat' except Exception as e: print 'Computing transform for frame '+frameDbData.getIdString()+', caught exception: ' + str(e) print "".join(traceback.format_exception(*sys.exc_info())) print 'Logging the result as no-confidence.' confidence = registration_common.CONFIDENCE_NONE imageInliers = [] gdcInliers = [] matchedImageId = 'NA' refMetersPerPixel = 999 imageToProjectedTransform = registration_common.getIdentityTransform() imageToGdcTransform = registration_common.getIdentityTransform() # A very rough estimation of localization error at the inlier locations! errorMeters = refMetersPerPixel * 1.5 # Convert into format that our DB is looking for. sourceDateTime = frameDbData.getMySqlDateTime() if confidence > registration_common.CONFIDENCE_NONE: (centerLon, centerLat) = computeCenterGdcCoord(imageToGdcTransform, frameDbData) else: (centerLon, centerLat) = (-999, -999) # Log the results to our database centerPointSource = frameDbData.centerPointSource georefDb.addResult(frameDbData.mission, frameDbData.roll, frameDbData.frame, imageToProjectedTransform, imageToGdcTransform, centerLon, centerLat, refMetersPerPixel, confidence, imageInliers, gdcInliers, matchedImageId, sourceDateTime, centerPointSource) # This tool just finds the interest points and computes the transform, # a different tool will actually write the output images. if not options.debug: os.remove(sourceImagePath) # Clean up the source image print ('Finished processing frame ' + frameDbData.getIdString() + ' with confidence ' + registration_common.CONFIDENCE_STRINGS[confidence]) return confidence except Exception as e: print 'Processing frame '+frameDbData.getIdString()+', caught exception: ' + str(e) print "".join(traceback.format_exception(*sys.exc_info())) #raise Exception('FAIL') return 0