diff --git a/CHANGELOG.md b/CHANGELOG.md index 977ffcc26259d3309046e7e04b78bd81f16d66d6..f8604d3a1c0362cfa3d8f9cd1606a3916c1d8560 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,11 @@ heading to indicate that only the bug fixes and security fixes are in the bug fi release. --> ## [Unreleased] +### Added +- Debug logging to `place_points_in_overlap` and `distribute_points_in_geom` to make debugging issues easier. + +### Fixed +- Error in `find_interesting_feature` that was mis-using the ROI API. This bug was introduced in 1.2.0 when the ROI API updated. ## [1.2.0] ### Added diff --git a/autocnet/cg/cg.py b/autocnet/cg/cg.py index 81cec479e399e7973e31aaf4ab19b27bcd05bd6b..2dd2f48fa644dd576633ef93d5012cbf8c548f56 100644 --- a/autocnet/cg/cg.py +++ b/autocnet/cg/cg.py @@ -460,6 +460,7 @@ def distribute_points_in_geom(geom, method="classic", ewpts_func=lambda x: ceil(round(x,1)*5), Session=None, ratio_size=0.1, + min_area=0.004, **kwargs): """ Given a geometry, attempt a basic classification of the shape. @@ -487,10 +488,15 @@ def distribute_points_in_geom(geom, method="classic", ewpts_func : obj Function taking a Number and returning an int + ratio_size : float A number that represent the minimum size the ratio is set at to be considered a sliver. + min_area : float + The minimum area, as measured in the project SRID, + below which points will not be placed and above which + points will be placed. Returns ------- valid : np.ndarray @@ -523,6 +529,9 @@ def distribute_points_in_geom(geom, method="classic", longid = i ratio = short/long + logging.debug(f'Area: {geom.area}') + logging.debug(f'Ratio: {ratio}') + ns = False ew = False valid = [] @@ -536,13 +545,14 @@ def distribute_points_in_geom(geom, method="classic", ew = True # Decision Tree - if ratio < ratio_size and geom.area < 0.01: - # Class: Slivers - ignore. + if ratio < ratio_size and geom.area < min_area: + logging.debug('Ratio check failed.') return np.array([]) - elif geom.area <= 0.004 and ratio >= 0.25: - # Single point at the centroid + elif geom.area <= min_area and ratio >= ratio_size: + logging.debug('Placing a single point.') valid = single_centroid(geom) elif ns==True: + logging.debug('Placing N/S oriented points.') # Class, north/south poly, multi-point nspts = nspts_func(long) ewpts = ewpts_func(short) @@ -551,6 +561,7 @@ def distribute_points_in_geom(geom, method="classic", else: valid = point_distribution_func(geom, nspts, ewpts, Session=Session, **kwargs) elif ew == True: + logging.debug('Placing E/W oriented points.') # Since this is an LS, we should place these diagonally from the 'lower left' to the 'upper right' nspts = ewpts_func(short) ewpts = nspts_func(long) diff --git a/autocnet/matcher/cross_instrument_matcher.py b/autocnet/matcher/cross_instrument_matcher.py index a006b2a8686113e578e02f5502d612edea5c7250..942f8e11703e365f32427adb538cddb65297ea63 100755 --- a/autocnet/matcher/cross_instrument_matcher.py +++ b/autocnet/matcher/cross_instrument_matcher.py @@ -112,12 +112,8 @@ def generate_ground_points(Session, log.warning(f'Line or sample are outside of the base.') continue - image = roi.Roi(ground_mosaic, sample, line, size_x=size[0], size_y=size[1]) - try: - image.clip() - except: - continue - image_roi = image.clipped_array + image = roi.Roi(ground_mosaic, sample, line) + image_roi = image.clip(size_x=size[0], size_y=size[1]) interesting = extract_most_interesting(bytescale(image_roi), extractor_parameters={}, extractor_method='vlfeat') # interesting = extract_most_interesting(bytescale(image_roi), extractor_parameters={'nfeatures':500}, extractor_method='orb') diff --git a/autocnet/spatial/centroids.py b/autocnet/spatial/centroids.py index f5ee41e0c347876a7253d785a7b78526a061e757..f4b8489cebc2627764a8c558703e36cefed7becb 100644 --- a/autocnet/spatial/centroids.py +++ b/autocnet/spatial/centroids.py @@ -186,9 +186,9 @@ def find_intresting_point(nodes, lon, lat, size=71): line = try_line # Extract ORB features in a sub-image around the desired point - image_roi = roi.Roi(node.geodata, sample, line, size_x=size, size_y=size) + image_roi = roi.Roi(node.geodata, sample, line) try: - roi_array = image_roi.clipped_array # Units are pixels for the array + roi_array = image_roi.clip(size_x=size, size_y=size) # Units are pixels for the array except: log.info(f'Failed to find interesting features in image.') continue @@ -199,7 +199,7 @@ def find_intresting_point(nodes, lon, lat, size=71): continue # Extract the most interesting feature in the search window - interesting = extract_most_interesting(image_roi.clipped_array) + interesting = extract_most_interesting(roi_array) if interesting is not None: # We have found an interesting feature and have identified the reference point. diff --git a/autocnet/spatial/overlap.py b/autocnet/spatial/overlap.py index 1ae324cadd57b192cc0355753d2c4ec94559bcb4..f799350132eaab51b12739770672f3d8336f7d27 100644 --- a/autocnet/spatial/overlap.py +++ b/autocnet/spatial/overlap.py @@ -117,12 +117,8 @@ def find_interesting_point(nodes, lon, lat, size=71, **kwargs): line = try_line # Extract ORB features in a sub-image around the desired point - image_roi = roi.Roi(node.geodata, sample, line, size_x=size, size_y=size) - try: - roi_array = image_roi.clipped_array # Units are pixels for the array - except: - log.info(f'Failed to find interesting features in image.') - continue + image_roi = roi.Roi(node.geodata, sample, line) + roi_array = image_roi.clip(size_x=size, size_y=size) # Units are pixels for the array # Check if the image is valid and could be used as the reference if not is_valid_lroc_image(roi_array): @@ -130,7 +126,7 @@ def find_interesting_point(nodes, lon, lat, size=71, **kwargs): continue # Extract the most interesting feature in the search window - interesting = extract_most_interesting(image_roi.clipped_array) + interesting = extract_most_interesting(roi_array) if interesting is not None: # We have found an interesting feature and have identified the reference point. @@ -224,6 +220,7 @@ def place_points_in_overlap(overlap, # Determine the point distribution in the overlap geom geom = overlap.geom 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}') return [] @@ -282,6 +279,7 @@ def place_points_in_overlap(overlap, else: if len(point.measures) >= 2: points_to_commit.append(point) + log.debug(f'Committing: {points_to_commit}') if points_to_commit: with ncg.session_scope() if ncg else nullcontext(session) as session: session.add_all(points_to_commit) @@ -359,12 +357,9 @@ def place_points_in_image(image, continue # Extract ORB features in a sub-image around the desired point - image_roi = roi.Roi(node.geodata, sample, line, size_x=size, size_y=size) - image_roi.clip() - try: - interesting = extract_most_interesting(image.clipped_array) - except: - continue + image_roi = roi.Roi(node.geodata, sample, line) + roi_array = image_roi.clip(size_x=size, size_y=size) + interesting = extract_most_interesting(roi_array) # kps are in the image space with upper left origin and the roi # could be the requested size or smaller if near an image boundary. diff --git a/autocnet/transformation/roi.py b/autocnet/transformation/roi.py index 3776548dc1e0e422fc4ea69a7c0dfd2b04c36f0f..db045ab7dbd025fbb79fea829507a6f108de347d 100644 --- a/autocnet/transformation/roi.py +++ b/autocnet/transformation/roi.py @@ -34,24 +34,9 @@ class Roi(): ndv : float An optional no data value override to set a custom no data value on the ROI. - buffer : int - An integer number of pixels to buffer the read number of pixels from a GeoDataset. This parameter - can be used to ensure that an affinely warped ROI contains only valid data. A buffer too small can - result in no data on one or more edges. - - clip_center : tuple - on instantiation, set to (). When clip is called and the clipped_array - variable is set, the clip_center is set to the center of the, potentially - affine transformed, cliped_array. - - clipped_array : ndarray - After calling the clip method, this is the resulting clipped, and possibly affinely warped - data array. - - warped_array_center : tuple - During clipping, if an affine transformation is provided, the clipped array is warped. The center - of the warped array is not the same as the center of the clipped array. This attribute is the - affine transformation of the clip_center. + center : tuple + The x,y coordinates as a tuple. + affine : object a scikit image affine transformation object that is applied when clipping. The default, identity matrix results in no transformation. diff --git a/autocnet/transformation/tests/test_roi.py b/autocnet/transformation/tests/test_roi.py index 23d7ad2be401d5ea3b9834a89c7ee622db423359..9892e6bb78342bbcde9c1f3801e5738820bfc25e 100644 --- a/autocnet/transformation/tests/test_roi.py +++ b/autocnet/transformation/tests/test_roi.py @@ -60,11 +60,11 @@ def test_extent_computation(x, y, size_arr, size_roi, expected, geodata_c): def test_array_extent_computation(x, y, size_arr, size_roi, buffer, expected, geodata_c): geodata_c.read_array.return_value = np.arange(size_arr[0]*size_arr[1]).reshape(size_arr) - roi = Roi(geodata_c, x, y, size_x=size_roi[0], size_y=size_roi[1], buffer=buffer) - roi.clip() + roi = Roi(geodata_c, x, y) + arr = roi.clip(size_x=size_roi[0], size_y=size_roi[1], buffer=buffer) - assert roi.clipped_array.dtype == np.float32 - assert (roi.clipped_array.shape == np.asarray(size_roi) * 2 + 1).all() + assert roi.arr.dtype == np.float32 + assert (roi.arr.shape == np.asarray(size_roi) * 2 + 1).all() @pytest.mark.parametrize("x, y, x1, y1, xs, ys, size_arr, size_roi, expected",[ (50, 50, 50, 50, -5, -5, (100, 100), (10, 10), (45, 45)),