Commit 6a9bfeca authored by Jay's avatar Jay
Browse files

Updates for PR comments

parent 1ba9d438
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -213,7 +213,9 @@ def main(): # pragma: no cover
    args = vars(parse_args())
    # set up the logger
    logging.basicConfig(level=os.environ.get("AUTOCNET_LOGLEVEL", "INFO"))
    # Get the message
    # Get the message; 30s timeout should be long enough to handle minor
    # network issues or congestion without holding onto cluster resources
    # for an undue amount of time.
    queue = StrictRedis(host=args['host'], port=args['port'], db=0,
                        socket_timeout=30, socket_connect_timeout=30)
    manage_messages(args, queue)
+26 −4
Original line number Diff line number Diff line
@@ -805,6 +805,7 @@ def subpixel_register_point_smart(point,
                                  chooser='subpixel_register_point_smart',
                                  verbose=False,
                                  func=pattern_match,
                                  maximum_affine_reprojective_error=1.0,
                                  ncg=None):

    """
@@ -882,7 +883,8 @@ def subpixel_register_point_smart(point,
                             size_y=match_kwargs['image_size'][1])
        try:
            baseline_affine = estimate_local_affine(moving_roi,
                                                    reference_roi)
                                                    reference_roi,
                                                    maximum_affine_reprojective_error)
        except Exception as e:
            log.exception(e)
            m = {'id': measure.id,
@@ -1121,6 +1123,7 @@ def validate_candidate_measure(point,
                               node_cache,
                               parameters=[],
                               func=pattern_match,
                               maximum_affine_reprojective_error=1.0,
                               **kwargs):
    """
    Compute the matching distances, matching the reference measure to the measure
@@ -1183,7 +1186,9 @@ def validate_candidate_measure(point,
                            buffer=20)
    
    try:
        baseline_affine = estimate_local_affine(moving_roi, reference_roi)
        baseline_affine = estimate_local_affine(moving_roi, 
                                                reference_roi,
                                                maximum_affine_reprojective_error)
    except:
       log.error('Unable to transform image to reference space. Likely too close to the edge of the non-reference image. Setting ignore=True')
       return [np.inf] * len(parameters)
@@ -1220,6 +1225,7 @@ def smart_register_point(point,
                         parameters=[], 
                         shared_kwargs={}, 
                         valid_reprojection_distance=1.5, 
                         maximum_affine_reprojective_error=1.0,
                         ncg=None):
    """
    The entry func for the smart subpixel registration code. This is the user
@@ -1256,6 +1262,12 @@ def smart_register_point(point,
                                  measures matched from the moving image to the reference image with a 
                                  distance less than this value in pixels are considered valid. Default: 1.1 

    maximum_affine_reprojective_error: float
                                       reprojective errors less than or equal to this value (default 1.0) are
                                       masked and removed from affine transform estimations. If less than 3 points
                                       are found, affine estimation will fail. This value can be used to loosen
                                       the reprojective constraint estimating the affine transform between 
                                       images.
    Returns
    -------
    measures_to_update : list
@@ -1269,12 +1281,22 @@ def smart_register_point(point,
    if not isinstance(point, Points):
        point = get_point(ncg, session, point)
        
    measure_results, node_cache = subpixel_register_point_smart(point, session, ncg=ncg, parameters=parameters, **shared_kwargs)
    measure_results, node_cache = subpixel_register_point_smart(point, 
                                                                session, 
                                                                ncg=ncg, 
                                                                parameters=parameters, 
                                                                maximum_affine_reprojective_error=maximum_affine_reprojective_error
                                                                **shared_kwargs)
    measures_to_update, measures_to_set_false = decider(measure_results)
    log.info(f'Found {len(measures_to_update)} measures that found subpixel registration consensus.')
    # Validate that the new position has consensus
    for measure in measures_to_update:
        reprojection_distances = validate_candidate_measure(point, measure, node_cache, parameters=parameters, **shared_kwargs)
        reprojection_distances = validate_candidate_measure(point, 
                                                            measure, 
                                                            node_cache, 
                                                            parameters=parameters, 
                                                            maximum_affine_reprojective_error=maximum_affine_reprojective_error,
                                                            **shared_kwargs)
        log.info(f'Validation Distance Boolean: {np.array(reprojection_distances) < valid_reprojection_distance}')
        if np.sum(np.array(reprojection_distances) < valid_reprojection_distance) < 2:
            log.info(f"Measure {measure['id']} failed validation. Setting ignore=True for this measure.")
+14 −6
Original line number Diff line number Diff line
from contextlib import nullcontext
import time
import logging
import warnings

import shapely
import json
@@ -121,8 +120,12 @@ def find_interesting_point(nodes, lon, lat, size=71, **kwargs):

        # Extract ORB features in a sub-image around the desired point
        image_roi = roi.Roi(node.geodata, sample, line)
        try:
            roi_array = image_roi.clip(size_x=size, size_y=size) # Units are pixels for the array

        except Exception as e:
            logging.debug(f'Failed to clip ROI with exception: {e}.')
            log.warn(f'Unable to clip ROI for {node}.')
            continue
        # Check if the image is valid and could be used as the reference
        if not is_valid_lroc_image(roi_array):
            log.info('Failed to find interesting features in image due to poor quality image.')
@@ -223,7 +226,7 @@ def place_points_in_overlap(overlap,
    candidate_points = compgeom.distribute_points_in_geom(geom, ratio_size=ratio_size, **distribute_points_kwargs, **kwargs)
    logging.debug(f'Found {len(candidate_points)} in overlap {overlap.id}.')
    if not candidate_points.any():
        warnings.warn(f'Failed to distribute points in overlap {overlap.id}')
        log.warn(f'Failed to distribute points in overlap {overlap.id}')
        return []
    log.info(f'Have {len(candidate_points)} potential points to place in overlap {overlap.id}.')
    
@@ -344,8 +347,13 @@ def place_points_in_image(image,
            continue

        # Extract ORB features in a sub-image around the desired point
        try:
            image_roi = roi.Roi(node.geodata, sample, line)
            roi_array = image_roi.clip(size_x=size, size_y=size)
        except Exception as e:
            log.debug(f'Failed to clip ROI with exception: {e}.')
            log.warn(f'Unable to clip ROI for {node}.')
            continue
        interesting = extract_most_interesting(roi_array)

        # kps are in the image space with upper left origin and the roi
+26 −19
Original line number Diff line number Diff line
@@ -35,7 +35,8 @@ def estimate_affine_from_sensors(reference_image,
                                 bcenter_x,
                                 bcenter_y,
                                 size_x=40,
                                 size_y=40):
                                 size_y=40,
                                 maximum_affine_reprojective_error=1.0):
    """
    Using the a priori sensor model, project corner and center points from the reference_image into
    the moving_image and use these points to estimate an affine transformation.
