refactor CUDA BFMatcher algorithm:
use new abstract interface and hidden implementation
This commit is contained in:
parent
764d55b81d
commit
8a178da1a4
@ -63,170 +63,315 @@ namespace cv { namespace cuda {
|
||||
//! @addtogroup cudafeatures2d
|
||||
//! @{
|
||||
|
||||
/** @brief Brute-force descriptor matcher.
|
||||
//
|
||||
// DescriptorMatcher
|
||||
//
|
||||
|
||||
For each descriptor in the first set, this matcher finds the closest descriptor in the second set
|
||||
by trying each one. This descriptor matcher supports masking permissible matches between descriptor
|
||||
sets.
|
||||
/** @brief Abstract base class for matching keypoint descriptors.
|
||||
|
||||
The class BFMatcher_CUDA has an interface similar to the class DescriptorMatcher. It has two groups
|
||||
of match methods: for matching descriptors of one image with another image or with an image set.
|
||||
Also, all functions have an alternative to save results either to the GPU memory or to the CPU
|
||||
memory.
|
||||
|
||||
@sa DescriptorMatcher, BFMatcher
|
||||
It has two groups of match methods: for matching descriptors of an image with another image or with
|
||||
an image set.
|
||||
*/
|
||||
class CV_EXPORTS BFMatcher_CUDA
|
||||
class CV_EXPORTS DescriptorMatcher : public cv::Algorithm
|
||||
{
|
||||
public:
|
||||
explicit BFMatcher_CUDA(int norm = cv::NORM_L2);
|
||||
//
|
||||
// Factories
|
||||
//
|
||||
|
||||
//! Add descriptors to train descriptor collection
|
||||
void add(const std::vector<GpuMat>& descCollection);
|
||||
/** @brief Brute-force descriptor matcher.
|
||||
|
||||
//! Get train descriptors collection
|
||||
const std::vector<GpuMat>& getTrainDescriptors() const;
|
||||
For each descriptor in the first set, this matcher finds the closest descriptor in the second set
|
||||
by trying each one. This descriptor matcher supports masking permissible matches of descriptor
|
||||
sets.
|
||||
|
||||
//! Clear train descriptors collection
|
||||
void clear();
|
||||
@param normType One of NORM_L1, NORM_L2, NORM_HAMMING. L1 and L2 norms are
|
||||
preferable choices for SIFT and SURF descriptors, NORM_HAMMING should be used with ORB, BRISK and
|
||||
BRIEF).
|
||||
*/
|
||||
static Ptr<DescriptorMatcher> createBFMatcher(int norm = cv::NORM_L2);
|
||||
|
||||
//! Return true if there are not train descriptors in collection
|
||||
bool empty() const;
|
||||
//
|
||||
// Utility
|
||||
//
|
||||
|
||||
//! Return true if the matcher supports mask in match methods
|
||||
bool isMaskSupported() const;
|
||||
/** @brief Returns true if the descriptor matcher supports masking permissible matches.
|
||||
*/
|
||||
virtual bool isMaskSupported() const = 0;
|
||||
|
||||
//! Find one best match for each query descriptor
|
||||
void matchSingle(const GpuMat& query, const GpuMat& train,
|
||||
GpuMat& trainIdx, GpuMat& distance,
|
||||
const GpuMat& mask = GpuMat(), Stream& stream = Stream::Null());
|
||||
//
|
||||
// Descriptor collection
|
||||
//
|
||||
|
||||
//! Download trainIdx and distance and convert it to CPU vector with DMatch
|
||||
static void matchDownload(const GpuMat& trainIdx, const GpuMat& distance, std::vector<DMatch>& matches);
|
||||
//! Convert trainIdx and distance to vector with DMatch
|
||||
static void matchConvert(const Mat& trainIdx, const Mat& distance, std::vector<DMatch>& matches);
|
||||
/** @brief Adds descriptors to train a descriptor collection.
|
||||
|
||||
//! Find one best match for each query descriptor
|
||||
void match(const GpuMat& query, const GpuMat& train, std::vector<DMatch>& matches, const GpuMat& mask = GpuMat());
|
||||
If the collection is not empty, the new descriptors are added to existing train descriptors.
|
||||
|
||||
//! Make gpu collection of trains and masks in suitable format for matchCollection function
|
||||
void makeGpuCollection(GpuMat& trainCollection, GpuMat& maskCollection, const std::vector<GpuMat>& masks = std::vector<GpuMat>());
|
||||
@param descriptors Descriptors to add. Each descriptors[i] is a set of descriptors from the same
|
||||
train image.
|
||||
*/
|
||||
virtual void add(const std::vector<GpuMat>& descriptors) = 0;
|
||||
|
||||
//! Find one best match from train collection for each query descriptor
|
||||
void matchCollection(const GpuMat& query, const GpuMat& trainCollection,
|
||||
GpuMat& trainIdx, GpuMat& imgIdx, GpuMat& distance,
|
||||
const GpuMat& masks = GpuMat(), Stream& stream = Stream::Null());
|
||||
/** @brief Returns a constant link to the train descriptor collection.
|
||||
*/
|
||||
virtual const std::vector<GpuMat>& getTrainDescriptors() const = 0;
|
||||
|
||||
//! Download trainIdx, imgIdx and distance and convert it to vector with DMatch
|
||||
static void matchDownload(const GpuMat& trainIdx, const GpuMat& imgIdx, const GpuMat& distance, std::vector<DMatch>& matches);
|
||||
//! Convert trainIdx, imgIdx and distance to vector with DMatch
|
||||
static void matchConvert(const Mat& trainIdx, const Mat& imgIdx, const Mat& distance, std::vector<DMatch>& matches);
|
||||
/** @brief Clears the train descriptor collection.
|
||||
*/
|
||||
virtual void clear() = 0;
|
||||
|
||||
//! Find one best match from train collection for each query descriptor.
|
||||
void match(const GpuMat& query, std::vector<DMatch>& matches, const std::vector<GpuMat>& masks = std::vector<GpuMat>());
|
||||
/** @brief Returns true if there are no train descriptors in the collection.
|
||||
*/
|
||||
virtual bool empty() const = 0;
|
||||
|
||||
//! Find k best matches for each query descriptor (in increasing order of distances)
|
||||
void knnMatchSingle(const GpuMat& query, const GpuMat& train,
|
||||
GpuMat& trainIdx, GpuMat& distance, GpuMat& allDist, int k,
|
||||
const GpuMat& mask = GpuMat(), Stream& stream = Stream::Null());
|
||||
/** @brief Trains a descriptor matcher.
|
||||
|
||||
//! Download trainIdx and distance and convert it to vector with DMatch
|
||||
//! compactResult is used when mask is not empty. If compactResult is false matches
|
||||
//! vector will have the same size as queryDescriptors rows. If compactResult is true
|
||||
//! matches vector will not contain matches for fully masked out query descriptors.
|
||||
static void knnMatchDownload(const GpuMat& trainIdx, const GpuMat& distance,
|
||||
std::vector< std::vector<DMatch> >& matches, bool compactResult = false);
|
||||
//! Convert trainIdx and distance to vector with DMatch
|
||||
static void knnMatchConvert(const Mat& trainIdx, const Mat& distance,
|
||||
std::vector< std::vector<DMatch> >& matches, bool compactResult = false);
|
||||
Trains a descriptor matcher (for example, the flann index). In all methods to match, the method
|
||||
train() is run every time before matching.
|
||||
*/
|
||||
virtual void train() = 0;
|
||||
|
||||
//! Find k best matches for each query descriptor (in increasing order of distances).
|
||||
//! compactResult is used when mask is not empty. If compactResult is false matches
|
||||
//! vector will have the same size as queryDescriptors rows. If compactResult is true
|
||||
//! matches vector will not contain matches for fully masked out query descriptors.
|
||||
void knnMatch(const GpuMat& query, const GpuMat& train,
|
||||
std::vector< std::vector<DMatch> >& matches, int k, const GpuMat& mask = GpuMat(),
|
||||
bool compactResult = false);
|
||||
//
|
||||
// 1 to 1 match
|
||||
//
|
||||
|
||||
//! Find k best matches from train collection for each query descriptor (in increasing order of distances)
|
||||
void knnMatch2Collection(const GpuMat& query, const GpuMat& trainCollection,
|
||||
GpuMat& trainIdx, GpuMat& imgIdx, GpuMat& distance,
|
||||
const GpuMat& maskCollection = GpuMat(), Stream& stream = Stream::Null());
|
||||
/** @brief Finds the best match for each descriptor from a query set (blocking version).
|
||||
|
||||
//! Download trainIdx and distance and convert it to vector with DMatch
|
||||
//! compactResult is used when mask is not empty. If compactResult is false matches
|
||||
//! vector will have the same size as queryDescriptors rows. If compactResult is true
|
||||
//! matches vector will not contain matches for fully masked out query descriptors.
|
||||
//! @see BFMatcher_CUDA::knnMatchDownload
|
||||
static void knnMatch2Download(const GpuMat& trainIdx, const GpuMat& imgIdx, const GpuMat& distance,
|
||||
std::vector< std::vector<DMatch> >& matches, bool compactResult = false);
|
||||
//! Convert trainIdx and distance to vector with DMatch
|
||||
//! @see BFMatcher_CUDA::knnMatchConvert
|
||||
static void knnMatch2Convert(const Mat& trainIdx, const Mat& imgIdx, const Mat& distance,
|
||||
std::vector< std::vector<DMatch> >& matches, bool compactResult = false);
|
||||
@param queryDescriptors Query set of descriptors.
|
||||
@param trainDescriptors Train set of descriptors. This set is not added to the train descriptors
|
||||
collection stored in the class object.
|
||||
@param matches Matches. If a query descriptor is masked out in mask , no match is added for this
|
||||
descriptor. So, matches size may be smaller than the query descriptors count.
|
||||
@param mask Mask specifying permissible matches between an input query and train matrices of
|
||||
descriptors.
|
||||
|
||||
//! Find k best matches for each query descriptor (in increasing order of distances).
|
||||
//! compactResult is used when mask is not empty. If compactResult is false matches
|
||||
//! vector will have the same size as queryDescriptors rows. If compactResult is true
|
||||
//! matches vector will not contain matches for fully masked out query descriptors.
|
||||
void knnMatch(const GpuMat& query, std::vector< std::vector<DMatch> >& matches, int k,
|
||||
const std::vector<GpuMat>& masks = std::vector<GpuMat>(), bool compactResult = false);
|
||||
In the first variant of this method, the train descriptors are passed as an input argument. In the
|
||||
second variant of the method, train descriptors collection that was set by DescriptorMatcher::add is
|
||||
used. Optional mask (or masks) can be passed to specify which query and training descriptors can be
|
||||
matched. Namely, queryDescriptors[i] can be matched with trainDescriptors[j] only if
|
||||
mask.at\<uchar\>(i,j) is non-zero.
|
||||
*/
|
||||
virtual void match(InputArray queryDescriptors, InputArray trainDescriptors,
|
||||
std::vector<DMatch>& matches,
|
||||
InputArray mask = noArray()) = 0;
|
||||
|
||||
//! Find best matches for each query descriptor which have distance less than maxDistance.
|
||||
//! nMatches.at<int>(0, queryIdx) will contain matches count for queryIdx.
|
||||
//! carefully nMatches can be greater than trainIdx.cols - it means that matcher didn't find all matches,
|
||||
//! because it didn't have enough memory.
|
||||
//! If trainIdx is empty, then trainIdx and distance will be created with size nQuery x max((nTrain / 100), 10),
|
||||
//! otherwize user can pass own allocated trainIdx and distance with size nQuery x nMaxMatches
|
||||
//! Matches doesn't sorted.
|
||||
void radiusMatchSingle(const GpuMat& query, const GpuMat& train,
|
||||
GpuMat& trainIdx, GpuMat& distance, GpuMat& nMatches, float maxDistance,
|
||||
const GpuMat& mask = GpuMat(), Stream& stream = Stream::Null());
|
||||
/** @overload
|
||||
*/
|
||||
virtual void match(InputArray queryDescriptors,
|
||||
std::vector<DMatch>& matches,
|
||||
const std::vector<GpuMat>& masks = std::vector<GpuMat>()) = 0;
|
||||
|
||||
//! Download trainIdx, nMatches and distance and convert it to vector with DMatch.
|
||||
//! matches will be sorted in increasing order of distances.
|
||||
//! compactResult is used when mask is not empty. If compactResult is false matches
|
||||
//! vector will have the same size as queryDescriptors rows. If compactResult is true
|
||||
//! matches vector will not contain matches for fully masked out query descriptors.
|
||||
static void radiusMatchDownload(const GpuMat& trainIdx, const GpuMat& distance, const GpuMat& nMatches,
|
||||
std::vector< std::vector<DMatch> >& matches, bool compactResult = false);
|
||||
//! Convert trainIdx, nMatches and distance to vector with DMatch.
|
||||
static void radiusMatchConvert(const Mat& trainIdx, const Mat& distance, const Mat& nMatches,
|
||||
std::vector< std::vector<DMatch> >& matches, bool compactResult = false);
|
||||
/** @brief Finds the best match for each descriptor from a query set (asynchronous version).
|
||||
|
||||
//! Find best matches for each query descriptor which have distance less than maxDistance
|
||||
//! in increasing order of distances).
|
||||
void radiusMatch(const GpuMat& query, const GpuMat& train,
|
||||
std::vector< std::vector<DMatch> >& matches, float maxDistance,
|
||||
const GpuMat& mask = GpuMat(), bool compactResult = false);
|
||||
@param queryDescriptors Query set of descriptors.
|
||||
@param trainDescriptors Train set of descriptors. This set is not added to the train descriptors
|
||||
collection stored in the class object.
|
||||
@param matches Matches array stored in GPU memory. Internal representation is not defined.
|
||||
Use DescriptorMatcher::matchConvert method to retrieve results in standard representation.
|
||||
@param mask Mask specifying permissible matches between an input query and train matrices of
|
||||
descriptors.
|
||||
@param stream CUDA stream.
|
||||
|
||||
//! Find best matches for each query descriptor which have distance less than maxDistance.
|
||||
//! If trainIdx is empty, then trainIdx and distance will be created with size nQuery x max((nQuery / 100), 10),
|
||||
//! otherwize user can pass own allocated trainIdx and distance with size nQuery x nMaxMatches
|
||||
//! Matches doesn't sorted.
|
||||
void radiusMatchCollection(const GpuMat& query, GpuMat& trainIdx, GpuMat& imgIdx, GpuMat& distance, GpuMat& nMatches, float maxDistance,
|
||||
const std::vector<GpuMat>& masks = std::vector<GpuMat>(), Stream& stream = Stream::Null());
|
||||
In the first variant of this method, the train descriptors are passed as an input argument. In the
|
||||
second variant of the method, train descriptors collection that was set by DescriptorMatcher::add is
|
||||
used. Optional mask (or masks) can be passed to specify which query and training descriptors can be
|
||||
matched. Namely, queryDescriptors[i] can be matched with trainDescriptors[j] only if
|
||||
mask.at\<uchar\>(i,j) is non-zero.
|
||||
*/
|
||||
virtual void matchAsync(InputArray queryDescriptors, InputArray trainDescriptors,
|
||||
OutputArray matches,
|
||||
InputArray mask = noArray(),
|
||||
Stream& stream = Stream::Null()) = 0;
|
||||
|
||||
//! Download trainIdx, imgIdx, nMatches and distance and convert it to vector with DMatch.
|
||||
//! matches will be sorted in increasing order of distances.
|
||||
//! compactResult is used when mask is not empty. If compactResult is false matches
|
||||
//! vector will have the same size as queryDescriptors rows. If compactResult is true
|
||||
//! matches vector will not contain matches for fully masked out query descriptors.
|
||||
static void radiusMatchDownload(const GpuMat& trainIdx, const GpuMat& imgIdx, const GpuMat& distance, const GpuMat& nMatches,
|
||||
std::vector< std::vector<DMatch> >& matches, bool compactResult = false);
|
||||
//! Convert trainIdx, nMatches and distance to vector with DMatch.
|
||||
static void radiusMatchConvert(const Mat& trainIdx, const Mat& imgIdx, const Mat& distance, const Mat& nMatches,
|
||||
std::vector< std::vector<DMatch> >& matches, bool compactResult = false);
|
||||
/** @overload
|
||||
*/
|
||||
virtual void matchAsync(InputArray queryDescriptors,
|
||||
OutputArray matches,
|
||||
const std::vector<GpuMat>& masks = std::vector<GpuMat>(),
|
||||
Stream& stream = Stream::Null()) = 0;
|
||||
|
||||
//! Find best matches from train collection for each query descriptor which have distance less than
|
||||
//! maxDistance (in increasing order of distances).
|
||||
void radiusMatch(const GpuMat& query, std::vector< std::vector<DMatch> >& matches, float maxDistance,
|
||||
const std::vector<GpuMat>& masks = std::vector<GpuMat>(), bool compactResult = false);
|
||||
/** @brief Converts matches array from internal representation to standard matches vector.
|
||||
|
||||
int norm;
|
||||
The method is supposed to be used with DescriptorMatcher::matchAsync to get final result.
|
||||
Call this method only after DescriptorMatcher::matchAsync is completed (ie. after synchronization).
|
||||
|
||||
private:
|
||||
std::vector<GpuMat> trainDescCollection;
|
||||
@param gpu_matches Matches, returned from DescriptorMatcher::matchAsync.
|
||||
@param matches Vector of DMatch objects.
|
||||
*/
|
||||
virtual void matchConvert(InputArray gpu_matches,
|
||||
std::vector<DMatch>& matches) = 0;
|
||||
|
||||
//
|
||||
// knn match
|
||||
//
|
||||
|
||||
/** @brief Finds the k best matches for each descriptor from a query set (blocking version).
|
||||
|
||||
@param queryDescriptors Query set of descriptors.
|
||||
@param trainDescriptors Train set of descriptors. This set is not added to the train descriptors
|
||||
collection stored in the class object.
|
||||
@param matches Matches. Each matches[i] is k or less matches for the same query descriptor.
|
||||
@param k Count of best matches found per each query descriptor or less if a query descriptor has
|
||||
less than k possible matches in total.
|
||||
@param mask Mask specifying permissible matches between an input query and train matrices of
|
||||
descriptors.
|
||||
@param compactResult Parameter used when the mask (or masks) is not empty. If compactResult is
|
||||
false, the matches vector has the same size as queryDescriptors rows. If compactResult is true,
|
||||
the matches vector does not contain matches for fully masked-out query descriptors.
|
||||
|
||||
These extended variants of DescriptorMatcher::match methods find several best matches for each query
|
||||
descriptor. The matches are returned in the distance increasing order. See DescriptorMatcher::match
|
||||
for the details about query and train descriptors.
|
||||
*/
|
||||
virtual void knnMatch(InputArray queryDescriptors, InputArray trainDescriptors,
|
||||
std::vector<std::vector<DMatch> >& matches,
|
||||
int k,
|
||||
InputArray mask = noArray(),
|
||||
bool compactResult = false) = 0;
|
||||
|
||||
/** @overload
|
||||
*/
|
||||
virtual void knnMatch(InputArray queryDescriptors,
|
||||
std::vector<std::vector<DMatch> >& matches,
|
||||
int k,
|
||||
const std::vector<GpuMat>& masks = std::vector<GpuMat>(),
|
||||
bool compactResult = false) = 0;
|
||||
|
||||
/** @brief Finds the k best matches for each descriptor from a query set (asynchronous version).
|
||||
|
||||
@param queryDescriptors Query set of descriptors.
|
||||
@param trainDescriptors Train set of descriptors. This set is not added to the train descriptors
|
||||
collection stored in the class object.
|
||||
@param matches Matches array stored in GPU memory. Internal representation is not defined.
|
||||
Use DescriptorMatcher::knnMatchConvert method to retrieve results in standard representation.
|
||||
@param k Count of best matches found per each query descriptor or less if a query descriptor has
|
||||
less than k possible matches in total.
|
||||
@param mask Mask specifying permissible matches between an input query and train matrices of
|
||||
descriptors.
|
||||
@param compactResult Parameter used when the mask (or masks) is not empty. If compactResult is
|
||||
false, the matches vector has the same size as queryDescriptors rows. If compactResult is true,
|
||||
the matches vector does not contain matches for fully masked-out query descriptors.
|
||||
@param stream CUDA stream.
|
||||
|
||||
These extended variants of DescriptorMatcher::matchAsync methods find several best matches for each query
|
||||
descriptor. The matches are returned in the distance increasing order. See DescriptorMatcher::matchAsync
|
||||
for the details about query and train descriptors.
|
||||
*/
|
||||
virtual void knnMatchAsync(InputArray queryDescriptors, InputArray trainDescriptors,
|
||||
OutputArray matches,
|
||||
int k,
|
||||
InputArray mask = noArray(),
|
||||
Stream& stream = Stream::Null()) = 0;
|
||||
|
||||
/** @overload
|
||||
*/
|
||||
virtual void knnMatchAsync(InputArray queryDescriptors,
|
||||
OutputArray matches,
|
||||
int k,
|
||||
const std::vector<GpuMat>& masks = std::vector<GpuMat>(),
|
||||
Stream& stream = Stream::Null()) = 0;
|
||||
|
||||
/** @brief Converts matches array from internal representation to standard matches vector.
|
||||
|
||||
The method is supposed to be used with DescriptorMatcher::knnMatchAsync to get final result.
|
||||
Call this method only after DescriptorMatcher::knnMatchAsync is completed (ie. after synchronization).
|
||||
|
||||
@param gpu_matches Matches, returned from DescriptorMatcher::knnMatchAsync.
|
||||
@param matches Vector of DMatch objects.
|
||||
@param compactResult Parameter used when the mask (or masks) is not empty. If compactResult is
|
||||
false, the matches vector has the same size as queryDescriptors rows. If compactResult is true,
|
||||
the matches vector does not contain matches for fully masked-out query descriptors.
|
||||
*/
|
||||
virtual void knnMatchConvert(InputArray gpu_matches,
|
||||
std::vector< std::vector<DMatch> >& matches,
|
||||
bool compactResult = false) = 0;
|
||||
|
||||
//
|
||||
// radius match
|
||||
//
|
||||
|
||||
/** @brief For each query descriptor, finds the training descriptors not farther than the specified distance (blocking version).
|
||||
|
||||
@param queryDescriptors Query set of descriptors.
|
||||
@param trainDescriptors Train set of descriptors. This set is not added to the train descriptors
|
||||
collection stored in the class object.
|
||||
@param matches Found matches.
|
||||
@param maxDistance Threshold for the distance between matched descriptors. Distance means here
|
||||
metric distance (e.g. Hamming distance), not the distance between coordinates (which is measured
|
||||
in Pixels)!
|
||||
@param mask Mask specifying permissible matches between an input query and train matrices of
|
||||
descriptors.
|
||||
@param compactResult Parameter used when the mask (or masks) is not empty. If compactResult is
|
||||
false, the matches vector has the same size as queryDescriptors rows. If compactResult is true,
|
||||
the matches vector does not contain matches for fully masked-out query descriptors.
|
||||
|
||||
For each query descriptor, the methods find such training descriptors that the distance between the
|
||||
query descriptor and the training descriptor is equal or smaller than maxDistance. Found matches are
|
||||
returned in the distance increasing order.
|
||||
*/
|
||||
virtual void radiusMatch(InputArray queryDescriptors, InputArray trainDescriptors,
|
||||
std::vector<std::vector<DMatch> >& matches,
|
||||
float maxDistance,
|
||||
InputArray mask = noArray(),
|
||||
bool compactResult = false) = 0;
|
||||
|
||||
/** @overload
|
||||
*/
|
||||
virtual void radiusMatch(InputArray queryDescriptors,
|
||||
std::vector<std::vector<DMatch> >& matches,
|
||||
float maxDistance,
|
||||
const std::vector<GpuMat>& masks = std::vector<GpuMat>(),
|
||||
bool compactResult = false) = 0;
|
||||
|
||||
/** @brief For each query descriptor, finds the training descriptors not farther than the specified distance (asynchronous version).
|
||||
|
||||
@param queryDescriptors Query set of descriptors.
|
||||
@param trainDescriptors Train set of descriptors. This set is not added to the train descriptors
|
||||
collection stored in the class object.
|
||||
@param matches Matches array stored in GPU memory. Internal representation is not defined.
|
||||
Use DescriptorMatcher::radiusMatchConvert method to retrieve results in standard representation.
|
||||
@param maxDistance Threshold for the distance between matched descriptors. Distance means here
|
||||
metric distance (e.g. Hamming distance), not the distance between coordinates (which is measured
|
||||
in Pixels)!
|
||||
@param mask Mask specifying permissible matches between an input query and train matrices of
|
||||
descriptors.
|
||||
@param compactResult Parameter used when the mask (or masks) is not empty. If compactResult is
|
||||
false, the matches vector has the same size as queryDescriptors rows. If compactResult is true,
|
||||
the matches vector does not contain matches for fully masked-out query descriptors.
|
||||
@param stream CUDA stream.
|
||||
|
||||
For each query descriptor, the methods find such training descriptors that the distance between the
|
||||
query descriptor and the training descriptor is equal or smaller than maxDistance. Found matches are
|
||||
returned in the distance increasing order.
|
||||
*/
|
||||
virtual void radiusMatchAsync(InputArray queryDescriptors, InputArray trainDescriptors,
|
||||
OutputArray matches,
|
||||
float maxDistance,
|
||||
InputArray mask = noArray(),
|
||||
Stream& stream = Stream::Null()) = 0;
|
||||
|
||||
/** @overload
|
||||
*/
|
||||
virtual void radiusMatchAsync(InputArray queryDescriptors,
|
||||
OutputArray matches,
|
||||
float maxDistance,
|
||||
const std::vector<GpuMat>& masks = std::vector<GpuMat>(),
|
||||
Stream& stream = Stream::Null()) = 0;
|
||||
|
||||
/** @brief Converts matches array from internal representation to standard matches vector.
|
||||
|
||||
The method is supposed to be used with DescriptorMatcher::radiusMatchAsync to get final result.
|
||||
Call this method only after DescriptorMatcher::radiusMatchAsync is completed (ie. after synchronization).
|
||||
|
||||
@param gpu_matches Matches, returned from DescriptorMatcher::radiusMatchAsync.
|
||||
@param matches Vector of DMatch objects.
|
||||
@param compactResult Parameter used when the mask (or masks) is not empty. If compactResult is
|
||||
false, the matches vector has the same size as queryDescriptors rows. If compactResult is true,
|
||||
the matches vector does not contain matches for fully masked-out query descriptors.
|
||||
*/
|
||||
virtual void radiusMatchConvert(InputArray gpu_matches,
|
||||
std::vector< std::vector<DMatch> >& matches,
|
||||
bool compactResult = false) = 0;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -167,16 +167,16 @@ PERF_TEST_P(DescSize_Norm, BFMatch,
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
cv::cuda::BFMatcher_CUDA d_matcher(normType);
|
||||
cv::Ptr<cv::cuda::DescriptorMatcher> d_matcher = cv::cuda::DescriptorMatcher::createBFMatcher(normType);
|
||||
|
||||
const cv::cuda::GpuMat d_query(query);
|
||||
const cv::cuda::GpuMat d_train(train);
|
||||
cv::cuda::GpuMat d_trainIdx, d_distance;
|
||||
cv::cuda::GpuMat d_matches;
|
||||
|
||||
TEST_CYCLE() d_matcher.matchSingle(d_query, d_train, d_trainIdx, d_distance);
|
||||
TEST_CYCLE() d_matcher->matchAsync(d_query, d_train, d_matches);
|
||||
|
||||
std::vector<cv::DMatch> gpu_matches;
|
||||
d_matcher.matchDownload(d_trainIdx, d_distance, gpu_matches);
|
||||
d_matcher->matchConvert(d_matches, gpu_matches);
|
||||
|
||||
SANITY_CHECK_MATCHES(gpu_matches);
|
||||
}
|
||||
@ -226,16 +226,16 @@ PERF_TEST_P(DescSize_K_Norm, BFKnnMatch,
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
cv::cuda::BFMatcher_CUDA d_matcher(normType);
|
||||
cv::Ptr<cv::cuda::DescriptorMatcher> d_matcher = cv::cuda::DescriptorMatcher::createBFMatcher(normType);
|
||||
|
||||
const cv::cuda::GpuMat d_query(query);
|
||||
const cv::cuda::GpuMat d_train(train);
|
||||
cv::cuda::GpuMat d_trainIdx, d_distance, d_allDist;
|
||||
cv::cuda::GpuMat d_matches;
|
||||
|
||||
TEST_CYCLE() d_matcher.knnMatchSingle(d_query, d_train, d_trainIdx, d_distance, d_allDist, k);
|
||||
TEST_CYCLE() d_matcher->knnMatchAsync(d_query, d_train, d_matches, k);
|
||||
|
||||
std::vector< std::vector<cv::DMatch> > matchesTbl;
|
||||
d_matcher.knnMatchDownload(d_trainIdx, d_distance, matchesTbl);
|
||||
d_matcher->knnMatchConvert(d_matches, matchesTbl);
|
||||
|
||||
std::vector<cv::DMatch> gpu_matches;
|
||||
toOneRowMatches(matchesTbl, gpu_matches);
|
||||
@ -280,16 +280,16 @@ PERF_TEST_P(DescSize_Norm, BFRadiusMatch,
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
cv::cuda::BFMatcher_CUDA d_matcher(normType);
|
||||
cv::Ptr<cv::cuda::DescriptorMatcher> d_matcher = cv::cuda::DescriptorMatcher::createBFMatcher(normType);
|
||||
|
||||
const cv::cuda::GpuMat d_query(query);
|
||||
const cv::cuda::GpuMat d_train(train);
|
||||
cv::cuda::GpuMat d_trainIdx, d_nMatches, d_distance;
|
||||
cv::cuda::GpuMat d_matches;
|
||||
|
||||
TEST_CYCLE() d_matcher.radiusMatchSingle(d_query, d_train, d_trainIdx, d_distance, d_nMatches, maxDistance);
|
||||
TEST_CYCLE() d_matcher->radiusMatchAsync(d_query, d_train, d_matches, maxDistance);
|
||||
|
||||
std::vector< std::vector<cv::DMatch> > matchesTbl;
|
||||
d_matcher.radiusMatchDownload(d_trainIdx, d_distance, d_nMatches, matchesTbl);
|
||||
d_matcher->radiusMatchConvert(d_matches, matchesTbl);
|
||||
|
||||
std::vector<cv::DMatch> gpu_matches;
|
||||
toOneRowMatches(matchesTbl, gpu_matches);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -285,7 +285,8 @@ PARAM_TEST_CASE(BruteForceMatcher, cv::cuda::DeviceInfo, NormCode, DescriptorSiz
|
||||
|
||||
CUDA_TEST_P(BruteForceMatcher, Match_Single)
|
||||
{
|
||||
cv::cuda::BFMatcher_CUDA matcher(normCode);
|
||||
cv::Ptr<cv::cuda::DescriptorMatcher> matcher =
|
||||
cv::cuda::DescriptorMatcher::createBFMatcher(normCode);
|
||||
|
||||
cv::cuda::GpuMat mask;
|
||||
if (useMask)
|
||||
@ -295,7 +296,7 @@ CUDA_TEST_P(BruteForceMatcher, Match_Single)
|
||||
}
|
||||
|
||||
std::vector<cv::DMatch> matches;
|
||||
matcher.match(loadMat(query), loadMat(train), matches, mask);
|
||||
matcher->match(loadMat(query), loadMat(train), matches, mask);
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(queryDescCount), matches.size());
|
||||
|
||||
@ -312,13 +313,14 @@ CUDA_TEST_P(BruteForceMatcher, Match_Single)
|
||||
|
||||
CUDA_TEST_P(BruteForceMatcher, Match_Collection)
|
||||
{
|
||||
cv::cuda::BFMatcher_CUDA matcher(normCode);
|
||||
cv::Ptr<cv::cuda::DescriptorMatcher> matcher =
|
||||
cv::cuda::DescriptorMatcher::createBFMatcher(normCode);
|
||||
|
||||
cv::cuda::GpuMat d_train(train);
|
||||
|
||||
// make add() twice to test such case
|
||||
matcher.add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(0, train.rows / 2)));
|
||||
matcher.add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(train.rows / 2, train.rows)));
|
||||
matcher->add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(0, train.rows / 2)));
|
||||
matcher->add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(train.rows / 2, train.rows)));
|
||||
|
||||
// prepare masks (make first nearest match illegal)
|
||||
std::vector<cv::cuda::GpuMat> masks(2);
|
||||
@ -331,9 +333,9 @@ CUDA_TEST_P(BruteForceMatcher, Match_Collection)
|
||||
|
||||
std::vector<cv::DMatch> matches;
|
||||
if (useMask)
|
||||
matcher.match(cv::cuda::GpuMat(query), matches, masks);
|
||||
matcher->match(cv::cuda::GpuMat(query), matches, masks);
|
||||
else
|
||||
matcher.match(cv::cuda::GpuMat(query), matches);
|
||||
matcher->match(cv::cuda::GpuMat(query), matches);
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(queryDescCount), matches.size());
|
||||
|
||||
@ -366,7 +368,8 @@ CUDA_TEST_P(BruteForceMatcher, Match_Collection)
|
||||
|
||||
CUDA_TEST_P(BruteForceMatcher, KnnMatch_2_Single)
|
||||
{
|
||||
cv::cuda::BFMatcher_CUDA matcher(normCode);
|
||||
cv::Ptr<cv::cuda::DescriptorMatcher> matcher =
|
||||
cv::cuda::DescriptorMatcher::createBFMatcher(normCode);
|
||||
|
||||
const int knn = 2;
|
||||
|
||||
@ -378,7 +381,7 @@ CUDA_TEST_P(BruteForceMatcher, KnnMatch_2_Single)
|
||||
}
|
||||
|
||||
std::vector< std::vector<cv::DMatch> > matches;
|
||||
matcher.knnMatch(loadMat(query), loadMat(train), matches, knn, mask);
|
||||
matcher->knnMatch(loadMat(query), loadMat(train), matches, knn, mask);
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(queryDescCount), matches.size());
|
||||
|
||||
@ -405,7 +408,8 @@ CUDA_TEST_P(BruteForceMatcher, KnnMatch_2_Single)
|
||||
|
||||
CUDA_TEST_P(BruteForceMatcher, KnnMatch_3_Single)
|
||||
{
|
||||
cv::cuda::BFMatcher_CUDA matcher(normCode);
|
||||
cv::Ptr<cv::cuda::DescriptorMatcher> matcher =
|
||||
cv::cuda::DescriptorMatcher::createBFMatcher(normCode);
|
||||
|
||||
const int knn = 3;
|
||||
|
||||
@ -417,7 +421,7 @@ CUDA_TEST_P(BruteForceMatcher, KnnMatch_3_Single)
|
||||
}
|
||||
|
||||
std::vector< std::vector<cv::DMatch> > matches;
|
||||
matcher.knnMatch(loadMat(query), loadMat(train), matches, knn, mask);
|
||||
matcher->knnMatch(loadMat(query), loadMat(train), matches, knn, mask);
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(queryDescCount), matches.size());
|
||||
|
||||
@ -444,15 +448,16 @@ CUDA_TEST_P(BruteForceMatcher, KnnMatch_3_Single)
|
||||
|
||||
CUDA_TEST_P(BruteForceMatcher, KnnMatch_2_Collection)
|
||||
{
|
||||
cv::cuda::BFMatcher_CUDA matcher(normCode);
|
||||
cv::Ptr<cv::cuda::DescriptorMatcher> matcher =
|
||||
cv::cuda::DescriptorMatcher::createBFMatcher(normCode);
|
||||
|
||||
const int knn = 2;
|
||||
|
||||
cv::cuda::GpuMat d_train(train);
|
||||
|
||||
// make add() twice to test such case
|
||||
matcher.add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(0, train.rows / 2)));
|
||||
matcher.add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(train.rows / 2, train.rows)));
|
||||
matcher->add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(0, train.rows / 2)));
|
||||
matcher->add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(train.rows / 2, train.rows)));
|
||||
|
||||
// prepare masks (make first nearest match illegal)
|
||||
std::vector<cv::cuda::GpuMat> masks(2);
|
||||
@ -466,9 +471,9 @@ CUDA_TEST_P(BruteForceMatcher, KnnMatch_2_Collection)
|
||||
std::vector< std::vector<cv::DMatch> > matches;
|
||||
|
||||
if (useMask)
|
||||
matcher.knnMatch(cv::cuda::GpuMat(query), matches, knn, masks);
|
||||
matcher->knnMatch(cv::cuda::GpuMat(query), matches, knn, masks);
|
||||
else
|
||||
matcher.knnMatch(cv::cuda::GpuMat(query), matches, knn);
|
||||
matcher->knnMatch(cv::cuda::GpuMat(query), matches, knn);
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(queryDescCount), matches.size());
|
||||
|
||||
@ -506,15 +511,16 @@ CUDA_TEST_P(BruteForceMatcher, KnnMatch_2_Collection)
|
||||
|
||||
CUDA_TEST_P(BruteForceMatcher, KnnMatch_3_Collection)
|
||||
{
|
||||
cv::cuda::BFMatcher_CUDA matcher(normCode);
|
||||
cv::Ptr<cv::cuda::DescriptorMatcher> matcher =
|
||||
cv::cuda::DescriptorMatcher::createBFMatcher(normCode);
|
||||
|
||||
const int knn = 3;
|
||||
|
||||
cv::cuda::GpuMat d_train(train);
|
||||
|
||||
// make add() twice to test such case
|
||||
matcher.add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(0, train.rows / 2)));
|
||||
matcher.add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(train.rows / 2, train.rows)));
|
||||
matcher->add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(0, train.rows / 2)));
|
||||
matcher->add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(train.rows / 2, train.rows)));
|
||||
|
||||
// prepare masks (make first nearest match illegal)
|
||||
std::vector<cv::cuda::GpuMat> masks(2);
|
||||
@ -528,9 +534,9 @@ CUDA_TEST_P(BruteForceMatcher, KnnMatch_3_Collection)
|
||||
std::vector< std::vector<cv::DMatch> > matches;
|
||||
|
||||
if (useMask)
|
||||
matcher.knnMatch(cv::cuda::GpuMat(query), matches, knn, masks);
|
||||
matcher->knnMatch(cv::cuda::GpuMat(query), matches, knn, masks);
|
||||
else
|
||||
matcher.knnMatch(cv::cuda::GpuMat(query), matches, knn);
|
||||
matcher->knnMatch(cv::cuda::GpuMat(query), matches, knn);
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(queryDescCount), matches.size());
|
||||
|
||||
@ -568,7 +574,8 @@ CUDA_TEST_P(BruteForceMatcher, KnnMatch_3_Collection)
|
||||
|
||||
CUDA_TEST_P(BruteForceMatcher, RadiusMatch_Single)
|
||||
{
|
||||
cv::cuda::BFMatcher_CUDA matcher(normCode);
|
||||
cv::Ptr<cv::cuda::DescriptorMatcher> matcher =
|
||||
cv::cuda::DescriptorMatcher::createBFMatcher(normCode);
|
||||
|
||||
const float radius = 1.f / countFactor;
|
||||
|
||||
@ -577,7 +584,7 @@ CUDA_TEST_P(BruteForceMatcher, RadiusMatch_Single)
|
||||
try
|
||||
{
|
||||
std::vector< std::vector<cv::DMatch> > matches;
|
||||
matcher.radiusMatch(loadMat(query), loadMat(train), matches, radius);
|
||||
matcher->radiusMatch(loadMat(query), loadMat(train), matches, radius);
|
||||
}
|
||||
catch (const cv::Exception& e)
|
||||
{
|
||||
@ -594,7 +601,7 @@ CUDA_TEST_P(BruteForceMatcher, RadiusMatch_Single)
|
||||
}
|
||||
|
||||
std::vector< std::vector<cv::DMatch> > matches;
|
||||
matcher.radiusMatch(loadMat(query), loadMat(train), matches, radius, mask);
|
||||
matcher->radiusMatch(loadMat(query), loadMat(train), matches, radius, mask);
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(queryDescCount), matches.size());
|
||||
|
||||
@ -617,7 +624,8 @@ CUDA_TEST_P(BruteForceMatcher, RadiusMatch_Single)
|
||||
|
||||
CUDA_TEST_P(BruteForceMatcher, RadiusMatch_Collection)
|
||||
{
|
||||
cv::cuda::BFMatcher_CUDA matcher(normCode);
|
||||
cv::Ptr<cv::cuda::DescriptorMatcher> matcher =
|
||||
cv::cuda::DescriptorMatcher::createBFMatcher(normCode);
|
||||
|
||||
const int n = 3;
|
||||
const float radius = 1.f / countFactor * n;
|
||||
@ -625,8 +633,8 @@ CUDA_TEST_P(BruteForceMatcher, RadiusMatch_Collection)
|
||||
cv::cuda::GpuMat d_train(train);
|
||||
|
||||
// make add() twice to test such case
|
||||
matcher.add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(0, train.rows / 2)));
|
||||
matcher.add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(train.rows / 2, train.rows)));
|
||||
matcher->add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(0, train.rows / 2)));
|
||||
matcher->add(std::vector<cv::cuda::GpuMat>(1, d_train.rowRange(train.rows / 2, train.rows)));
|
||||
|
||||
// prepare masks (make first nearest match illegal)
|
||||
std::vector<cv::cuda::GpuMat> masks(2);
|
||||
@ -642,7 +650,7 @@ CUDA_TEST_P(BruteForceMatcher, RadiusMatch_Collection)
|
||||
try
|
||||
{
|
||||
std::vector< std::vector<cv::DMatch> > matches;
|
||||
matcher.radiusMatch(cv::cuda::GpuMat(query), matches, radius, masks);
|
||||
matcher->radiusMatch(cv::cuda::GpuMat(query), matches, radius, masks);
|
||||
}
|
||||
catch (const cv::Exception& e)
|
||||
{
|
||||
@ -654,9 +662,9 @@ CUDA_TEST_P(BruteForceMatcher, RadiusMatch_Collection)
|
||||
std::vector< std::vector<cv::DMatch> > matches;
|
||||
|
||||
if (useMask)
|
||||
matcher.radiusMatch(cv::cuda::GpuMat(query), matches, radius, masks);
|
||||
matcher->radiusMatch(cv::cuda::GpuMat(query), matches, radius, masks);
|
||||
else
|
||||
matcher.radiusMatch(cv::cuda::GpuMat(query), matches, radius);
|
||||
matcher->radiusMatch(cv::cuda::GpuMat(query), matches, radius);
|
||||
|
||||
ASSERT_EQ(static_cast<size_t>(queryDescCount), matches.size());
|
||||
|
||||
|
@ -154,7 +154,7 @@ void CpuMatcher::match(const ImageFeatures &features1, const ImageFeatures &feat
|
||||
|
||||
matches_info.matches.clear();
|
||||
|
||||
Ptr<DescriptorMatcher> matcher;
|
||||
Ptr<cv::DescriptorMatcher> matcher;
|
||||
#if 0 // TODO check this
|
||||
if (ocl::useOpenCL())
|
||||
{
|
||||
@ -220,13 +220,13 @@ void GpuMatcher::match(const ImageFeatures &features1, const ImageFeatures &feat
|
||||
descriptors1_.upload(features1.descriptors);
|
||||
descriptors2_.upload(features2.descriptors);
|
||||
|
||||
BFMatcher_CUDA matcher(NORM_L2);
|
||||
Ptr<cuda::DescriptorMatcher> matcher = cuda::DescriptorMatcher::createBFMatcher(NORM_L2);
|
||||
|
||||
MatchesSet matches;
|
||||
|
||||
// Find 1->2 matches
|
||||
pair_matches.clear();
|
||||
matcher.knnMatchSingle(descriptors1_, descriptors2_, train_idx_, distance_, all_dist_, 2);
|
||||
matcher.knnMatchDownload(train_idx_, distance_, pair_matches);
|
||||
matcher->knnMatch(descriptors1_, descriptors2_, pair_matches, 2);
|
||||
for (size_t i = 0; i < pair_matches.size(); ++i)
|
||||
{
|
||||
if (pair_matches[i].size() < 2)
|
||||
@ -242,8 +242,7 @@ void GpuMatcher::match(const ImageFeatures &features1, const ImageFeatures &feat
|
||||
|
||||
// Find 2->1 matches
|
||||
pair_matches.clear();
|
||||
matcher.knnMatchSingle(descriptors2_, descriptors1_, train_idx_, distance_, all_dist_, 2);
|
||||
matcher.knnMatchDownload(train_idx_, distance_, pair_matches);
|
||||
matcher->knnMatch(descriptors2_, descriptors1_, pair_matches, 2);
|
||||
for (size_t i = 0; i < pair_matches.size(); ++i)
|
||||
{
|
||||
if (pair_matches[i].size() < 2)
|
||||
|
@ -379,14 +379,14 @@ TEST(BruteForceMatcher)
|
||||
|
||||
// Init CUDA matcher
|
||||
|
||||
cuda::BFMatcher_CUDA d_matcher(NORM_L2);
|
||||
Ptr<cuda::DescriptorMatcher> d_matcher = cuda::DescriptorMatcher::createBFMatcher(NORM_L2);
|
||||
|
||||
cuda::GpuMat d_query(query);
|
||||
cuda::GpuMat d_train(train);
|
||||
|
||||
// Output
|
||||
vector< vector<DMatch> > matches(2);
|
||||
cuda::GpuMat d_trainIdx, d_distance, d_allDist, d_nMatches;
|
||||
cuda::GpuMat d_matches;
|
||||
|
||||
SUBTEST << "match";
|
||||
|
||||
@ -396,10 +396,10 @@ TEST(BruteForceMatcher)
|
||||
matcher.match(query, train, matches[0]);
|
||||
CPU_OFF;
|
||||
|
||||
d_matcher.matchSingle(d_query, d_train, d_trainIdx, d_distance);
|
||||
d_matcher->matchAsync(d_query, d_train, d_matches);
|
||||
|
||||
CUDA_ON;
|
||||
d_matcher.matchSingle(d_query, d_train, d_trainIdx, d_distance);
|
||||
d_matcher->matchAsync(d_query, d_train, d_matches);
|
||||
CUDA_OFF;
|
||||
|
||||
SUBTEST << "knnMatch";
|
||||
@ -410,10 +410,10 @@ TEST(BruteForceMatcher)
|
||||
matcher.knnMatch(query, train, matches, 2);
|
||||
CPU_OFF;
|
||||
|
||||
d_matcher.knnMatchSingle(d_query, d_train, d_trainIdx, d_distance, d_allDist, 2);
|
||||
d_matcher->knnMatchAsync(d_query, d_train, d_matches, 2);
|
||||
|
||||
CUDA_ON;
|
||||
d_matcher.knnMatchSingle(d_query, d_train, d_trainIdx, d_distance, d_allDist, 2);
|
||||
d_matcher->knnMatchAsync(d_query, d_train, d_matches, 2);
|
||||
CUDA_OFF;
|
||||
|
||||
SUBTEST << "radiusMatch";
|
||||
@ -426,12 +426,10 @@ TEST(BruteForceMatcher)
|
||||
matcher.radiusMatch(query, train, matches, max_distance);
|
||||
CPU_OFF;
|
||||
|
||||
d_trainIdx.release();
|
||||
|
||||
d_matcher.radiusMatchSingle(d_query, d_train, d_trainIdx, d_distance, d_nMatches, max_distance);
|
||||
d_matcher->radiusMatchAsync(d_query, d_train, d_matches, max_distance);
|
||||
|
||||
CUDA_ON;
|
||||
d_matcher.radiusMatchSingle(d_query, d_train, d_trainIdx, d_distance, d_nMatches, max_distance);
|
||||
d_matcher->radiusMatchAsync(d_query, d_train, d_matches, max_distance);
|
||||
CUDA_OFF;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user