def match_by_max_pmcc(tiles_file, fixed_tiles, out_fname, jar_file, conf_fname=None, threads_num=None): tile_file = tiles_file.replace('file://', '') with open(tile_file, 'r') as data_file: tilespecs = json.load(data_file) # TODO: add all tiles to a kd-tree so it will be faster to find overlap between tiles # TODO: limit searches for matches to overlap area of bounding boxes # iterate over the tiles, and for each tile, find intersecting tiles that overlap, # and match their features # Nested loop: # for each tile_i in range[0..N): # for each tile_j in range[tile_i..N)] indices = [] for idx1 in range(len(tilespecs)): for idx2 in range(idx1 + 1, len(tilespecs)): # if the two tiles intersect, match them bbox1 = BoundingBox.fromList(tilespecs[idx1]["bbox"]) bbox2 = BoundingBox.fromList(tilespecs[idx2]["bbox"]) if bbox1.overlap(bbox2): imageUrl1 = tilespecs[idx1]["mipmapLevels"]["0"]["imageUrl"] imageUrl2 = tilespecs[idx2]["mipmapLevels"]["0"]["imageUrl"] print "Matching by max pmcc: {0} and {1}".format( imageUrl1, imageUrl2) indices.append((idx1, idx2)) match_multiple_pmcc(tiles_file, indices, fixed_tiles, jar_file, out_fname, conf_fname, threads_num)
def load_tiles(tiles_spec_fname, bbox): relevant_tiles = [] with open(tiles_spec_fname, 'r') as data_file: data = json.load(data_file) for tile in data: tile_bbox = BoundingBox.fromList(tile['bbox']) if bbox.overlap(tile_bbox): relevant_tiles.append(tile) return relevant_tiles
def match_sift_features(tiles_file, features_file, out_fname, jar_file, conf=None): tilespecs, feature_indices = load_data_files(tiles_file, features_file) for k, v in feature_indices.iteritems(): print k, v # TODO: add all tiles to a kd-tree so it will be faster to find overlap between tiles # TODO: limit searches for matches to overlap area of bounding boxes # iterate over the tiles, and for each tile, find intersecting tiles that overlap, # and match their features # Nested loop: # for each tile_i in range[0..N): # for each tile_j in range[tile_i..N)] indices = [] for pair in itertools.combinations(tilespecs, 2): # if the two tiles intersect, match them bbox1 = BoundingBox.fromList(pair[0]["bbox"]) bbox2 = BoundingBox.fromList(pair[1]["bbox"]) if bbox1.overlap(bbox2): imageUrl1 = pair[0]["mipmapLevels"]["0"]["imageUrl"] imageUrl2 = pair[1]["mipmapLevels"]["0"]["imageUrl"] print "Matching sift of tiles: {0} and {1}".format( imageUrl1, imageUrl2) idx1 = feature_indices[imageUrl1] idx2 = feature_indices[imageUrl2] indices.append((idx1, idx2)) conf_args = utils.conf_args(conf, 'MatchSiftFeatures') match_multiple_sift_features(tiles_file, features_file, indices, jar_file, out_fname, conf_args)
# TODO: add all tiles to a kd-tree so it will be faster to find overlap between tiles # iterate over the tiles, and for each tile, find intersecting tiles that overlap, # and match their features # Nested loop: # for each tile_i in range[0..N): # for each tile_j in range[tile_i..N)] start_time = time.time() indices = [] for pair in itertools.combinations(xrange(len(tilespecs)), 2): idx1 = pair[0] idx2 = pair[1] ts1 = tilespecs[idx1] ts2 = tilespecs[idx2] # if the two tiles intersect, match them bbox1 = BoundingBox.fromList(ts1["bbox"]) bbox2 = BoundingBox.fromList(ts2["bbox"]) if bbox1.overlap(bbox2): imageUrl1 = ts1["mipmapLevels"]["0"]["imageUrl"] imageUrl2 = ts2["mipmapLevels"]["0"]["imageUrl"] tile_fname1 = os.path.basename(imageUrl1).split('.')[0] tile_fname2 = os.path.basename(imageUrl2).split('.')[0] print "Matching features of tiles: {0} and {1}".format(imageUrl1, imageUrl2) index_pair = [idx1, idx2] match_json = os.path.join(args.workspace_dir, "{0}_sift_matches_{1}_{2}.json".format(tiles_fname_prefix, tile_fname1, tile_fname2)) # match the features of overlapping tiles if not os.path.exists(match_json): match_single_sift_features_and_filter(args.tiles_fname, all_features[imageUrl1], all_features[imageUrl2], match_json, index_pair, conf_fname=args.conf_file_name) all_matched_features.append(match_json) print 'features matching took {0:1.4f} seconds'.format(time.time() - start_time)
def match_single_pair(tilespec1, tilespec2, feature_h5_filename1, feature_h5_filename2, output_json_filename, rod, iterations, max_epsilon, min_inlier_ratio, min_num_inlier, model_index, max_trust, det_delta): logger.info("Loading sift features") _, points1, _, _, descriptors1 = load_features(feature_h5_filename1) _, points2, _, _, descriptors2 = load_features(feature_h5_filename2) logger.info("Loaded {0} features from file: {1}".format( points1.shape[0], feature_h5_filename1)) logger.info("Loaded {0} features from file: {1}".format( points2.shape[0], feature_h5_filename2)) min_features_sum = 5 if points1.shape[0] < min_features_sum or points2.shape[ 0] < min_features_sum: logger.info( "Less than {} features (even before overlap) of one of the tiles, saving an empty match json file" ) create_empty_matches_json_file( output_json_filename, tilespec1["mipmapLevels"]["0"]["imageUrl"], tilespec2["mipmapLevels"]["0"]["imageUrl"]) return # Get the tile specification transforms logger.info("Getting transformation") tilespec1_transform = get_tile_specification_transformation(tilespec1) tilespec2_transform = get_tile_specification_transformation(tilespec2) # Filter the features to ensure that only features that are in the overlapping tile will be matches bbox1 = BoundingBox.fromList(tilespec1["bbox"]) logger.info("bbox1 {}".format(bbox1)) bbox2 = BoundingBox.fromList(tilespec2["bbox"]) logger.info("bbox2 {}".format(bbox2)) overlap_bbox = bbox1.intersect(bbox2).expand(offset=50) logger.info("overlap_bbox {}".format(overlap_bbox)) features_mask1 = overlap_bbox.contains(tilespec1_transform.apply(points1)) features_mask2 = overlap_bbox.contains(tilespec2_transform.apply(points2)) points1 = points1[features_mask1] points2 = points2[features_mask2] descriptors1 = descriptors1[features_mask1] descriptors2 = descriptors2[features_mask2] logger.info("Found {0} features in the overlap from file: {1}".format( points1.shape[0], feature_h5_filename1)) logger.info("Found {0} features in the overlap from file: {1}".format( points2.shape[0], feature_h5_filename2)) min_features_sum = 5 if points1.shape[0] < min_features_sum or points2.shape[ 0] < min_features_sum: logger.info( "Less than {} features in the overlap of one of the tiles, saving an empty match json file" ) create_empty_matches_json_file( output_json_filename, tilespec1["mipmapLevels"]["0"]["imageUrl"], tilespec2["mipmapLevels"]["0"]["imageUrl"]) return logger.info("Matching sift features") matches = match_features(descriptors1, descriptors2, rod) logger.info("Found {0} possible matches between {1} and {2}".format( len(matches), feature_h5_filename1, feature_h5_filename2)) match_points = np.array([ np.array([points1[[m[0].queryIdx for m in matches]]][0]), np.array([points2[[m[0].trainIdx for m in matches]]][0]) ]) model, filtered_matches = ransac.filter_matches(match_points, model_index, iterations, max_epsilon, min_inlier_ratio, min_num_inlier, max_trust, det_delta) model_json = [] if model is None: filtered_matches = [[], []] else: model_json = model.to_modelspec() out_data = [{ "mipmapLevel": 0, "url1": tilespec1["mipmapLevels"]["0"]["imageUrl"], "url2": tilespec2["mipmapLevels"]["0"]["imageUrl"], "correspondencePointPairs": [{ "p1": { "w": np.array(tilespec1_transform.apply(p1)[:2]).tolist(), "l": np.array([p1[0], p1[1]]).tolist() }, "p2": { "w": np.array(tilespec2_transform.apply(p2)[:2]).tolist(), "l": np.array([p2[0], p2[1]]).tolist() }, } for p1, p2 in zip(filtered_matches[0], filtered_matches[1])], "model": model_json }] logger.info("Saving matches into {}".format(output_json_filename)) with open(output_json_filename, 'w') as out: json.dump(out_data, out, sort_keys=True, indent=4) return True