1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2008, Willow Garage Inc., all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41 
42 /*
43 OpenCV wrapper of reference implementation of
44 [1] Fast Explicit Diffusion for Accelerated Features in Nonlinear Scale Spaces.
45 Pablo F. Alcantarilla, J. Nuevo and Adrien Bartoli.
46 In British Machine Vision Conference (BMVC), Bristol, UK, September 2013
47 http://www.robesafe.com/personal/pablo.alcantarilla/papers/Alcantarilla13bmvc.pdf
48 @author Eugene Khvedchenya <ekhvedchenya@gmail.com>
49 */
50 
51 #include "precomp.hpp"
52 #include "kaze/AKAZEFeatures.h"
53 
54 #include <iostream>
55 
56 namespace cv
57 {
58     using namespace std;
59 
60     class AKAZE_Impl : public AKAZE
61     {
62     public:
AKAZE_Impl(int _descriptor_type,int _descriptor_size,int _descriptor_channels,float _threshold,int _octaves,int _sublevels,int _diffusivity)63         AKAZE_Impl(int _descriptor_type, int _descriptor_size, int _descriptor_channels,
64                  float _threshold, int _octaves, int _sublevels, int _diffusivity)
65         : descriptor(_descriptor_type)
66         , descriptor_channels(_descriptor_channels)
67         , descriptor_size(_descriptor_size)
68         , threshold(_threshold)
69         , octaves(_octaves)
70         , sublevels(_sublevels)
71         , diffusivity(_diffusivity)
72         {
73         }
74 
~AKAZE_Impl()75         virtual ~AKAZE_Impl()
76         {
77 
78         }
79 
setDescriptorType(int dtype)80         void setDescriptorType(int dtype) { descriptor = dtype; }
getDescriptorType() const81         int getDescriptorType() const { return descriptor; }
82 
setDescriptorSize(int dsize)83         void setDescriptorSize(int dsize) { descriptor_size = dsize; }
getDescriptorSize() const84         int getDescriptorSize() const { return descriptor_size; }
85 
setDescriptorChannels(int dch)86         void setDescriptorChannels(int dch) { descriptor_channels = dch; }
getDescriptorChannels() const87         int getDescriptorChannels() const { return descriptor_channels; }
88 
setThreshold(double threshold_)89         void setThreshold(double threshold_) { threshold = (float)threshold_; }
getThreshold() const90         double getThreshold() const { return threshold; }
91 
setNOctaves(int octaves_)92         void setNOctaves(int octaves_) { octaves = octaves_; }
getNOctaves() const93         int getNOctaves() const { return octaves; }
94 
setNOctaveLayers(int octaveLayers_)95         void setNOctaveLayers(int octaveLayers_) { sublevels = octaveLayers_; }
getNOctaveLayers() const96         int getNOctaveLayers() const { return sublevels; }
97 
setDiffusivity(int diff_)98         void setDiffusivity(int diff_) { diffusivity = diff_; }
getDiffusivity() const99         int getDiffusivity() const { return diffusivity; }
100 
101         // returns the descriptor size in bytes
descriptorSize() const102         int descriptorSize() const
103         {
104             switch (descriptor)
105             {
106             case DESCRIPTOR_KAZE:
107             case DESCRIPTOR_KAZE_UPRIGHT:
108                 return 64;
109 
110             case DESCRIPTOR_MLDB:
111             case DESCRIPTOR_MLDB_UPRIGHT:
112                 // We use the full length binary descriptor -> 486 bits
113                 if (descriptor_size == 0)
114                 {
115                     int t = (6 + 36 + 120) * descriptor_channels;
116                     return (int)ceil(t / 8.);
117                 }
118                 else
119                 {
120                     // We use the random bit selection length binary descriptor
121                     return (int)ceil(descriptor_size / 8.);
122                 }
123 
124             default:
125                 return -1;
126             }
127         }
128 
129         // returns the descriptor type
descriptorType() const130         int descriptorType() const
131         {
132             switch (descriptor)
133             {
134             case DESCRIPTOR_KAZE:
135             case DESCRIPTOR_KAZE_UPRIGHT:
136                     return CV_32F;
137 
138             case DESCRIPTOR_MLDB:
139             case DESCRIPTOR_MLDB_UPRIGHT:
140                     return CV_8U;
141 
142                 default:
143                     return -1;
144             }
145         }
146 
147         // returns the default norm type
defaultNorm() const148         int defaultNorm() const
149         {
150             switch (descriptor)
151             {
152             case DESCRIPTOR_KAZE:
153             case DESCRIPTOR_KAZE_UPRIGHT:
154                 return NORM_L2;
155 
156             case DESCRIPTOR_MLDB:
157             case DESCRIPTOR_MLDB_UPRIGHT:
158                 return NORM_HAMMING;
159 
160             default:
161                 return -1;
162             }
163         }
164 
detectAndCompute(InputArray image,InputArray mask,std::vector<KeyPoint> & keypoints,OutputArray descriptors,bool useProvidedKeypoints)165         void detectAndCompute(InputArray image, InputArray mask,
166                               std::vector<KeyPoint>& keypoints,
167                               OutputArray descriptors,
168                               bool useProvidedKeypoints)
169         {
170             Mat img = image.getMat();
171             if (img.type() != CV_8UC1)
172                 cvtColor(image, img, COLOR_BGR2GRAY);
173 
174             Mat img1_32;
175             if ( img.depth() == CV_32F )
176                 img1_32 = img;
177             else if ( img.depth() == CV_8U )
178                 img.convertTo(img1_32, CV_32F, 1.0 / 255.0, 0);
179             else if ( img.depth() == CV_16U )
180                 img.convertTo(img1_32, CV_32F, 1.0 / 65535.0, 0);
181 
182             CV_Assert( ! img1_32.empty() );
183 
184             AKAZEOptions options;
185             options.descriptor = descriptor;
186             options.descriptor_channels = descriptor_channels;
187             options.descriptor_size = descriptor_size;
188             options.img_width = img.cols;
189             options.img_height = img.rows;
190             options.dthreshold = threshold;
191             options.omax = octaves;
192             options.nsublevels = sublevels;
193             options.diffusivity = diffusivity;
194 
195             AKAZEFeatures impl(options);
196             impl.Create_Nonlinear_Scale_Space(img1_32);
197 
198             if (!useProvidedKeypoints)
199             {
200                 impl.Feature_Detection(keypoints);
201             }
202 
203             if (!mask.empty())
204             {
205                 KeyPointsFilter::runByPixelsMask(keypoints, mask.getMat());
206             }
207 
208             if( descriptors.needed() )
209             {
210                 Mat& desc = descriptors.getMatRef();
211                 impl.Compute_Descriptors(keypoints, desc);
212 
213                 CV_Assert((!desc.rows || desc.cols == descriptorSize()));
214                 CV_Assert((!desc.rows || (desc.type() == descriptorType())));
215             }
216         }
217 
write(FileStorage & fs) const218         void write(FileStorage& fs) const
219         {
220             fs << "descriptor" << descriptor;
221             fs << "descriptor_channels" << descriptor_channels;
222             fs << "descriptor_size" << descriptor_size;
223             fs << "threshold" << threshold;
224             fs << "octaves" << octaves;
225             fs << "sublevels" << sublevels;
226             fs << "diffusivity" << diffusivity;
227         }
228 
read(const FileNode & fn)229         void read(const FileNode& fn)
230         {
231             descriptor = (int)fn["descriptor"];
232             descriptor_channels = (int)fn["descriptor_channels"];
233             descriptor_size = (int)fn["descriptor_size"];
234             threshold = (float)fn["threshold"];
235             octaves = (int)fn["octaves"];
236             sublevels = (int)fn["sublevels"];
237             diffusivity = (int)fn["diffusivity"];
238         }
239 
240         int descriptor;
241         int descriptor_channels;
242         int descriptor_size;
243         float threshold;
244         int octaves;
245         int sublevels;
246         int diffusivity;
247     };
248 
create(int descriptor_type,int descriptor_size,int descriptor_channels,float threshold,int octaves,int sublevels,int diffusivity)249     Ptr<AKAZE> AKAZE::create(int descriptor_type,
250                              int descriptor_size, int descriptor_channels,
251                              float threshold, int octaves,
252                              int sublevels, int diffusivity)
253     {
254         return makePtr<AKAZE_Impl>(descriptor_type, descriptor_size, descriptor_channels,
255                                    threshold, octaves, sublevels, diffusivity);
256     }
257 }
258