Ocean
offline/Frame2FrameTracker.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_TRACKING_OFFLINE_FRAME_2_FRAME_TRACKER_H
9 #define META_OCEAN_TRACKING_OFFLINE_FRAME_2_FRAME_TRACKER_H
10 
12 
13 #include "ocean/base/Worker.h"
14 
15 #include "ocean/cv/FramePyramid.h"
16 
18 
20 
23 
24 namespace Ocean
25 {
26 
27 namespace Tracking
28 {
29 
30 namespace Offline
31 {
32 
33 /**
34  * This class implements a tracker allowing to tracker feature points between two frames.
35  * @ingroup trackingoffline
36  */
37 class OCEAN_TRACKING_OFFLINE_EXPORT Frame2FrameTracker
38 {
39  public:
40 
41  /**
42  * This function tracks a planar plane or object between two successive frames.
43  * @param pinholeCamera The pinhole camera object defining the projection
44  * @param previousPose Pose of the previous frame
45  * @param previousPlane 3D plane that specifies the planar object in the previous frame
46  * @param previousImagePoints Image points located in the previous frame all lying on a 3D plane
47  * @param nextImagePoints Image points located in the next frame, each point corresponds to a point in the previous frame, by index
48  * @param correspondences The number of points correspondences
49  * @param nextPose Resulting pose for the next frame
50  * @return True, if succeeded
51  */
52  static bool trackPlanarObject(const PinholeCamera& pinholeCamera, const HomogenousMatrix4& previousPose, const Plane3& previousPlane, const Vector2* previousImagePoints, const Vector2* nextImagePoints, const size_t correspondences, HomogenousMatrix4& nextPose);
53 
54  /**
55  * This function tracks a planar plane or object between two successive frames.
56  * The points are tracked bidirectional, thus the points are tracked from the previous to the current and from the current to the previous frame.<br>
57  * Point correspondences with an inaccurate bidirectional tracking are discarded.<br>
58  * If a point is near the frame border, a mirrored image patch is applied.<br>
59  * @param pinholeCamera The pinhole camera object defining the projection
60  * @param previousPyramid Previous frame pyramid
61  * @param nextPyramid Next frame pyramid, with same frame type as the previous frame
62  * @param layerRadius Search radius in each layer
63  * @param previousPose Pose of the previous frame
64  * @param previousPlane 3D plane that specifies the planar object in the previous frame
65  * @param previousSubRegion Optional 2D triangles specifying a sub-region in that the points are tracked only
66  * @param nextPose Resulting pose for the next frame
67  * @param maximalSqrError Maximal square distance between forward and backward tracking for a valid point
68  * @param horizontalBins Optional horizontal bins that can be used to distribute the tracked points into array bins (in each bin there will be at most one point)
69  * @param verticalBins Optional vertical bins that can be used to distribute the tracked points into array bins (in each bin there will be at most one point)
70  * @param strength Minimal strength parameter of the tracked feature points
71  * @param worker Optional worker object to distribute the computation
72  * @param trackingLayers Number of pyramid layers on which points are tracked
73  * @param previousImagePoints Optional resulting image points of the previous image that have been used for tracking
74  * @param currentImagePoints Optional resulting image points of the current image that have been used for tracking, each point corresponds to one point in the previous image
75  * @return The number of feature points that have been used for pose determination, with range [0] or [5, infinity)
76  * @tparam tSize Size of the image patch that is used to determine the motion, must be odd
77  */
78  template <unsigned int tSize>
79  static size_t trackPlanarObject(const PinholeCamera& pinholeCamera, const CV::FramePyramid& previousPyramid, const CV::FramePyramid& nextPyramid, const unsigned int layerRadius, const HomogenousMatrix4& previousPose, const Plane3& previousPlane, const CV::SubRegion& previousSubRegion, HomogenousMatrix4& nextPose, const Scalar maximalSqrError /*= Scalar(0.9 * 0.9)*/, const unsigned int horizontalBins /*= 0u*/, const unsigned int verticalBins /*= 0u*/, const unsigned int strength = 30u, Worker* worker = nullptr, const unsigned int trackingLayers = 1u, Vectors2* previousImagePoints = nullptr, Vectors2* currentImagePoints = nullptr);
80 
81  /**
82  * This function tracks a planar plane or object between two successive frames.
83  * The points are tracked bidirectional, thus the points are tracked from the previous to the current and from the current to the previous frame.<br>
84  * Point correspondences with an inaccurate bidirectional tracking are discarded.<br>
85  * If a point is near the frame border, a mirrored image patch is applied.<br>
86  * @param pinholeCamera The pinhole camera object defining the projection
87  * @param previousFrame Previous frame
88  * @param nextFrame Next frame, with same frame type as the previous frame
89  * @param layerRadius Search radius in each layer
90  * @param previousPose Pose of the previous frame
91  * @param previousPlane 3D plane that specifies the planar object in the previous frame
92  * @param previousSubRegion Optional sub-region in that the points are tracked only
93  * @param nextPose Resulting pose for the next frame
94  * @param maximalSqrError Maximal square distance between forward and backward tracking for a valid point
95  * @param downsamplingMode The downsampling mode that is applied to create the pyramid layers
96  * @param worker Optional worker object to distribute the computation
97  * @return The number of feature points that have been used for pose determination, with range [0] or [5, infinity)
98  * @tparam tSize Size of the image patch that is used to determine the motion, must be odd
99  */
100  template <unsigned int tSize>
101  static inline size_t trackPlanarObject(const PinholeCamera& pinholeCamera, const Frame& previousFrame, const Frame& nextFrame, const unsigned int layerRadius, const HomogenousMatrix4& previousPose, const Plane3& previousPlane, const CV::SubRegion& previousSubRegion, HomogenousMatrix4& nextPose, const Scalar maximalSqrError = Scalar(0.9 * 0.9), const CV::FramePyramid::DownsamplingMode downsamplingMode = CV::FramePyramid::DM_FILTER_14641, Worker* worker = nullptr);
102 };
103 
104 template <unsigned int tSize>
105 size_t Frame2FrameTracker::trackPlanarObject(const PinholeCamera& pinholeCamera, const CV::FramePyramid& previousPyramid, const CV::FramePyramid& nextPyramid, const unsigned int layerRadius, const HomogenousMatrix4& previousPose, const Plane3& previousPlane, const CV::SubRegion& previousSubRegion, HomogenousMatrix4& nextPose, const Scalar maximalSqrError, const unsigned int horizontalBins, const unsigned int verticalBins, const unsigned int strength, Worker* worker, const unsigned int trackingLayers, Vectors2* previousImagePoints, Vectors2* currentImagePoints)
106 {
107  ocean_assert(pinholeCamera && previousPyramid && nextPyramid);
108  ocean_assert(previousPose.isValid());
109  ocean_assert(previousPlane.isValid());
110 
111  Vectors2 previousRobustImagePoints, nextRobustImagePoints;
112  if (!CV::Advanced::AdvancedMotionZeroMeanSSD::trackArbitraryPointsBidirectionalSubPixelMirroredBorder<tSize>(previousPyramid, nextPyramid, layerRadius, previousRobustImagePoints, nextRobustImagePoints, maximalSqrError, previousSubRegion, horizontalBins, verticalBins, strength, worker, trackingLayers) || previousRobustImagePoints.size() < 5)
113  {
114  return false;
115  }
116 
117  ocean_assert(previousRobustImagePoints.size() == nextRobustImagePoints.size());
118 
119  if (!trackPlanarObject(pinholeCamera, previousPose, previousPlane, previousRobustImagePoints.data(), nextRobustImagePoints.data(), previousRobustImagePoints.size(), nextPose))
120  {
121  return 0;
122  }
123 
124  ocean_assert(previousRobustImagePoints.size() >= 5);
125  const size_t result = previousRobustImagePoints.size();
126 
127  if (previousImagePoints)
128  {
129  *previousImagePoints = std::move(previousRobustImagePoints);
130  }
131 
132  if (currentImagePoints)
133  {
134  *currentImagePoints = std::move(nextRobustImagePoints);
135  }
136 
137  return result;
138 }
139 
140 template <unsigned int tSize>
141 size_t Frame2FrameTracker::trackPlanarObject(const PinholeCamera& pinholeCamera, const Frame& previousFrame, const Frame& nextFrame, const unsigned int layerRadius, const HomogenousMatrix4& previousPose, const Plane3& previousPlane, const CV::SubRegion& previousSubRegion, HomogenousMatrix4& nextPose, const Scalar maximalSqrError, const CV::FramePyramid::DownsamplingMode downsamplingMode, Worker* worker)
142 {
143  ocean_assert(pinholeCamera && previousFrame && nextFrame);
144  ocean_assert(previousPose.isValid());
145 
146  if (!previousFrame || previousFrame.frameType() != nextFrame.frameType())
147  {
148  return false;
149  }
150 
151  const unsigned int layers = CV::FramePyramid::idealLayers(previousFrame.width(), previousFrame.height(), 60u, 60u, 2u, 64u);
152  if (layers == 0u)
153  {
154  return false;
155  }
156 
157  const CV::FramePyramid previousPyramid(previousFrame, downsamplingMode, layers, false /*copyFirstLayer*/, worker);
158  const CV::FramePyramid nextPyramid(nextFrame, downsamplingMode, layers, false /*copyFirstLayer*/, worker);
159 
160  return trackPlanarObject<tSize>(pinholeCamera, previousPyramid, nextPyramid, layerRadius, previousPose, previousPlane, previousSubRegion, nextPose, maximalSqrError, worker);
161 }
162 
163 }
164 
165 }
166 
167 }
168 
169 #endif // META_OCEAN_TRACKING_OFFLINE_FRAME_2_FRAME_TRACKER_H
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.
DownsamplingMode
Definition of individual down sampling modes.
Definition: FramePyramid.h:44
@ DM_FILTER_14641
Down sampling is realized by a 5x5 Gaussian filter.
Definition: FramePyramid.h:72
This class implement a sub-region either defined by 2D triangles or defined by a binary mask.
Definition: SubRegion.h:32
This class implements Ocean's image class.
Definition: Frame.h:1792
const FrameType & frameType() const
Returns the frame type of this frame.
Definition: Frame.h:3775
unsigned int width() const
Returns the width of the frame format in pixel.
Definition: Frame.h:3143
unsigned int height() const
Returns the height of the frame in pixel.
Definition: Frame.h:3148
bool isValid() const
Returns whether this matrix is a valid homogeneous transformation.
Definition: HomogenousMatrix4.h:1806
bool isValid() const
Returns whether this plane is valid.
Definition: Plane3.h:538
This class implements a tracker allowing to tracker feature points between two frames.
Definition: offline/Frame2FrameTracker.h:38
static bool trackPlanarObject(const PinholeCamera &pinholeCamera, const HomogenousMatrix4 &previousPose, const Plane3 &previousPlane, const Vector2 *previousImagePoints, const Vector2 *nextImagePoints, const size_t correspondences, HomogenousMatrix4 &nextPose)
This function tracks a planar plane or object between two successive frames.
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
float Scalar
Definition of a scalar type.
Definition: Math.h:128
std::vector< Vector2 > Vectors2
Definition of a vector holding Vector2 objects.
Definition: Vector2.h:64
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15