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)
Esempio n. 2
0
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