@@ -54,6 +55,12 @@ def estimate_affine_from_sensors(reference_image,
                half-height of the subimage used in the affine transformation
    size_y:     int
                half-width of the subimage used in affine transformation
    maximum_affine_reprojective_error: float
                reprojective errors less than or equal to this value (default 1.0) are
                masked and removed from affine transform estimations. If less than 3 points
                are found, affine estimation will fail. This value can be used to loosen
                the reprojective constraint estimating the affine transform between 
                images.
                
    Returns
    -------
@@ -72,20 +79,9 @@ def estimate_affine_from_sensors(reference_image,
    base_stopx = int(bcenter_x + size_x)
    base_stopy = int(bcenter_y + size_y)
    
    match_size = reference_image.raster_size

    # for now, require the entire window resides inside both cubes.
    # if base_stopx > match_size[0]:
    #     raise Exception(f"Window: {base_stopx} > {match_size[0]}, center: {bcenter_x},{bcenter_y}")
    # if base_startx < 0:
    #     raise Exception(f"Window: {base_startx} < 0, center: {bcenter_x},{bcenter_y}")
    # if base_stopy > match_size[1]:
    #     raise Exception(f"Window: {base_stopy} > {match_size[1]}, center: {bcenter_x},{bcenter_y} ")
    # if base_starty < 0:
    #     raise Exception(f"Window: {base_starty} < 0, center: {bcenter_x},{bcenter_y}")
    
    x_coords = [base_startx, base_startx, base_stopx, base_stopx, bcenter_x]
    y_coords = [base_starty, base_stopy, base_stopy, base_starty, bcenter_y]
    
    # Dispatch to the sensor to get the a priori pixel location in the input image
    lons, lats = reference_image.sensormodel.sampline2lonlat(x_coords, y_coords, allowoutside=True)
    xs, ys = moving_image.sensormodel.lonlat2sampline(lons, lats, allowoutside=True)
@@ -103,13 +99,14 @@ def estimate_affine_from_sensors(reference_image,
        raise ValueError(f'Unable to find enough points to compute an affine transformation. Found {len(dst_gcps)} points, but need at least 3.')

    log.debug(f'Number of GCPs for affine estimation: {len(dst_gcps)}')
    
    affine = tf.AffineTransform()
    # Estimate the affine twice. The first time to get an initial estimate
    # and the second time to drop points with an estimated reprojection 
    # error greater than or equal to 0.1px.
    # error greater than the passed maximum_affine_reprojective_error.
    affine.estimate(np.array(base_gcps), np.array(dst_gcps))
    residuals = affine.residuals(np.array(base_gcps), np.array(dst_gcps))
    mask = residuals <= 1
    mask = residuals <= maximum_affine_reprojective_error
    if len(np.array(base_gcps)[mask]) < 3:
        logging.info(f'Affine residuals: {residuals}.')
        raise ValueError(f'Unable to find enough points to compute an affine transformation. Found {len(np.array(dst_gcps)[mask])} points, but need at least 3.')
@@ -122,7 +119,7 @@ def estimate_affine_from_sensors(reference_image,
    return affine


def estimate_local_affine(reference_roi, moving_roi, size_x=60, size_y=60):
def estimate_local_affine(reference_roi, moving_roi, size_x=60, size_y=60, maximum_affine_reprojective_error=1.0):
    """
    Applies the affine transfromation calculated in estimate_affine_from_sensors to the moving region of interest (ROI).
    
@@ -135,7 +132,16 @@ def estimate_local_affine(reference_roi, moving_roi, size_x=60, size_y=60):
    moving_image : autocnet.io.geodataset.AGeoDataset
                   Image that is expected to move around during the matching process, 
                   points are projected onto this image to compute an affine  

    size_x:     int
                half-height of the subimage used in the affine transformation
    size_y:     int
                half-width of the subimage used in affine transformation
    maximum_affine_reprojective_error: float
                reprojective errors less than or equal to this value (default 1.0) are
                masked and removed from affine transform estimations. If less than 3 points
                are found, affine estimation will fail. This value can be used to loosen
                the reprojective constraint estimating the affine transform between 
                images.
    Returns
    -------
    affine
@@ -146,7 +152,8 @@ def estimate_local_affine(reference_roi, moving_roi, size_x=60, size_y=60):
                                                    reference_roi.x, 
                                                    reference_roi.y, 
                                                    size_x=size_x, 
                                                    size_y=size_y)
                                                    size_y=size_y,
                                                    maximum_affine_reprojective_error=1.0)


    # Remove the translation from the transformation. Users of this function should add