Ocean
Loading...
Searching...
No Matches
ORBFeatureDescriptor.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_CV_DETECTOR_ORB_FEATURE_DESCRIPTOR_H
9#define META_OCEAN_CV_DETECTOR_ORB_FEATURE_DESCRIPTOR_H
10
14
15#include "ocean/base/Frame.h"
16#include "ocean/base/Worker.h"
17
20
21#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 30
22 #include "ocean/cv/SSE.h"
23#endif
24
25#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
26 #include "ocean/cv/NEON.h"
27#endif
28
29namespace Ocean
30{
31
32namespace CV
33{
34
35namespace Detector
36{
37
38/**
39 * This class implements all necessary functions for the ORB feature descriptor and matcher.
40 * @ingroup cvdetector
41 */
42class OCEAN_CV_DETECTOR_EXPORT ORBFeatureDescriptor
43{
44 public:
45
46 /**
47 * Calculate the ORB descriptor for all given feature points.
48 * If sub layers are used, three descriptors are determined per feature. One for the unmodified frame size, one for a resizing factor of sqrt(2) and one for a resizing factor of 1/sqrt(2).
49 * @param linedIntegralFrame Pointer to the (lined) integral frame of the actual 8 bit frame for which the feature descriptors will be calculated, the integral frame has an extra line with zero pixels on the left and top of the integral frame
50 * @param width The width of the original frame in pixel (not the width of the lined-integral frame), with range [43, infinity)
51 * @param height The height of the original frame in pixel (not the height of the lined-integral frame), with range [43, infinity)
52 * @param featurePoints Feature points to calculate the descriptors for, with range [21, width - 22]x[21, height - 22] for 'useMultiLayers == false', with range [31, width - 32]x[31, height - 32] for 'useMultiLayers == true'
53 * @param useMultiLayers True, if two additional sub layers for descriptors are use, create three descriptors per feature point; otherwise, only one layer is used
54 * @param worker Optional worker object to distribute the computation to several CPU cores
55 */
56 static inline void determineDescriptors(const uint32_t* linedIntegralFrame, const unsigned int width, const unsigned int height, ORBFeatures& featurePoints, const bool useMultiLayers = false, Worker* worker = nullptr);
57
58 /**
59 * Detect feature points of the reference frame and calculate the ORB descriptors for them.
60 * Feature points are detect within individual pyramid layers separately, and for each of this feature points three descriptors are calculated.
61 * @param frame The reference frame for which the feature points will be determined, must be valid
62 * @param featurePoints The resulting feature points
63 * @param pyramidLayers The number of pyramid layers to use, with range [1, infinity)
64 * @param useHarrisFeatures True, to use Harris corners; False, to use FAST features
65 * @param featureThreshold The threshold to be used during feature detection, with range [0, 255]
66 * @param worker Optional worker object to distribute the computation to several CPU cores
67 * @return True, if succeeded
68 */
69 static inline bool detectReferenceFeaturesAndDetermineDescriptors(const Frame& frame, ORBFeatures& featurePoints, const unsigned int pyramidLayers, const bool useHarrisFeatures, const unsigned int featureThreshold, Worker* worker);
70
71 /**
72 * Detect feature points in a reference frame and calculate the ORB descriptors for them.
73 * Feature points are detect within individual pyramid layers separately, and for each of this feature points three descriptors are calculated.
74 * @param framePyramid Frame pyramid of the reference frame
75 * @param featurePoints The resulting feature points
76 * @param useHarrisFeatures True, to use Harris corners; False, to use FAST features
77 * @param featureThreshold The threshold to be used during feature detection, with range [0, 255]
78 * @param worker Optional worker object to distribute the computation to several CPU cores
79 */
80 static void detectReferenceFeaturesAndDetermineDescriptors(const FramePyramid& framePyramid, ORBFeatures& featurePoints, const bool useHarrisFeatures, const unsigned int featureThreshold, Worker* worker);
81
82 /**
83 * Determines feature correspondences - one backward feature point for each given forward feature point.
84 * @param forwardFeatures The forward feature points for which corresponding backward features will be determined, at least one
85 * @param backwardFeatures The backward feature points, at least one
86 * @param correspondences The resulting feature correspondences, pairs of feature indices (forward to backward indices)
87 * @param threshold The percentage (in relation to the number of descriptor bits) of the maximal hamming distance so that two descriptors count as similar, with range [0, 1]
88 * @param worker Optional worker object to distribute the computation to several CPU cores
89 */
90 static inline void determineNonBijectiveCorrespondences(const ORBFeatures& forwardFeatures, const ORBFeatures& backwardFeatures, IndexPairs32& correspondences, const float threshold = 0.15f, Worker* worker = nullptr);
91
92 /**
93 * Calculate the hamming distance between two feature descriptors (the number of different bits).
94 * @param referenceDescriptor Reference descriptor
95 * @param featureDescriptor Feature descriptor
96 * @return Hamming distance, with range [0, 256]
97 */
98 static OCEAN_FORCE_INLINE unsigned int calculateHammingDistance(const ORBDescriptor& referenceDescriptor, const ORBDescriptor& featureDescriptor);
99
100 protected:
101
102 /**
103 * Calculate the ORB descriptor for all given feature points.
104 * If sub layers are used, three descriptors are determined per feature. One for the unmodified frame size, one for a resizing factor of sqrt(2) and one for a resizing factor of 1/sqrt(2).
105 * @param linedIntegralFrame Pointer to the (lined) integral frame of the actual 8 bit frame for which the feature descriptors will be calculated, the integral frame has an extra line with zero pixels on the left and top of the integral frame
106 * @param width The width of the original frame in pixel (not the width of the lined-integral frame), with range [43, infinity)
107 * @param height The height of the original frame in pixel (not the height of the lined-integral frame), with range [43, infinity)
108 * @param featurePoints Feature points to calculate the descriptors for, with range [21, width - 22]x[21, height - 22] for 'useMultiLayers == false', with range [31, width - 32]x[31, height - 32] for 'useMultiLayers == true'
109 * @param useMultiLayers True, if two additional sub layers for descriptors are use, create three descriptors per feature point; otherwise, only one layer is used
110 * @param firstFeaturePoint The first feature points to be handled, with range [0, size)
111 * @param numberFeaturePoints The number of feature points to be handled, with range [1, size]
112 */
113 static void determineDescriptorsSubset(const uint32_t* linedIntegralFrame, const unsigned int width, const unsigned int height, ORBFeature* featurePoints, const bool useMultiLayers, const unsigned int firstFeaturePoint, const unsigned int numberFeaturePoints);
114
115 /**
116 * Determines feature correspondences for a subset of forward feature points - one backward feature point for each given forward feature point.
117 * @param forwardFeatures The forward feature points for which corresponding backward features will be determined, must be valid
118 * @param numberForwardFeatures The number of forward feature points, with range [0, infinity)
119 * @param backwardFeatures The backward feature points, must be valid
120 * @param numberBackwardFeatures The number of backward feature points, with range [0, infinity)
121 * @param threshold The percentage (in relation to the number of descriptor bits) of the maximal hamming distance so that two descriptors count as similar, with range [0, 1]
122 * @param correspondences The resulting feature correspondences, pairs of feature indices (forward to backward indices)
123 * @param lock The lock for thread save adding of the match indices, nullptr if the function is executed single-threaded
124 * @param firstIndex First index of the feature point vector to be handled
125 * @param numberIndices Number of feature points to be handled
126 */
127 static void determineNonBijectiveCorrespondencesSubset(const ORBFeature* forwardFeatures, const size_t numberForwardFeatures, const ORBFeature* backwardFeatures, const size_t numberBackwardFeatures, const float threshold, IndexPairs32* correspondences, Lock* lock, const unsigned int firstIndex, const unsigned int numberIndices);
128};
129
130inline void ORBFeatureDescriptor::determineDescriptors(const uint32_t* linedIntegralFrame, const unsigned int width, const unsigned int height, ORBFeatures& featurePoints, const bool useMultiLayers, Worker* worker)
131{
132 ocean_assert(linedIntegralFrame != nullptr);
133 ocean_assert(width >= 43u && height >= 43u);
134
135 if (worker)
136 {
137 worker->executeFunction(Worker::Function::createStatic(&ORBFeatureDescriptor::determineDescriptorsSubset, linedIntegralFrame, width, height, featurePoints.data(), useMultiLayers, 0u, 0u), 0u, (unsigned int)(featurePoints.size()));
138 }
139 else
140 {
141 determineDescriptorsSubset(linedIntegralFrame, width, height, featurePoints.data(), useMultiLayers, 0u, (unsigned int)(featurePoints.size()));
142 }
143}
144
145inline bool ORBFeatureDescriptor::detectReferenceFeaturesAndDetermineDescriptors(const Frame& frame, ORBFeatures& featurePoints, const unsigned int pyramidLayers, const bool useHarrisFeatures, const unsigned int featureThreshold, Worker* worker)
146{
147 Frame yFrame;
149 {
150 return false;
151 }
152
153 const unsigned int maxLayerNumber = FramePyramid::idealLayers(frame.width(), frame.height(), 64u, 64u);
154
155 if (maxLayerNumber == 0u)
156 {
157 return false;
158 }
159
160 const FramePyramid framePyramid(yFrame, std::min(pyramidLayers, maxLayerNumber), false /*copyFirstLayer*/, worker);
161
162 if (!framePyramid.isValid())
163 {
164 return false;
165 }
166
167 detectReferenceFeaturesAndDetermineDescriptors(framePyramid, featurePoints, useHarrisFeatures, featureThreshold, worker);
168
169 return true;
170}
171
172inline void ORBFeatureDescriptor::determineNonBijectiveCorrespondences(const ORBFeatures& forwardFeatures, const ORBFeatures& backwardFeatures, IndexPairs32& correspondences, const float threshold, Worker* worker)
173{
174 ocean_assert(threshold >= 0.0f && threshold <= 1.0f);
175
176 correspondences.reserve(forwardFeatures.size());
177
178 if (worker != nullptr)
179 {
180 Lock lock;
181 worker->executeFunction(Worker::Function::createStatic(&ORBFeatureDescriptor::determineNonBijectiveCorrespondencesSubset, forwardFeatures.data(), forwardFeatures.size(), backwardFeatures.data(), backwardFeatures.size(), threshold, &correspondences, &lock, 0u, 0u), 0u, (unsigned int)(forwardFeatures.size()));
182 }
183 else
184 {
185 determineNonBijectiveCorrespondencesSubset(forwardFeatures.data(), forwardFeatures.size(), backwardFeatures.data(), backwardFeatures.size(), threshold, &correspondences, nullptr, 0u, (unsigned int)(forwardFeatures.size()));
186 }
187}
188
189OCEAN_FORCE_INLINE unsigned int ORBFeatureDescriptor::calculateHammingDistance(const ORBDescriptor& referenceDescriptor, const ORBDescriptor& featureDescriptor)
190{
191 static_assert(sizeof(ORBDescriptor::DescriptorBitset) == 256 / 8, "Invalid descriptor size!");
192
193 return Descriptor::calculateHammingDistance<256>(&referenceDescriptor, &featureDescriptor);
194}
195
196}
197
198}
199
200}
201
202#endif // META_OCEAN_CV_DETECTOR_ORB_FEATURE_DESCRIPTOR_H
This class implement the descriptor for ORB features.
Definition ORBDescriptor.h:41
std::bitset< descriptorLengthInBits > DescriptorBitset
Definition of a bitset with 256 bits.
Definition ORBDescriptor.h:50
This class implements all necessary functions for the ORB feature descriptor and matcher.
Definition ORBFeatureDescriptor.h:43
static void determineNonBijectiveCorrespondencesSubset(const ORBFeature *forwardFeatures, const size_t numberForwardFeatures, const ORBFeature *backwardFeatures, const size_t numberBackwardFeatures, const float threshold, IndexPairs32 *correspondences, Lock *lock, const unsigned int firstIndex, const unsigned int numberIndices)
Determines feature correspondences for a subset of forward feature points - one backward feature poin...
static void detectReferenceFeaturesAndDetermineDescriptors(const FramePyramid &framePyramid, ORBFeatures &featurePoints, const bool useHarrisFeatures, const unsigned int featureThreshold, Worker *worker)
Detect feature points in a reference frame and calculate the ORB descriptors for them.
static void determineNonBijectiveCorrespondences(const ORBFeatures &forwardFeatures, const ORBFeatures &backwardFeatures, IndexPairs32 &correspondences, const float threshold=0.15f, Worker *worker=nullptr)
Determines feature correspondences - one backward feature point for each given forward feature point.
Definition ORBFeatureDescriptor.h:172
static void determineDescriptorsSubset(const uint32_t *linedIntegralFrame, const unsigned int width, const unsigned int height, ORBFeature *featurePoints, const bool useMultiLayers, const unsigned int firstFeaturePoint, const unsigned int numberFeaturePoints)
Calculate the ORB descriptor for all given feature points.
static void determineDescriptors(const uint32_t *linedIntegralFrame, const unsigned int width, const unsigned int height, ORBFeatures &featurePoints, const bool useMultiLayers=false, Worker *worker=nullptr)
Calculate the ORB descriptor for all given feature points.
Definition ORBFeatureDescriptor.h:130
static OCEAN_FORCE_INLINE unsigned int calculateHammingDistance(const ORBDescriptor &referenceDescriptor, const ORBDescriptor &featureDescriptor)
Calculate the hamming distance between two feature descriptors (the number of different bits).
Definition ORBFeatureDescriptor.h:189
static bool detectReferenceFeaturesAndDetermineDescriptors(const Frame &frame, ORBFeatures &featurePoints, const unsigned int pyramidLayers, const bool useHarrisFeatures, const unsigned int featureThreshold, Worker *worker)
Detect feature points of the reference frame and calculate the ORB descriptors for them.
Definition ORBFeatureDescriptor.h:145
This class implements a ORB feature.
Definition ORBFeature.h:40
static bool convert(const Frame &source, const FrameType::PixelFormat targetPixelFormat, const FrameType::PixelOrigin targetPixelOrigin, Frame &target, const bool forceCopy=true, Worker *worker=nullptr, const Options &options=Options())
Converts a frame with arbitrary dimension, pixel format and pixel origin into a frame with the same d...
@ CP_AVOID_COPY_IF_POSSIBLE
Tries to avoid copying the frame data whenever possible.
Definition FrameConverter.h:96
This class implements a frame pyramid.
Definition FramePyramid.h:37
static unsigned int idealLayers(const unsigned int width, const unsigned int height, const unsigned int invalidCoarsestWidthOrHeight, unsigned int *coarsestLayerWidth=nullptr, unsigned int *coarsestLayerHeight=nullptr)
Determines the number of layers until an invalid frame size would be reached in the next layer.
bool isValid() const
Returns whether this pyramid holds at least one frame layer.
Definition FramePyramid.h:863
static Caller< void > createStatic(typename StaticFunctionPointerMaker< void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a static function with no function parameter.
Definition Caller.h:2876
This class implements Ocean's image class.
Definition Frame.h:1808
@ FORMAT_Y8
Pixel format for grayscale images with byte order Y and 8 bits per pixel.
Definition Frame.h:594
unsigned int width() const
Returns the width of the frame format in pixel.
Definition Frame.h:3170
unsigned int height() const
Returns the height of the frame in pixel.
Definition Frame.h:3175
This class implements a recursive lock object.
Definition Lock.h:31
This class implements a worker able to distribute function calls over different threads.
Definition Worker.h:33
bool executeFunction(const Function &function, const unsigned int first, const unsigned int size, const unsigned int firstIndex=(unsigned int)(-1), const unsigned int sizeIndex=(unsigned int)(-1), const unsigned int minimalIterations=1u, const unsigned int threadIndex=(unsigned int)(-1))
Executes a callback function separable by two function parameters.
std::vector< IndexPair32 > IndexPairs32
Definition of a vector holding 32 bit index pairs.
Definition Base.h:144
std::vector< ORBFeature > ORBFeatures
Definition of a vector holding ORB features.
Definition ORBFeature.h:32
The namespace covering the entire Ocean framework.
Definition Accessor.h:15