Loading autocnet/matcher/subpixel.py +30 −17 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ import cv2 from skimage import transform as tf from skimage import registration from skimage import filters from skimage.util import img_as_float32 from scipy import fftpack from matplotlib import pyplot as plt Loading Loading @@ -523,7 +524,7 @@ def subpixel_template_classic(sx, sy, dx, dy, if (s_image is None) or (d_template is None): return None, None, None, None shift_x, shift_y, metrics, corrmap = func(d_template.astype('float32'), s_image.astype('float32'), **kwargs) shift_x, shift_y, metrics, corrmap = func(img_as_float32(d_template), img_as_float32(s_image), **kwargs) if shift_x is None: return None, None, None, None # Apply the shift and return Loading Loading @@ -1521,7 +1522,6 @@ def subpixel_register_point(pointid, for measure in measures: res = session.query(Images).filter(Images.id == measure.imageid).one() nodes[measure.imageid] = NetworkNode(node_id=measure.imageid, image_path=res.path) session.expunge_all() resultlog = [] Loading Loading @@ -2172,41 +2172,46 @@ def subpixel_register_point_smart(pointid, t1 = time.time() with ncg.session_scope() as session: # Order by is important here because the measures get ids in sequential order when initially placed # and the reference_index is positionally linked to the ordered vector of measures. measures = session.query(Measures).filter(Measures.pointid == pointid).order_by(Measures.id).all() point = session.query(Points).filter(Points.id == pointid).one() reference_index = point.reference_index t2 = time.time() print(f'Query took {t2-t1} seconds to find the measures and reference measure.') # Get the reference measure. Previously this was index 0, but now it is a database tracked attribute # Get the reference measure to instantiate the source node. All other measures will # match to the source node. source = measures[reference_index] reference_index_id = source.imageid print(f'Using measure {source.id} on image {source.imageid}/{source.serial} as the reference.') print(f'Measure reference index is: {reference_index}') source.template_metric = 1 source.template_shift = 0 source.phase_error = 0 source.phase_diff = 0 source.phase_shift = 0 sourceid = source.imageid sourceres = session.query(Images).filter(Images.id == sourceid).one() source_node = NetworkNode(node_id=sourceid, image_path=sourceres.path) source_node.parent = ncg t3 = time.time() print(f'Query for the image to use as source took {t3-t2} seconds.') print(f'Attempting to subpixel register {len(measures)-1} measures for point {pointid}') # Build a node cache so that this is an encapsulated database call. Then nodes # can be pulled from the lookup sans database. nodes = {} for measure in measures: res = session.query(Images).filter(Images.id == measure.imageid).one() nodes[measure.imageid] = NetworkNode(node_id=measure.imageid, image_path=res.path) nn = NetworkNode(node_id=measure.imageid, image_path=res.path) nn.parent = ncg nodes[measure.imageid] = nn session.expunge_all() t3 = time.time() print(f'Query for the image to use as source took {t3-t2} seconds.') print(f'Attempting to subpixel register {len(measures)-1} measures for point {pointid}') print(nodes) # Set the reference image source_node = nodes[reference_index_id] print(f'Source: sample: {source.sample} | line: {source.line}') resultlog = [] updated_measures = [] for i, measure in enumerate(measures): # If this is the reference node, do not attempt to match it. if i == reference_index: continue Loading Loading @@ -2270,8 +2275,12 @@ def subpixel_register_point_smart(pointid, updated_measures.append([None, None, m]) continue base_roi = img_as_float32(base_roi) dst_roi = img_as_float32(dst_roi) baseline_mi = mutual_information(base_roi, dst_roi) # Refactor this call to module result = cv2.matchTemplate(base_roi, dst_roi, method=cv2.TM_CCOEFF_NORMED) baseline_corr = result[0][0] Loading @@ -2296,6 +2305,10 @@ def subpixel_register_point_smart(pointid, base_roi = roi.Roi(base_arr, source.apriorisample, source.aprioriline, size_x=size_x, size_y=size_y).clip() dst_roi = roi.Roi(dst_arr, x, y, size_x=size_x, size_y=size_y).clip() #TODO: When refactored, all this type conversion should happen in the ROI object. base_roi = img_as_float32(base_roi) dst_roi = img_as_float32(dst_roi) mi_metric = mutual_information(base_roi, dst_roi) if mi_metric is None: Loading autocnet/spatial/overlap.py +15 −6 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ def place_points_in_overlaps(size_threshold=0.0007, if not ncg.Session: raise BrokenPipeError('This func requires a database session from a NetworkCandidateGraph.') for overlap in Overlay.overlapping_larger_than(size_threshold, Session): for overlap in Overlay.overlapping_larger_than(size_threshold, ncg.Session): if overlap.intersections == None: continue place_points_in_overlap(overlap, Loading @@ -93,7 +93,7 @@ def place_points_in_overlap(overlap, use_cache=False, **kwargs): """ Place points into an overlap geometry by back-projecing using sensor models. Place points into an overlap geometry by back-projecting using sensor models. The DEM specified in the config file will be used to calculate point elevations. Parameters Loading @@ -102,7 +102,7 @@ def place_points_in_overlap(overlap, An autocnet.io.db.model Overlay model instance. identifier: str The tag used to distiguish points laid down by this function. The tag used to distinguish points laid down by this function. cam_type : str options: {"csm", "isis"} Loading Loading @@ -292,16 +292,25 @@ def place_points_in_overlap(overlap, # Compute ground point to back project into measurtes gnd = csmapi.EcefCoord(x, y, z) for node in nodes: for current_index, node in enumerate(nodes): if cam_type == "csm": image_coord = node.camera.groundToImage(gnd) sample, line = image_coord.samp, image_coord.line if cam_type == "isis": # If this try/except fails, then the reference_index could be wrong because the length # of the measures list is different than the length of the nodes list that was used # to find the most interesting feature. try: sample, line = isis.ground_to_image(node["image_path"], updated_lon, updated_lat) except CalledProcessError as e: if 'Requested position does not project in camera model' in e.stderr: print(f'interesting point ({updated_lon},{updated_lat}) does not project to image {node["image_path"]}') # If the current_index is greater than the reference_index, the change in list size does # not impact the positional index of the reference. If current_index is less than the # reference_index, then the reference_index needs to de-increment by one for each time # a measure fails to be placed. if current_index < reference_index: reference_index -= 1 continue point.measures.append(Measures(sample=sample, Loading Loading
autocnet/matcher/subpixel.py +30 −17 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ import cv2 from skimage import transform as tf from skimage import registration from skimage import filters from skimage.util import img_as_float32 from scipy import fftpack from matplotlib import pyplot as plt Loading Loading @@ -523,7 +524,7 @@ def subpixel_template_classic(sx, sy, dx, dy, if (s_image is None) or (d_template is None): return None, None, None, None shift_x, shift_y, metrics, corrmap = func(d_template.astype('float32'), s_image.astype('float32'), **kwargs) shift_x, shift_y, metrics, corrmap = func(img_as_float32(d_template), img_as_float32(s_image), **kwargs) if shift_x is None: return None, None, None, None # Apply the shift and return Loading Loading @@ -1521,7 +1522,6 @@ def subpixel_register_point(pointid, for measure in measures: res = session.query(Images).filter(Images.id == measure.imageid).one() nodes[measure.imageid] = NetworkNode(node_id=measure.imageid, image_path=res.path) session.expunge_all() resultlog = [] Loading Loading @@ -2172,41 +2172,46 @@ def subpixel_register_point_smart(pointid, t1 = time.time() with ncg.session_scope() as session: # Order by is important here because the measures get ids in sequential order when initially placed # and the reference_index is positionally linked to the ordered vector of measures. measures = session.query(Measures).filter(Measures.pointid == pointid).order_by(Measures.id).all() point = session.query(Points).filter(Points.id == pointid).one() reference_index = point.reference_index t2 = time.time() print(f'Query took {t2-t1} seconds to find the measures and reference measure.') # Get the reference measure. Previously this was index 0, but now it is a database tracked attribute # Get the reference measure to instantiate the source node. All other measures will # match to the source node. source = measures[reference_index] reference_index_id = source.imageid print(f'Using measure {source.id} on image {source.imageid}/{source.serial} as the reference.') print(f'Measure reference index is: {reference_index}') source.template_metric = 1 source.template_shift = 0 source.phase_error = 0 source.phase_diff = 0 source.phase_shift = 0 sourceid = source.imageid sourceres = session.query(Images).filter(Images.id == sourceid).one() source_node = NetworkNode(node_id=sourceid, image_path=sourceres.path) source_node.parent = ncg t3 = time.time() print(f'Query for the image to use as source took {t3-t2} seconds.') print(f'Attempting to subpixel register {len(measures)-1} measures for point {pointid}') # Build a node cache so that this is an encapsulated database call. Then nodes # can be pulled from the lookup sans database. nodes = {} for measure in measures: res = session.query(Images).filter(Images.id == measure.imageid).one() nodes[measure.imageid] = NetworkNode(node_id=measure.imageid, image_path=res.path) nn = NetworkNode(node_id=measure.imageid, image_path=res.path) nn.parent = ncg nodes[measure.imageid] = nn session.expunge_all() t3 = time.time() print(f'Query for the image to use as source took {t3-t2} seconds.') print(f'Attempting to subpixel register {len(measures)-1} measures for point {pointid}') print(nodes) # Set the reference image source_node = nodes[reference_index_id] print(f'Source: sample: {source.sample} | line: {source.line}') resultlog = [] updated_measures = [] for i, measure in enumerate(measures): # If this is the reference node, do not attempt to match it. if i == reference_index: continue Loading Loading @@ -2270,8 +2275,12 @@ def subpixel_register_point_smart(pointid, updated_measures.append([None, None, m]) continue base_roi = img_as_float32(base_roi) dst_roi = img_as_float32(dst_roi) baseline_mi = mutual_information(base_roi, dst_roi) # Refactor this call to module result = cv2.matchTemplate(base_roi, dst_roi, method=cv2.TM_CCOEFF_NORMED) baseline_corr = result[0][0] Loading @@ -2296,6 +2305,10 @@ def subpixel_register_point_smart(pointid, base_roi = roi.Roi(base_arr, source.apriorisample, source.aprioriline, size_x=size_x, size_y=size_y).clip() dst_roi = roi.Roi(dst_arr, x, y, size_x=size_x, size_y=size_y).clip() #TODO: When refactored, all this type conversion should happen in the ROI object. base_roi = img_as_float32(base_roi) dst_roi = img_as_float32(dst_roi) mi_metric = mutual_information(base_roi, dst_roi) if mi_metric is None: Loading
autocnet/spatial/overlap.py +15 −6 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ def place_points_in_overlaps(size_threshold=0.0007, if not ncg.Session: raise BrokenPipeError('This func requires a database session from a NetworkCandidateGraph.') for overlap in Overlay.overlapping_larger_than(size_threshold, Session): for overlap in Overlay.overlapping_larger_than(size_threshold, ncg.Session): if overlap.intersections == None: continue place_points_in_overlap(overlap, Loading @@ -93,7 +93,7 @@ def place_points_in_overlap(overlap, use_cache=False, **kwargs): """ Place points into an overlap geometry by back-projecing using sensor models. Place points into an overlap geometry by back-projecting using sensor models. The DEM specified in the config file will be used to calculate point elevations. Parameters Loading @@ -102,7 +102,7 @@ def place_points_in_overlap(overlap, An autocnet.io.db.model Overlay model instance. identifier: str The tag used to distiguish points laid down by this function. The tag used to distinguish points laid down by this function. cam_type : str options: {"csm", "isis"} Loading Loading @@ -292,16 +292,25 @@ def place_points_in_overlap(overlap, # Compute ground point to back project into measurtes gnd = csmapi.EcefCoord(x, y, z) for node in nodes: for current_index, node in enumerate(nodes): if cam_type == "csm": image_coord = node.camera.groundToImage(gnd) sample, line = image_coord.samp, image_coord.line if cam_type == "isis": # If this try/except fails, then the reference_index could be wrong because the length # of the measures list is different than the length of the nodes list that was used # to find the most interesting feature. try: sample, line = isis.ground_to_image(node["image_path"], updated_lon, updated_lat) except CalledProcessError as e: if 'Requested position does not project in camera model' in e.stderr: print(f'interesting point ({updated_lon},{updated_lat}) does not project to image {node["image_path"]}') # If the current_index is greater than the reference_index, the change in list size does # not impact the positional index of the reference. If current_index is less than the # reference_index, then the reference_index needs to de-increment by one for each time # a measure fails to be placed. if current_index < reference_index: reference_index -= 1 continue point.measures.append(Measures(sample=sample, Loading