1 /*
2 By downloading, copying, installing or using the software you agree to this license.
3 If you do not agree to this license, do not download, install,
4 copy or use the software.
5 
6 
7                           License Agreement
8                For Open Source Computer Vision Library
9                        (3-clause BSD License)
10 
11 Copyright (C) 2000-2016, Intel Corporation, all rights reserved.
12 Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
13 Copyright (C) 2009-2016, NVIDIA Corporation, all rights reserved.
14 Copyright (C) 2010-2013, Advanced Micro Devices, Inc., all rights reserved.
15 Copyright (C) 2015-2016, OpenCV Foundation, all rights reserved.
16 Copyright (C) 2015-2016, Itseez Inc., all rights reserved.
17 Third party copyrights are property of their respective owners.
18 
19 Redistribution and use in source and binary forms, with or without modification,
20 are permitted provided that the following conditions are met:
21 
22   * Redistributions of source code must retain the above copyright notice,
23     this list of conditions and the following disclaimer.
24 
25   * Redistributions in binary form must reproduce the above copyright notice,
26     this list of conditions and the following disclaimer in the documentation
27     and/or other materials provided with the distribution.
28 
29   * Neither the names of the copyright holders nor the names of the contributors
30     may be used to endorse or promote products derived from this software
31     without specific prior written permission.
32 
33 This software is provided by the copyright holders and contributors "as is" and
34 any express or implied warranties, including, but not limited to, the implied
35 warranties of merchantability and fitness for a particular purpose are disclaimed.
36 In no event shall copyright holders or contributors be liable for any direct,
37 indirect, incidental, special, exemplary, or consequential damages
38 (including, but not limited to, procurement of substitute goods or services;
39 loss of use, data, or profits; or business interruption) however caused
40 and on any theory of liability, whether in contract, strict liability,
41 or tort (including negligence or otherwise) arising in any way out of
42 the use of this software, even if advised of the possibility of such damage.
43 */
44 
45 /*
46 Contributed by Gregor Kovalcik <gregor dot kovalcik at gmail dot com>
47     based on code provided by Martin Krulis, Jakub Lokoc and Tomas Skopal.
48 
49 References:
50     Martin Krulis, Jakub Lokoc, Tomas Skopal.
51     Efficient Extraction of Clustering-Based Feature Signatures Using GPU Architectures.
52     Multimedia tools and applications, 75(13), pp.: 8071�8103, Springer, ISSN: 1380-7501, 2016
53 
54     Christian Beecks, Merih Seran Uysal, Thomas Seidl.
55     Signature quadratic form distance.
56     In Proceedings of the ACM International Conference on Image and Video Retrieval, pages 438-445.
57     ACM, 2010.
58 */
59 #include "precomp.hpp"
60 
61 #include "pct_signatures/constants.hpp"
62 #include "pct_signatures/similarity.hpp"
63 
64 namespace cv
65 {
66     namespace xfeatures2d
67     {
68         namespace pct_signatures
69         {
70             class PCTSignaturesSQFD_Impl : public PCTSignaturesSQFD
71             {
72             public:
PCTSignaturesSQFD_Impl(const int distanceFunction,const int similarityFunction,const float similarityParameter)73                 PCTSignaturesSQFD_Impl(
74                     const int distanceFunction,
75                     const int similarityFunction,
76                     const float similarityParameter)
77                     : mDistanceFunction(distanceFunction),
78                     mSimilarityFunction(similarityFunction),
79                     mSimilarityParameter(similarityParameter)
80                 {
81 
82                 }
83 
84 
85                 float computeQuadraticFormDistance(
86                     InputArray _signature0,
87                     InputArray _signature1) const CV_OVERRIDE;
88 
89                 void computeQuadraticFormDistances(
90                     const Mat& sourceSignature,
91                     const std::vector<Mat>& imageSignatures,
92                     std::vector<float>& distances) const CV_OVERRIDE;
93 
94 
95             private:
96                 int mDistanceFunction;
97                 int mSimilarityFunction;
98                 float mSimilarityParameter;
99 
100                 float computePartialSQFD(
101                     const Mat& signature0,
102                     const Mat& signature1) const;
103 
104             };
105 
106 
107             /**
108             * @brief Class implementing parallel computing of SQFD distance for multiple images.
109             */
110             class Parallel_computeSQFDs : public ParallelLoopBody
111             {
112             private:
113                 const PCTSignaturesSQFD* mPctSignaturesSQFDAlgorithm;
114                 const Mat* mSourceSignature;
115                 const std::vector<Mat>* mImageSignatures;
116                 std::vector<float>* mDistances;
117 
118             public:
Parallel_computeSQFDs(const PCTSignaturesSQFD * pctSignaturesSQFDAlgorithm,const Mat * sourceSignature,const std::vector<Mat> * imageSignatures,std::vector<float> * distances)119                 Parallel_computeSQFDs(
120                     const PCTSignaturesSQFD* pctSignaturesSQFDAlgorithm,
121                     const Mat* sourceSignature,
122                     const std::vector<Mat>* imageSignatures,
123                     std::vector<float>* distances)
124                     : mPctSignaturesSQFDAlgorithm(pctSignaturesSQFDAlgorithm),
125                     mSourceSignature(sourceSignature),
126                     mImageSignatures(imageSignatures),
127                     mDistances(distances)
128                 {
129                     mDistances->resize(imageSignatures->size());
130                 }
131 
operator ()(const Range & range) const132                 void operator()(const Range& range) const CV_OVERRIDE
133                 {
134                     if (mSourceSignature->empty())
135                     {
136                         CV_Error(Error::StsBadArg, "Source signature is empty!");
137                     }
138 
139                     for (int i = range.start; i < range.end; i++)
140                     {
141                         if (mImageSignatures[i].empty())
142                         {
143                             CV_Error_(Error::StsBadArg, ("Signature ID: %d is empty!", i));
144                         }
145 
146                         (*mDistances)[i] = mPctSignaturesSQFDAlgorithm->computeQuadraticFormDistance(
147                             *mSourceSignature, (*mImageSignatures)[i]);
148                     }
149                 }
150             };
151 
152 
computeQuadraticFormDistance(InputArray _signature0,InputArray _signature1) const153             float PCTSignaturesSQFD_Impl::computeQuadraticFormDistance(
154                       InputArray _signature0,
155                       InputArray _signature1) const
156             {
157                 // check input
158                 if (_signature0.empty() || _signature1.empty())
159                 {
160                     CV_Error(Error::StsBadArg, "Empty signature!");
161                 }
162 
163                 Mat signature0 = _signature0.getMat();
164                 Mat signature1 = _signature1.getMat();
165 
166                 if (signature0.cols != SIGNATURE_DIMENSION || signature1.cols != SIGNATURE_DIMENSION)
167                 {
168                     CV_Error_(Error::StsBadArg, ("Signature dimension must be %d!", SIGNATURE_DIMENSION));
169                 }
170 
171                 if (signature0.rows <= 0 || signature1.rows <= 0)
172                 {
173                     CV_Error(Error::StsBadArg, "Signature count must be greater than 0!");
174                 }
175 
176                 // compute sqfd
177                 float result = 0;
178                 result += computePartialSQFD(signature0, signature0);
179                 result += computePartialSQFD(signature1, signature1);
180                 result -= computePartialSQFD(signature0, signature1) * 2;
181 
182                 return sqrt(result);
183             }
184 
computeQuadraticFormDistances(const Mat & sourceSignature,const std::vector<Mat> & imageSignatures,std::vector<float> & distances) const185             void PCTSignaturesSQFD_Impl::computeQuadraticFormDistances(
186                       const Mat& sourceSignature,
187                       const std::vector<Mat>& imageSignatures,
188                       std::vector<float>& distances) const
189             {
190                 parallel_for_(Range(0, (int)imageSignatures.size()),
191                     Parallel_computeSQFDs(this, &sourceSignature, &imageSignatures, &distances));
192             }
193 
computePartialSQFD(const Mat & signature0,const Mat & signature1) const194             float PCTSignaturesSQFD_Impl::computePartialSQFD(
195                       const Mat& signature0,
196                       const Mat& signature1) const
197             {
198                 float result = 0;
199                 for (int i = 0; i < signature0.rows; i++)
200                 {
201                     for (int j = 0; j < signature1.rows; j++)
202                     {
203                         result += signature0.at<float>(i, WEIGHT_IDX) * signature1.at<float>(j, WEIGHT_IDX)
204                             * computeSimilarity(mDistanceFunction, mSimilarityFunction, mSimilarityParameter, signature0, i, signature1, j);
205                     }
206                 }
207                 return result;
208             }
209 
210 
211 
212         }// end of namespace pct_signatures
213 
214 
create(const int distanceFunction,const int similarityFunction,const float similarityParameter)215         Ptr<PCTSignaturesSQFD> PCTSignaturesSQFD::create(
216             const int distanceFunction,
217             const int similarityFunction,
218             const float similarityParameter)
219         {
220             return makePtr<pct_signatures::PCTSignaturesSQFD_Impl>(distanceFunction, similarityFunction, similarityParameter);
221         }
222 
223     }
224 }
225