1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*M///////////////////////////////////////////////////////////////////////////////////////
2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  By downloading, copying, installing or using the software you agree to this license.
6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  If you do not agree to this license, do not download, install,
7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//  copy or use the software.
8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//                        Intel License Agreement
11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//                For Open Source Computer Vision Library
12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Copyright (C) 2000, Intel Corporation, all rights reserved.
14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Third party copyrights are property of their respective owners.
15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// Redistribution and use in source and binary forms, with or without modification,
17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// are permitted provided that the following conditions are met:
18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//   * Redistribution's of source code must retain the above copyright notice,
20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     this list of conditions and the following disclaimer.
21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//   * Redistribution's in binary form must reproduce the above copyright notice,
23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     this list of conditions and the following disclaimer in the documentation
24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     and/or other materials provided with the distribution.
25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//   * The name of Intel Corporation may not be used to endorse or promote products
27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//     derived from this software without specific prior written permission.
28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// This software is provided by the copyright holders and contributors "as is" and
30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// any express or implied warranties, including, but not limited to, the implied
31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// warranties of merchantability and fitness for a particular purpose are disclaimed.
32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// In no event shall the Intel Corporation or contributors be liable for any direct,
33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// indirect, incidental, special, exemplary, or consequential damages
34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// (including, but not limited to, procurement of substitute goods or services;
35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// loss of use, data, or profits; or business interruption) however caused
36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// and on any theory of liability, whether in contract, strict liability,
37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// or tort (including negligence or otherwise) arising in any way out of
38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// the use of this software, even if advised of the possibility of such damage.
39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//
40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler//M*/
41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "precomp.hpp"
43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <limits>
44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencl_kernels_features2d.hpp"
45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if defined(HAVE_EIGEN) && EIGEN_WORLD_VERSION == 2
47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <Eigen/Array>
48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslernamespace cv
51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/////////////////////// ocl functions for BFMatcher ///////////////////////////
54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void ensureSizeIsEnough(int rows, int cols, int type, UMat &m)
56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (m.type() == type && m.rows >= rows && m.cols >= cols)
58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        m = m(Rect(0, 0, cols, rows));
59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        m.create(rows, cols, type);
61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_matchSingle(InputArray query, InputArray train,
64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        UMat &trainIdx, UMat &distance, int distType)
65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (query.empty() || train.empty())
67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int query_rows = query.rows();
70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int query_cols = query.cols();
71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ensureSizeIsEnough(1, query_rows, CV_32S, trainIdx);
73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ensureSizeIsEnough(1, query_rows, CV_32F, distance);
74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Device devDef = ocl::Device::getDefault();
76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat uquery = query.getUMat(), utrain = train.getUMat();
78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int kercn = 1;
79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (devDef.isIntel() &&
80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (0 == (uquery.step % 4)) && (0 == (uquery.cols % 4)) && (0 == (uquery.offset % 4)) &&
81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (0 == (utrain.step % 4)) && (0 == (utrain.cols % 4)) && (0 == (utrain.offset % 4)))
82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        kercn = 4;
83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int block_size = 16;
85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int max_desc_len = 0;
86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool is_cpu = devDef.type() == ocl::Device::TYPE_CPU;
87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (query_cols <= 64)
88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        max_desc_len = 64 / kercn;
89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else if (query_cols <= 128 && !is_cpu)
90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        max_desc_len = 128 / kercn;
91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int depth = query.depth();
93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cv::String opts;
94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    opts = cv::format("-D T=%s -D TN=%s -D kercn=%d %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d -D MAX_DESC_LEN=%d",
95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        ocl::typeToStr(depth), ocl::typeToStr(CV_MAKETYPE(depth, kercn)), kercn, depth == CV_32F ? "-D T_FLOAT" : "", distType, block_size, max_desc_len);
96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Kernel k("BruteForceMatch_Match", ocl::features2d::brute_force_match_oclsrc, opts);
97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(k.empty())
98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t globalSize[] = {(query.size().height + block_size - 1) / block_size * block_size, block_size};
101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t localSize[] = {block_size, block_size};
102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int idx = 0;
104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrReadOnly(uquery));
105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrReadOnly(utrain));
106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(trainIdx));
107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(distance));
108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, uquery.rows);
109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, uquery.cols);
110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, utrain.rows);
111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, utrain.cols);
112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, (int)(uquery.step / sizeof(float)));
113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return k.run(2, globalSize, localSize, false);
115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_matchConvert(const Mat &trainIdx, const Mat &distance, std::vector< std::vector<DMatch> > &matches)
118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (trainIdx.empty() || distance.empty())
120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( (trainIdx.type() != CV_32SC1) || (distance.type() != CV_32FC1 || distance.cols != trainIdx.cols) )
123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int nQuery = trainIdx.cols;
126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matches.clear();
128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matches.reserve(nQuery);
129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int *trainIdx_ptr = trainIdx.ptr<int>();
131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const float *distance_ptr =  distance.ptr<float>();
132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (int queryIdx = 0; queryIdx < nQuery; ++queryIdx, ++trainIdx_ptr, ++distance_ptr)
133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int trainIndex = *trainIdx_ptr;
135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (trainIndex == -1)
137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            continue;
138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        float dst = *distance_ptr;
140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        DMatch m(queryIdx, trainIndex, 0, dst);
142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::vector<DMatch> temp;
144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        temp.push_back(m);
145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matches.push_back(temp);
146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return true;
148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_matchDownload(const UMat &trainIdx, const UMat &distance, std::vector< std::vector<DMatch> > &matches)
151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (trainIdx.empty() || distance.empty())
153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat trainIdxCPU = trainIdx.getMat(ACCESS_READ);
156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat distanceCPU = distance.getMat(ACCESS_READ);
157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return ocl_matchConvert(trainIdxCPU, distanceCPU, matches);
159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_knnMatchSingle(InputArray query, InputArray train, UMat &trainIdx,
162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                               UMat &distance, int distType)
163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (query.empty() || train.empty())
165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int query_rows = query.rows();
168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int query_cols = query.cols();
169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ensureSizeIsEnough(1, query_rows, CV_32SC2, trainIdx);
171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ensureSizeIsEnough(1, query_rows, CV_32FC2, distance);
172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    trainIdx.setTo(Scalar::all(-1));
174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Device devDef = ocl::Device::getDefault();
176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat uquery = query.getUMat(), utrain = train.getUMat();
178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int kercn = 1;
179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (devDef.isIntel() &&
180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (0 == (uquery.step % 4)) && (0 == (uquery.cols % 4)) && (0 == (uquery.offset % 4)) &&
181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (0 == (utrain.step % 4)) && (0 == (utrain.cols % 4)) && (0 == (utrain.offset % 4)))
182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        kercn = 4;
183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int block_size = 16;
185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int max_desc_len = 0;
186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool is_cpu = devDef.type() == ocl::Device::TYPE_CPU;
187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (query_cols <= 64)
188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        max_desc_len = 64 / kercn;
189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else if (query_cols <= 128 && !is_cpu)
190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        max_desc_len = 128 / kercn;
191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int depth = query.depth();
193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cv::String opts;
194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    opts = cv::format("-D T=%s -D TN=%s -D kercn=%d %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d -D MAX_DESC_LEN=%d",
195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        ocl::typeToStr(depth), ocl::typeToStr(CV_MAKETYPE(depth, kercn)), kercn, depth == CV_32F ? "-D T_FLOAT" : "", distType, block_size, max_desc_len);
196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Kernel k("BruteForceMatch_knnMatch", ocl::features2d::brute_force_match_oclsrc, opts);
197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(k.empty())
198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t globalSize[] = {(query_rows + block_size - 1) / block_size * block_size, block_size};
201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t localSize[] = {block_size, block_size};
202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int idx = 0;
204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrReadOnly(uquery));
205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrReadOnly(utrain));
206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(trainIdx));
207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(distance));
208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, uquery.rows);
209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, uquery.cols);
210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, utrain.rows);
211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, utrain.cols);
212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, (int)(uquery.step / sizeof(float)));
213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return k.run(2, globalSize, localSize, false);
215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_knnMatchConvert(const Mat &trainIdx, const Mat &distance, std::vector< std::vector<DMatch> > &matches, bool compactResult)
218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (trainIdx.empty() || distance.empty())
220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(trainIdx.type() != CV_32SC2 && trainIdx.type() != CV_32SC1) return false;
223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(distance.type() != CV_32FC2 && distance.type() != CV_32FC1)return false;
224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(distance.size() != trainIdx.size()) return false;
225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(!trainIdx.isContinuous() || !distance.isContinuous()) return false;
226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int nQuery = trainIdx.type() == CV_32SC2 ? trainIdx.cols : trainIdx.rows;
228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int k = trainIdx.type() == CV_32SC2 ? 2 : trainIdx.cols;
229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matches.clear();
231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matches.reserve(nQuery);
232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int *trainIdx_ptr = trainIdx.ptr<int>();
234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const float *distance_ptr = distance.ptr<float>();
235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (int queryIdx = 0; queryIdx < nQuery; ++queryIdx)
237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matches.push_back(std::vector<DMatch>());
239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::vector<DMatch> &curMatches = matches.back();
240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        curMatches.reserve(k);
241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for (int i = 0; i < k; ++i, ++trainIdx_ptr, ++distance_ptr)
243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            int trainIndex = *trainIdx_ptr;
245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (trainIndex != -1)
247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                float dst = *distance_ptr;
249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                DMatch m(queryIdx, trainIndex, 0, dst);
251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                curMatches.push_back(m);
253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (compactResult && curMatches.empty())
257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            matches.pop_back();
258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return true;
260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_knnMatchDownload(const UMat &trainIdx, const UMat &distance, std::vector< std::vector<DMatch> > &matches, bool compactResult)
263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (trainIdx.empty() || distance.empty())
265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat trainIdxCPU = trainIdx.getMat(ACCESS_READ);
268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat distanceCPU = distance.getMat(ACCESS_READ);
269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return ocl_knnMatchConvert(trainIdxCPU, distanceCPU, matches, compactResult);
271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_radiusMatchSingle(InputArray query, InputArray train,
274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        UMat &trainIdx,   UMat &distance, UMat &nMatches, float maxDistance, int distType)
275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (query.empty() || train.empty())
277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int query_rows = query.rows();
280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int train_rows = train.rows();
281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ensureSizeIsEnough(1, query_rows, CV_32SC1, nMatches);
283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (trainIdx.empty())
285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        ensureSizeIsEnough(query_rows, std::max((train_rows / 100), 10), CV_32SC1, trainIdx);
287793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        ensureSizeIsEnough(query_rows, std::max((train_rows / 100), 10), CV_32FC1, distance);
288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    nMatches.setTo(Scalar::all(0));
291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Device devDef = ocl::Device::getDefault();
293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat uquery = query.getUMat(), utrain = train.getUMat();
294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int kercn = 1;
295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (devDef.isIntel() &&
296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (0 == (uquery.step % 4)) && (0 == (uquery.cols % 4)) && (0 == (uquery.offset % 4)) &&
297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (0 == (utrain.step % 4)) && (0 == (utrain.cols % 4)) && (0 == (utrain.offset % 4)))
298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        kercn = 4;
299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int block_size = 16;
301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int depth = query.depth();
302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cv::String opts;
303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    opts = cv::format("-D T=%s -D TN=%s -D kercn=%d %s -D DIST_TYPE=%d -D BLOCK_SIZE=%d",
304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        ocl::typeToStr(depth), ocl::typeToStr(CV_MAKETYPE(depth, kercn)), kercn, depth == CV_32F ? "-D T_FLOAT" : "", distType, block_size);
305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ocl::Kernel k("BruteForceMatch_RadiusMatch", ocl::features2d::brute_force_match_oclsrc, opts);
306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (k.empty())
307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t globalSize[] = {(train_rows + block_size - 1) / block_size * block_size, (query_rows + block_size - 1) / block_size * block_size};
310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t localSize[] = {block_size, block_size};
311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int idx = 0;
313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrReadOnly(uquery));
314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrReadOnly(utrain));
315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, maxDistance);
316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(trainIdx));
317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(distance));
318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, ocl::KernelArg::PtrWriteOnly(nMatches));
319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, uquery.rows);
320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, uquery.cols);
321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, utrain.rows);
322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, utrain.cols);
323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, trainIdx.cols);
324793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, (int)(uquery.step / sizeof(float)));
325793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    idx = k.set(idx, (int)(trainIdx.step / sizeof(int)));
326793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
327793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return k.run(2, globalSize, localSize, false);
328793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
329793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
330793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_radiusMatchConvert(const Mat &trainIdx, const Mat &distance, const Mat &_nMatches,
331793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::vector< std::vector<DMatch> > &matches, bool compactResult)
332793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
333793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (trainIdx.empty() || distance.empty() || _nMatches.empty())
334793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
335793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
336793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( (trainIdx.type() != CV_32SC1) ||
337793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (distance.type() != CV_32FC1 || distance.size() != trainIdx.size()) ||
338793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (_nMatches.type() != CV_32SC1 || _nMatches.cols != trainIdx.rows) )
339793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
340793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
341793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int nQuery = trainIdx.rows;
342793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
343793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matches.clear();
344793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matches.reserve(nQuery);
345793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
346793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int *nMatches_ptr = _nMatches.ptr<int>();
347793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
348793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (int queryIdx = 0; queryIdx < nQuery; ++queryIdx)
349793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
350793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        const int *trainIdx_ptr = trainIdx.ptr<int>(queryIdx);
351793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        const float *distance_ptr = distance.ptr<float>(queryIdx);
352793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
353793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        const int nMatches = std::min(nMatches_ptr[queryIdx], trainIdx.cols);
354793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
355793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (nMatches == 0)
356793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
357793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (!compactResult)
358793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                matches.push_back(std::vector<DMatch>());
359793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            continue;
360793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
361793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
362793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matches.push_back(std::vector<DMatch>(nMatches));
363793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::vector<DMatch> &curMatches = matches.back();
364793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
365793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for (int i = 0; i < nMatches; ++i, ++trainIdx_ptr, ++distance_ptr)
366793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
367793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            int trainIndex = *trainIdx_ptr;
368793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
369793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            float dst = *distance_ptr;
370793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
371793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            DMatch m(queryIdx, trainIndex, 0, dst);
372793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
373793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            curMatches[i] = m;
374793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
375793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
376793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::sort(curMatches.begin(), curMatches.end());
377793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
378793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return true;
379793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
380793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
381793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_radiusMatchDownload(const UMat &trainIdx, const UMat &distance, const UMat &nMatches,
382793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::vector< std::vector<DMatch> > &matches, bool compactResult)
383793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
384793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (trainIdx.empty() || distance.empty() || nMatches.empty())
385793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
386793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
387793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat trainIdxCPU = trainIdx.getMat(ACCESS_READ);
388793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat distanceCPU = distance.getMat(ACCESS_READ);
389793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat nMatchesCPU = nMatches.getMat(ACCESS_READ);
390793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
391793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return ocl_radiusMatchConvert(trainIdxCPU, distanceCPU, nMatchesCPU, matches, compactResult);
392793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
393793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
394793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/****************************************************************************************\
395793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler*                                      DescriptorMatcher                                 *
396793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler\****************************************************************************************/
397793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerDescriptorMatcher::DescriptorCollection::DescriptorCollection()
398793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{}
399793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
400793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerDescriptorMatcher::DescriptorCollection::DescriptorCollection( const DescriptorCollection& collection )
401793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
402793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    mergedDescriptors = collection.mergedDescriptors.clone();
403793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::copy( collection.startIdxs.begin(), collection.startIdxs.begin(), startIdxs.begin() );
404793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
405793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
406793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerDescriptorMatcher::DescriptorCollection::~DescriptorCollection()
407793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{}
408793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
409793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::DescriptorCollection::set( const std::vector<Mat>& descriptors )
410793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
411793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    clear();
412793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
413793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t imageCount = descriptors.size();
414793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( imageCount > 0 );
415793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
416793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    startIdxs.resize( imageCount );
417793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
418793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int dim = -1;
419793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int type = -1;
420793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    startIdxs[0] = 0;
421793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( size_t i = 1; i < imageCount; i++ )
422793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
423793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int s = 0;
424793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( !descriptors[i-1].empty() )
425793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
426793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            dim = descriptors[i-1].cols;
427793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            type = descriptors[i-1].type();
428793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            s = descriptors[i-1].rows;
429793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
430793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        startIdxs[i] = startIdxs[i-1] + s;
431793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
432793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( imageCount == 1 )
433793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
434793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( descriptors[0].empty() ) return;
435793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
436793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        dim = descriptors[0].cols;
437793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        type = descriptors[0].type();
438793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
439793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( dim > 0 );
440793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
441793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int count = startIdxs[imageCount-1] + descriptors[imageCount-1].rows;
442793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
443793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( count > 0 )
444793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
445793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        mergedDescriptors.create( count, dim, type );
446793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for( size_t i = 0; i < imageCount; i++ )
447793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
448793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if( !descriptors[i].empty() )
449793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
450793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                CV_Assert( descriptors[i].cols == dim && descriptors[i].type() == type );
451793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                Mat m = mergedDescriptors.rowRange( startIdxs[i], startIdxs[i] + descriptors[i].rows );
452793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                descriptors[i].copyTo(m);
453793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
454793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
455793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
456793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
457793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
458793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::DescriptorCollection::clear()
459793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
460793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    startIdxs.clear();
461793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    mergedDescriptors.release();
462793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
463793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
464793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerconst Mat DescriptorMatcher::DescriptorCollection::getDescriptor( int imgIdx, int localDescIdx ) const
465793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
466793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( imgIdx < (int)startIdxs.size() );
467793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int globalIdx = startIdxs[imgIdx] + localDescIdx;
468793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( globalIdx < (int)size() );
469793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
470793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return getDescriptor( globalIdx );
471793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
472793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
473793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerconst Mat& DescriptorMatcher::DescriptorCollection::getDescriptors() const
474793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
475793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return mergedDescriptors;
476793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
477793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
478793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerconst Mat DescriptorMatcher::DescriptorCollection::getDescriptor( int globalDescIdx ) const
479793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
480793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( globalDescIdx < size() );
481793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return mergedDescriptors.row( globalDescIdx );
482793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
483793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
484793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::DescriptorCollection::getLocalIdx( int globalDescIdx, int& imgIdx, int& localDescIdx ) const
485793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
486793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( (globalDescIdx>=0) && (globalDescIdx < size()) );
487793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<int>::const_iterator img_it = std::upper_bound(startIdxs.begin(), startIdxs.end(), globalDescIdx);
488793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    --img_it;
489793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    imgIdx = (int)(img_it - startIdxs.begin());
490793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    localDescIdx = globalDescIdx - (*img_it);
491793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
492793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
493793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerint DescriptorMatcher::DescriptorCollection::size() const
494793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
495793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return mergedDescriptors.rows;
496793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
497793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
498793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
499793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * DescriptorMatcher
500793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
501793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void convertMatches( const std::vector<std::vector<DMatch> >& knnMatches, std::vector<DMatch>& matches )
502793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
503793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matches.clear();
504793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matches.reserve( knnMatches.size() );
505793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( size_t i = 0; i < knnMatches.size(); i++ )
506793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
507793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Assert( knnMatches[i].size() <= 1 );
508793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( !knnMatches[i].empty() )
509793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            matches.push_back( knnMatches[i][0] );
510793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
511793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
512793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
513793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerDescriptorMatcher::~DescriptorMatcher()
514793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{}
515793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
516793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::add( InputArrayOfArrays _descriptors )
517793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
518793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(_descriptors.isUMatVector())
519793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
520793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::vector<UMat> descriptors;
521793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        _descriptors.getUMatVector(descriptors);
522793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        utrainDescCollection.insert( utrainDescCollection.end(), descriptors.begin(), descriptors.end() );
523793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
524793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else if(_descriptors.isUMat())
525793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
526793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::vector<UMat> descriptors = std::vector<UMat>(1, _descriptors.getUMat());
527793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        utrainDescCollection.insert( utrainDescCollection.end(), descriptors.begin(), descriptors.end() );
528793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
529793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else if(_descriptors.isMatVector())
530793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
531793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::vector<Mat> descriptors;
532793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        _descriptors.getMatVector(descriptors);
533793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        trainDescCollection.insert( trainDescCollection.end(), descriptors.begin(), descriptors.end() );
534793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
535793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else if(_descriptors.isMat())
536793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
537793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::vector<Mat> descriptors = std::vector<Mat>(1, _descriptors.getMat());
538793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        trainDescCollection.insert( trainDescCollection.end(), descriptors.begin(), descriptors.end() );
539793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
540793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
541793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Assert( _descriptors.isUMat() || _descriptors.isUMatVector() || _descriptors.isMat() || _descriptors.isMatVector() );
542793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
543793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
544793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerconst std::vector<Mat>& DescriptorMatcher::getTrainDescriptors() const
545793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
546793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return trainDescCollection;
547793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
548793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
549793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::clear()
550793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
551793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    utrainDescCollection.clear();
552793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    trainDescCollection.clear();
553793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
554793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
555793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbool DescriptorMatcher::empty() const
556793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
557793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return trainDescCollection.empty() && utrainDescCollection.empty();
558793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
559793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
560793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::train()
561793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{}
562793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
563793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::match( InputArray queryDescriptors, InputArray trainDescriptors,
564793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                              std::vector<DMatch>& matches, InputArray mask ) const
565793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
566793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Ptr<DescriptorMatcher> tempMatcher = clone(true);
567793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    tempMatcher->add(trainDescriptors);
568793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    tempMatcher->match( queryDescriptors, matches, std::vector<Mat>(1, mask.getMat()) );
569793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
570793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
571793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::knnMatch( InputArray queryDescriptors, InputArray trainDescriptors,
572793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                  std::vector<std::vector<DMatch> >& matches, int knn,
573793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                  InputArray mask, bool compactResult ) const
574793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
575793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Ptr<DescriptorMatcher> tempMatcher = clone(true);
576793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    tempMatcher->add(trainDescriptors);
577793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    tempMatcher->knnMatch( queryDescriptors, matches, knn, std::vector<Mat>(1, mask.getMat()), compactResult );
578793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
579793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
580793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::radiusMatch( InputArray queryDescriptors, InputArray trainDescriptors,
581793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                     std::vector<std::vector<DMatch> >& matches, float maxDistance, InputArray mask,
582793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                     bool compactResult ) const
583793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
584793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Ptr<DescriptorMatcher> tempMatcher = clone(true);
585793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    tempMatcher->add(trainDescriptors);
586793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    tempMatcher->radiusMatch( queryDescriptors, matches, maxDistance, std::vector<Mat>(1, mask.getMat()), compactResult );
587793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
588793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
589793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::match( InputArray queryDescriptors, std::vector<DMatch>& matches, InputArrayOfArrays masks )
590793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
591793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<std::vector<DMatch> > knnMatches;
592793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    knnMatch( queryDescriptors, knnMatches, 1, masks, true /*compactResult*/ );
593793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    convertMatches( knnMatches, matches );
594793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
595793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
596793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::checkMasks( InputArrayOfArrays _masks, int queryDescriptorsCount ) const
597793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
598793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<Mat> masks;
599793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _masks.getMatVector(masks);
600793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
601793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( isMaskSupported() && !masks.empty() )
602793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
603793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        // Check masks
604793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        size_t imageCount = std::max(trainDescCollection.size(), utrainDescCollection.size() );
605793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Assert( masks.size() == imageCount );
606793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for( size_t i = 0; i < imageCount; i++ )
607793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
608793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if( !masks[i].empty() && (!trainDescCollection[i].empty() || !utrainDescCollection[i].empty() ) )
609793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
610793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                int rows = trainDescCollection[i].empty() ? utrainDescCollection[i].rows : trainDescCollection[i].rows;
611793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    CV_Assert( masks[i].rows == queryDescriptorsCount &&
612793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        (masks[i].cols == rows || masks[i].cols == rows) &&
613793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        masks[i].type() == CV_8UC1 );
614793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
615793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
616793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
617793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
618793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
619793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::knnMatch( InputArray queryDescriptors, std::vector<std::vector<DMatch> >& matches, int knn,
620793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                  InputArrayOfArrays masks, bool compactResult )
621793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
622793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( empty() || queryDescriptors.empty() )
623793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return;
624793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
625793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( knn > 0 );
626793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
627793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    checkMasks( masks, queryDescriptors.size().height );
628793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
629793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    train();
630793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    knnMatchImpl( queryDescriptors, matches, knn, masks, compactResult );
631793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
632793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
633793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::radiusMatch( InputArray queryDescriptors, std::vector<std::vector<DMatch> >& matches, float maxDistance,
634793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                     InputArrayOfArrays masks, bool compactResult )
635793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
636793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matches.clear();
637793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( empty() || queryDescriptors.empty() )
638793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return;
639793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
640793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( maxDistance > std::numeric_limits<float>::epsilon() );
641793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
642793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    checkMasks( masks, queryDescriptors.size().height );
643793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
644793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    train();
645793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    radiusMatchImpl( queryDescriptors, matches, maxDistance, masks, compactResult );
646793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
647793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
648793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::read( const FileNode& )
649793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{}
650793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
651793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid DescriptorMatcher::write( FileStorage& ) const
652793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{}
653793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
654793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbool DescriptorMatcher::isPossibleMatch( InputArray _mask, int queryIdx, int trainIdx )
655793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
656793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat mask = _mask.getMat();
657793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return mask.empty() || mask.at<uchar>(queryIdx, trainIdx);
658793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
659793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
660793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbool DescriptorMatcher::isMaskedOut( InputArrayOfArrays _masks, int queryIdx )
661793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
662793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<Mat> masks;
663793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _masks.getMatVector(masks);
664793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
665793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    size_t outCount = 0;
666793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( size_t i = 0; i < masks.size(); i++ )
667793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
668793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( !masks[i].empty() && (countNonZero(masks[i].row(queryIdx)) == 0) )
669793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            outCount++;
670793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
671793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
672793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return !masks.empty() && outCount == masks.size() ;
673793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
674793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
675793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
676793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler////////////////////////////////////////////////////// BruteForceMatcher /////////////////////////////////////////////////
677793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
678793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerBFMatcher::BFMatcher( int _normType, bool _crossCheck )
679793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
680793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    normType = _normType;
681793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    crossCheck = _crossCheck;
682793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
683793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
684793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerPtr<DescriptorMatcher> BFMatcher::clone( bool emptyTrainData ) const
685793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
686793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Ptr<BFMatcher> matcher = makePtr<BFMatcher>(normType, crossCheck);
687793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( !emptyTrainData )
688793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
689793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matcher->trainDescCollection.resize(trainDescCollection.size());
690793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::transform( trainDescCollection.begin(), trainDescCollection.end(),
691793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        matcher->trainDescCollection.begin(), clone_op );
692793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
693793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return matcher;
694793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
695793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
696793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_match(InputArray query, InputArray _train, std::vector< std::vector<DMatch> > &matches, int dstType)
697793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
698793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat trainIdx, distance;
699793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (!ocl_matchSingle(query, _train, trainIdx, distance, dstType))
700793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
701793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (!ocl_matchDownload(trainIdx, distance, matches))
702793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
703793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return true;
704793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
705793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
706793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_knnMatch(InputArray query, InputArray _train, std::vector< std::vector<DMatch> > &matches, int k, int dstType, bool compactResult)
707793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
708793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat trainIdx, distance;
709793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (k != 2)
710793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
711793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (!ocl_knnMatchSingle(query, _train, trainIdx, distance, dstType))
712793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
713793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (!ocl_knnMatchDownload(trainIdx, distance, matches, compactResult) )
714793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
715793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return true;
716793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
717793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
718793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid BFMatcher::knnMatchImpl( InputArray _queryDescriptors, std::vector<std::vector<DMatch> >& matches, int knn,
719793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                             InputArrayOfArrays _masks, bool compactResult )
720793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
721793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int trainDescType = trainDescCollection.empty() ? utrainDescCollection[0].type() : trainDescCollection[0].type();
722793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( _queryDescriptors.type() == trainDescType );
723793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
724793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int IMGIDX_SHIFT = 18;
725793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int IMGIDX_ONE = (1 << IMGIDX_SHIFT);
726793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
727793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( _queryDescriptors.empty() || (trainDescCollection.empty() && utrainDescCollection.empty()))
728793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
729793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matches.clear();
730793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return;
731793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
732793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
733793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<Mat> masks;
734793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _masks.getMatVector(masks);
735793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
736793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(!trainDescCollection.empty() && !utrainDescCollection.empty())
737793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
738793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for(int i = 0; i < (int)utrainDescCollection.size(); i++)
739793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
740793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Mat tempMat;
741793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            utrainDescCollection[i].copyTo(tempMat);
742793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            trainDescCollection.push_back(tempMat);
743793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
744793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        utrainDescCollection.clear();
745793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
746793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
747793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int trainDescVectorSize = trainDescCollection.empty() ? (int)utrainDescCollection.size() : (int)trainDescCollection.size();
748793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size trainDescSize = trainDescCollection.empty() ? utrainDescCollection[0].size() : trainDescCollection[0].size();
749793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int trainDescOffset = trainDescCollection.empty() ? (int)utrainDescCollection[0].offset : 0;
750793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
751793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if ( ocl::useOpenCL() && _queryDescriptors.isUMat() && _queryDescriptors.dims()<=2 && trainDescVectorSize == 1 &&
752793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        _queryDescriptors.type() == CV_32FC1 && _queryDescriptors.offset() == 0 && trainDescOffset == 0 &&
753793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        trainDescSize.width == _queryDescriptors.size().width && masks.size() == 1 && masks[0].total() == 0 )
754793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
755793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if(knn == 1)
756793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
757793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if(trainDescCollection.empty())
758793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
759793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if(ocl_match(_queryDescriptors, utrainDescCollection[0], matches, normType))
760793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
761793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    CV_IMPL_ADD(CV_IMPL_OCL);
762793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    return;
763793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
764793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
765793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            else
766793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
767793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if(ocl_match(_queryDescriptors, trainDescCollection[0], matches, normType))
768793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
769793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    CV_IMPL_ADD(CV_IMPL_OCL);
770793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    return;
771793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
772793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
773793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
774793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        else
775793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
776793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if(trainDescCollection.empty())
777793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
778793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if(ocl_knnMatch(_queryDescriptors, utrainDescCollection[0], matches, knn, normType, compactResult) )
779793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
780793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    CV_IMPL_ADD(CV_IMPL_OCL);
781793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    return;
782793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
783793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
784793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            else
785793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
786793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if(ocl_knnMatch(_queryDescriptors, trainDescCollection[0], matches, knn, normType, compactResult) )
787793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                {
788793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    CV_IMPL_ADD(CV_IMPL_OCL);
789793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    return;
790793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                }
791793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
792793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
793793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
794793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
795793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat queryDescriptors = _queryDescriptors.getMat();
796793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(trainDescCollection.empty() && !utrainDescCollection.empty())
797793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
798793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for(int i = 0; i < (int)utrainDescCollection.size(); i++)
799793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
800793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Mat tempMat;
801793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            utrainDescCollection[i].copyTo(tempMat);
802793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            trainDescCollection.push_back(tempMat);
803793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
804793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        utrainDescCollection.clear();
805793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
806793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
807793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matches.reserve(queryDescriptors.rows);
808793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
809793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat dist, nidx;
810793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
811793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int iIdx, imgCount = (int)trainDescCollection.size(), update = 0;
812793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int dtype = normType == NORM_HAMMING || normType == NORM_HAMMING2 ||
813793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (normType == NORM_L1 && queryDescriptors.type() == CV_8U) ? CV_32S : CV_32F;
814793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
815793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( (int64)imgCount*IMGIDX_ONE < INT_MAX );
816793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
817793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( iIdx = 0; iIdx < imgCount; iIdx++ )
818793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
819793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Assert( trainDescCollection[iIdx].rows < IMGIDX_ONE );
820793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        batchDistance(queryDescriptors, trainDescCollection[iIdx], dist, dtype, nidx,
821793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                      normType, knn, masks.empty() ? Mat() : masks[iIdx], update, crossCheck);
822793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        update += IMGIDX_ONE;
823793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
824793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
825793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( dtype == CV_32S )
826793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
827793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat temp;
828793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        dist.convertTo(temp, CV_32F);
829793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        dist = temp;
830793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
831793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
832793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
833793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
834793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        const float* distptr = dist.ptr<float>(qIdx);
835793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        const int* nidxptr = nidx.ptr<int>(qIdx);
836793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
837793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matches.push_back( std::vector<DMatch>() );
838793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::vector<DMatch>& mq = matches.back();
839793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        mq.reserve(knn);
840793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
841793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for( int k = 0; k < nidx.cols; k++ )
842793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
843793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if( nidxptr[k] < 0 )
844793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
845793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            mq.push_back( DMatch(qIdx, nidxptr[k] & (IMGIDX_ONE - 1),
846793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                          nidxptr[k] >> IMGIDX_SHIFT, distptr[k]) );
847793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
848793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
849793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( mq.empty() && compactResult )
850793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            matches.pop_back();
851793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
852793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
853793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
854793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic bool ocl_radiusMatch(InputArray query, InputArray _train, std::vector< std::vector<DMatch> > &matches,
855793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        float maxDistance, int dstType, bool compactResult)
856793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
857793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    UMat trainIdx, distance, nMatches;
858793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (!ocl_radiusMatchSingle(query, _train, trainIdx, distance, nMatches, maxDistance, dstType))
859793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
860793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (!ocl_radiusMatchDownload(trainIdx, distance, nMatches, matches, compactResult))
861793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return false;
862793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return true;
863793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
864793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
865793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid BFMatcher::radiusMatchImpl( InputArray _queryDescriptors, std::vector<std::vector<DMatch> >& matches,
866793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                float maxDistance, InputArrayOfArrays _masks, bool compactResult )
867793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
868793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int trainDescType = trainDescCollection.empty() ? utrainDescCollection[0].type() : trainDescCollection[0].type();
869793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( _queryDescriptors.type() == trainDescType );
870793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
871793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( _queryDescriptors.empty() || (trainDescCollection.empty() && utrainDescCollection.empty()))
872793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
873793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matches.clear();
874793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return;
875793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
876793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
877793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<Mat> masks;
878793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _masks.getMatVector(masks);
879793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
880793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(!trainDescCollection.empty() && !utrainDescCollection.empty())
881793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
882793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for(int i = 0; i < (int)utrainDescCollection.size(); i++)
883793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
884793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Mat tempMat;
885793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            utrainDescCollection[i].copyTo(tempMat);
886793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            trainDescCollection.push_back(tempMat);
887793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
888793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        utrainDescCollection.clear();
889793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
890793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
891793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int trainDescVectorSize = trainDescCollection.empty() ? (int)utrainDescCollection.size() : (int)trainDescCollection.size();
892793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size trainDescSize = trainDescCollection.empty() ? utrainDescCollection[0].size() : trainDescCollection[0].size();
893793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int trainDescOffset = trainDescCollection.empty() ? (int)utrainDescCollection[0].offset : 0;
894793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
895793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if ( ocl::useOpenCL() && _queryDescriptors.isUMat() && _queryDescriptors.dims()<=2 && trainDescVectorSize == 1 &&
896793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        _queryDescriptors.type() == CV_32FC1 && _queryDescriptors.offset() == 0 && trainDescOffset == 0 &&
897793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        trainDescSize.width == _queryDescriptors.size().width && masks.size() == 1 && masks[0].total() == 0 )
898793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
899793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (trainDescCollection.empty())
900793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
901793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if(ocl_radiusMatch(_queryDescriptors, utrainDescCollection[0], matches, maxDistance, normType, compactResult) )
902793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
903793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                CV_IMPL_ADD(CV_IMPL_OCL);
904793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                return;
905793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
906793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
907793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        else
908793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
909793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (ocl_radiusMatch(_queryDescriptors, trainDescCollection[0], matches, maxDistance, normType, compactResult) )
910793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
911793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                CV_IMPL_ADD(CV_IMPL_OCL);
912793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                return;
913793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
914793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
915793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
916793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
917793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat queryDescriptors = _queryDescriptors.getMat();
918793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if(trainDescCollection.empty() && !utrainDescCollection.empty())
919793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
920793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for(int i = 0; i < (int)utrainDescCollection.size(); i++)
921793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
922793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Mat tempMat;
923793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            utrainDescCollection[i].copyTo(tempMat);
924793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            trainDescCollection.push_back(tempMat);
925793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
926793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        utrainDescCollection.clear();
927793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
928793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
929793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matches.resize(queryDescriptors.rows);
930793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat dist, distf;
931793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
932793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int iIdx, imgCount = (int)trainDescCollection.size();
933793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int dtype = normType == NORM_HAMMING ||
934793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (normType == NORM_L1 && queryDescriptors.type() == CV_8U) ? CV_32S : CV_32F;
935793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
936793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( iIdx = 0; iIdx < imgCount; iIdx++ )
937793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
938793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        batchDistance(queryDescriptors, trainDescCollection[iIdx], dist, dtype, noArray(),
939793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                      normType, 0, masks.empty() ? Mat() : masks[iIdx], 0, false);
940793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( dtype == CV_32S )
941793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            dist.convertTo(distf, CV_32F);
942793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        else
943793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            distf = dist;
944793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
945793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
946793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
947793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            const float* distptr = distf.ptr<float>(qIdx);
948793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
949793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            std::vector<DMatch>& mq = matches[qIdx];
950793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            for( int k = 0; k < distf.cols; k++ )
951793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
952793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if( distptr[k] <= maxDistance )
953793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    mq.push_back( DMatch(qIdx, k, iIdx, distptr[k]) );
954793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
955793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
956793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
957793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
958793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int qIdx0 = 0;
959793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
960793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
961793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( matches[qIdx].empty() && compactResult )
962793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            continue;
963793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
964793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if( qIdx0 < qIdx )
965793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            std::swap(matches[qIdx], matches[qIdx0]);
966793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
967793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::sort( matches[qIdx0].begin(), matches[qIdx0].end() );
968793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        qIdx0++;
969793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
970793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
971793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
972793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler///////////////////////////////////////////////////////////////////////////////////////////////////////
973793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
974793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
975793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Factory function for DescriptorMatcher creating
976793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
977793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerPtr<DescriptorMatcher> DescriptorMatcher::create( const String& descriptorMatcherType )
978793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
979793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Ptr<DescriptorMatcher> dm;
980793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( !descriptorMatcherType.compare( "FlannBased" ) )
981793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
982793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        dm = makePtr<FlannBasedMatcher>();
983793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
984793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else if( !descriptorMatcherType.compare( "BruteForce" ) ) // L2
985793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
986793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        dm = makePtr<BFMatcher>(int(NORM_L2)); // anonymous enums can't be template parameters
987793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
988793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else if( !descriptorMatcherType.compare( "BruteForce-SL2" ) ) // Squared L2
989793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
990793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        dm = makePtr<BFMatcher>(int(NORM_L2SQR));
991793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
992793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else if( !descriptorMatcherType.compare( "BruteForce-L1" ) )
993793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
994793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        dm = makePtr<BFMatcher>(int(NORM_L1));
995793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
996793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else if( !descriptorMatcherType.compare("BruteForce-Hamming") ||
997793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             !descriptorMatcherType.compare("BruteForce-HammingLUT") )
998793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
999793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        dm = makePtr<BFMatcher>(int(NORM_HAMMING));
1000793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1001793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else if( !descriptorMatcherType.compare("BruteForce-Hamming(2)") )
1002793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
1003793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        dm = makePtr<BFMatcher>(int(NORM_HAMMING2));
1004793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1005793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
1006793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Error( Error::StsBadArg, "Unknown matcher name" );
1007793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1008793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return dm;
1009793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1010793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1011793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1012793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
1013793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Flann based matcher
1014793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
1015793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerFlannBasedMatcher::FlannBasedMatcher( const Ptr<flann::IndexParams>& _indexParams, const Ptr<flann::SearchParams>& _searchParams )
1016793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    : indexParams(_indexParams), searchParams(_searchParams), addedDescCount(0)
1017793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1018793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( _indexParams );
1019793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    CV_Assert( _searchParams );
1020793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1021793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1022793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid FlannBasedMatcher::add( InputArrayOfArrays _descriptors )
1023793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1024793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    DescriptorMatcher::add( _descriptors );
1025793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    std::vector<UMat> descriptors;
1026793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    _descriptors.getUMatVector(descriptors);
1027793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1028793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( size_t i = 0; i < descriptors.size(); i++ )
1029793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
1030793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        addedDescCount += descriptors[i].rows;
1031793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1032793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1033793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1034793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid FlannBasedMatcher::clear()
1035793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1036793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    DescriptorMatcher::clear();
1037793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1038793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    mergedDescriptors.clear();
1039793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    flannIndex.release();
1040793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1041793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    addedDescCount = 0;
1042793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1043793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1044793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid FlannBasedMatcher::train()
1045793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1046793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( !flannIndex || mergedDescriptors.size() < addedDescCount )
1047793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
1048793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        // FIXIT: Workaround for 'utrainDescCollection' issue (PR #2142)
1049793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (!utrainDescCollection.empty())
1050793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
1051793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            CV_Assert(trainDescCollection.size() == 0);
1052793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            for (size_t i = 0; i < utrainDescCollection.size(); ++i)
1053793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                trainDescCollection.push_back(utrainDescCollection[i].getMat(ACCESS_READ));
1054793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1055793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        mergedDescriptors.set( trainDescCollection );
1056793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        flannIndex = makePtr<flann::Index>( mergedDescriptors.getDescriptors(), *indexParams );
1057793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1058793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1059793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1060793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid FlannBasedMatcher::read( const FileNode& fn)
1061793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1062793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (!indexParams)
1063793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         indexParams = makePtr<flann::IndexParams>();
1064793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1065793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     FileNode ip = fn["indexParams"];
1066793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     CV_Assert(ip.type() == FileNode::SEQ);
1067793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1068793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     for(int i = 0; i < (int)ip.size(); ++i)
1069793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     {
1070793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Assert(ip[i].type() == FileNode::MAP);
1071793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        String _name =  (String)ip[i]["name"];
1072793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int type =  (int)ip[i]["type"];
1073793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1074793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        switch(type)
1075793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
1076793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_8U:
1077793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_8S:
1078793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_16U:
1079793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_16S:
1080793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_32S:
1081793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            indexParams->setInt(_name, (int) ip[i]["value"]);
1082793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
1083793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_32F:
1084793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            indexParams->setFloat(_name, (float) ip[i]["value"]);
1085793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
1086793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_64F:
1087793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            indexParams->setDouble(_name, (double) ip[i]["value"]);
1088793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
1089793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_USRTYPE1:
1090793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            indexParams->setString(_name, (String) ip[i]["value"]);
1091793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
1092793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_MAKETYPE(CV_USRTYPE1,2):
1093793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            indexParams->setBool(_name, (int) ip[i]["value"] != 0);
1094793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
1095793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_MAKETYPE(CV_USRTYPE1,3):
1096793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            indexParams->setAlgorithm((int) ip[i]["value"]);
1097793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
1098793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        };
1099793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (!searchParams)
1102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         searchParams = makePtr<flann::SearchParams>();
1103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     FileNode sp = fn["searchParams"];
1105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     CV_Assert(sp.type() == FileNode::SEQ);
1106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     for(int i = 0; i < (int)sp.size(); ++i)
1108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     {
1109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Assert(sp[i].type() == FileNode::MAP);
1110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        String _name =  (String)sp[i]["name"];
1111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        int type =  (int)sp[i]["type"];
1112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        switch(type)
1114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
1115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_8U:
1116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_8S:
1117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_16U:
1118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_16S:
1119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_32S:
1120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            searchParams->setInt(_name, (int) sp[i]["value"]);
1121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
1122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_32F:
1123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            searchParams->setFloat(_name, (float) ip[i]["value"]);
1124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
1125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_64F:
1126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            searchParams->setDouble(_name, (double) ip[i]["value"]);
1127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
1128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_USRTYPE1:
1129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            searchParams->setString(_name, (String) ip[i]["value"]);
1130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
1131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_MAKETYPE(CV_USRTYPE1,2):
1132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            searchParams->setBool(_name, (int) ip[i]["value"] != 0);
1133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
1134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case CV_MAKETYPE(CV_USRTYPE1,3):
1135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            searchParams->setAlgorithm((int) ip[i]["value"]);
1136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
1137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        };
1138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    flannIndex.release();
1141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid FlannBasedMatcher::write( FileStorage& fs) const
1144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     fs << "indexParams" << "[";
1146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (indexParams)
1148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     {
1149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         std::vector<String> names;
1150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         std::vector<int> types;
1151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         std::vector<String> strValues;
1152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         std::vector<double> numValues;
1153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         indexParams->getAll(names, types, strValues, numValues);
1155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         for(size_t i = 0; i < names.size(); ++i)
1157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         {
1158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             fs << "{" << "name" << names[i] << "type" << types[i] << "value";
1159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             switch(types[i])
1160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             {
1161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_8U:
1162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (uchar)numValues[i];
1163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_8S:
1165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (char)numValues[i];
1166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_16U:
1168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (ushort)numValues[i];
1169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_16S:
1171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (short)numValues[i];
1172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_32S:
1174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_MAKETYPE(CV_USRTYPE1,2):
1175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_MAKETYPE(CV_USRTYPE1,3):
1176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (int)numValues[i];
1177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_32F:
1179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (float)numValues[i];
1180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_64F:
1182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (double)numValues[i];
1183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_USRTYPE1:
1185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << strValues[i];
1186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             default:
1188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (double)numValues[i];
1189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << "typename" << strValues[i];
1190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             }
1192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             fs << "}";
1193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         }
1194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     fs << "]" << "searchParams" << "[";
1197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     if (searchParams)
1199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     {
1200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         std::vector<String> names;
1201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         std::vector<int> types;
1202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         std::vector<String> strValues;
1203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         std::vector<double> numValues;
1204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         searchParams->getAll(names, types, strValues, numValues);
1206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         for(size_t i = 0; i < names.size(); ++i)
1208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         {
1209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             fs << "{" << "name" << names[i] << "type" << types[i] << "value";
1210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             switch(types[i])
1211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             {
1212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_8U:
1213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (uchar)numValues[i];
1214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_8S:
1216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (char)numValues[i];
1217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_16U:
1219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (ushort)numValues[i];
1220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_16S:
1222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (short)numValues[i];
1223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_32S:
1225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_MAKETYPE(CV_USRTYPE1,2):
1226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_MAKETYPE(CV_USRTYPE1,3):
1227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (int)numValues[i];
1228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_32F:
1230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (float)numValues[i];
1231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_64F:
1233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (double)numValues[i];
1234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             case CV_USRTYPE1:
1236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << strValues[i];
1237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             default:
1239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << (double)numValues[i];
1240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 fs << "typename" << strValues[i];
1241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 break;
1242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             }
1243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             fs << "}";
1244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler         }
1245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     }
1246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler     fs << "]";
1247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbool FlannBasedMatcher::isMaskSupported() const
1250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return false;
1252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1254793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerPtr<DescriptorMatcher> FlannBasedMatcher::clone( bool emptyTrainData ) const
1255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Ptr<FlannBasedMatcher> matcher = makePtr<FlannBasedMatcher>(indexParams, searchParams);
1257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if( !emptyTrainData )
1258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
1259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Error( Error::StsNotImplemented, "deep clone functionality is not implemented, because "
1260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  "Flann::Index has not copy constructor or clone method ");
1261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        //matcher->flannIndex;
1262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matcher->addedDescCount = addedDescCount;
1263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matcher->mergedDescriptors = DescriptorCollection( mergedDescriptors );
1264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        std::transform( trainDescCollection.begin(), trainDescCollection.end(),
1265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                        matcher->trainDescCollection.begin(), clone_op );
1266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return matcher;
1268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid FlannBasedMatcher::convertToDMatches( const DescriptorCollection& collection, const Mat& indices, const Mat& dists,
1271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                           std::vector<std::vector<DMatch> >& matches )
1272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matches.resize( indices.rows );
1274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( int i = 0; i < indices.rows; i++ )
1275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
1276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for( int j = 0; j < indices.cols; j++ )
1277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
1278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            int idx = indices.at<int>(i, j);
1279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if( idx >= 0 )
1280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
1281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                int imgIdx, trainIdx;
1282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                collection.getLocalIdx( idx, imgIdx, trainIdx );
1283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                float dist = 0;
1284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                if (dists.type() == CV_32S)
1285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    dist = static_cast<float>( dists.at<int>(i,j) );
1286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                else
1287793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    dist = std::sqrt(dists.at<float>(i,j));
1288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                matches[i].push_back( DMatch( i, trainIdx, imgIdx, dist ) );
1289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
1290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
1291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid FlannBasedMatcher::knnMatchImpl( InputArray _queryDescriptors, std::vector<std::vector<DMatch> >& matches, int knn,
1295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                     InputArrayOfArrays /*masks*/, bool /*compactResult*/ )
1296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat queryDescriptors = _queryDescriptors.getMat();
1298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat indices( queryDescriptors.rows, knn, CV_32SC1 );
1299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat dists( queryDescriptors.rows, knn, CV_32FC1);
1300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    flannIndex->knnSearch( queryDescriptors, indices, dists, knn, *searchParams );
1301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    convertToDMatches( mergedDescriptors, indices, dists, matches );
1303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslervoid FlannBasedMatcher::radiusMatchImpl( InputArray _queryDescriptors, std::vector<std::vector<DMatch> >& matches, float maxDistance,
1306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                         InputArrayOfArrays /*masks*/, bool /*compactResult*/ )
1307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
1308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat queryDescriptors = _queryDescriptors.getMat();
1309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    const int count = mergedDescriptors.size(); // TODO do count as param?
1310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat indices( queryDescriptors.rows, count, CV_32SC1, Scalar::all(-1) );
1311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat dists( queryDescriptors.rows, count, CV_32FC1, Scalar::all(-1) );
1312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for( int qIdx = 0; qIdx < queryDescriptors.rows; qIdx++ )
1313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
1314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat queryDescriptorsRow = queryDescriptors.row(qIdx);
1315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat indicesRow = indices.row(qIdx);
1316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        Mat distsRow = dists.row(qIdx);
1317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        flannIndex->radiusSearch( queryDescriptorsRow, indicesRow, distsRow, maxDistance*maxDistance, count, *searchParams );
1318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
1319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    convertToDMatches( mergedDescriptors, indices, dists, matches );
1321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
1323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
1324