Files
2014-02-15 11:39:18 -05:00

71 lines
2.6 KiB
Python

import numpy as np
from scipy.spatial.distance import cdist
def match_descriptors(descriptors1, descriptors2, metric=None, p=2,
max_distance=np.inf, cross_check=True):
"""Brute-force matching of descriptors.
For each descriptor in the first set this matcher finds the closest
descriptor in the second set (and vice-versa in the case of enabled
cross-checking).
Parameters
----------
descriptors1 : (M, P) array
Binary descriptors of size P about M keypoints in the first image.
descriptors2 : (N, P) array
Binary descriptors of size P about N keypoints in the second image.
metric : {'euclidean', 'cityblock', 'minkowski', 'hamming', ...}
The metric to compute the distance between two descriptors. See
`scipy.spatial.distance.cdist` for all possible types. The hamming
distance should be used for binary descriptors. By default the L2-norm
is used for all descriptors of dtype float or double and the Hamming
distance is used for binary descriptors automatically.
p : int
The p-norm to apply for ``metric='minkowski'``.
max_distance : float
Maximum allowed distance between descriptors of two keypoints
in separate images to be regarded as a match.
cross_check : bool
If True, the matched keypoints are returned after cross checking i.e. a
matched pair (keypoint1, keypoint2) is returned if keypoint2 is the
best match for keypoint1 in second image and keypoint1 is the best
match for keypoint2 in first image.
Returns
-------
matches : (Q, 2) array
Indices of corresponding matches in first and second set of
descriptors, where ``matches[:, 0]`` denote the indices in the first
and ``matches[:, 1]`` the indices in the second set of descriptors.
"""
if descriptors1.shape[1] != descriptors2.shape[1]:
raise ValueError("Descriptor length must equal.")
if metric is None:
if np.issubdtype(descriptors1.dtype, np.bool):
metric = 'hamming'
else:
metric = 'euclidean'
distances = cdist(descriptors1, descriptors2, metric=metric, p=p)
indices1 = np.arange(descriptors1.shape[0])
indices2 = np.argmin(distances, axis=1)
if cross_check:
matches1 = np.argmin(distances, axis=0)
mask = indices1 == matches1[indices2]
indices1 = indices1[mask]
indices2 = indices2[mask]
matches = np.column_stack((indices1, indices2))
if max_distance < np.inf:
matches = matches[distances[indices1, indices2] < max_distance]
return matches