Ocean
HomographyImageAlignmentDense.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_IMAGE_ALIGNMENT_DENSE_H
9 #define META_OCEAN_TRACKING_IMAGE_ALIGNMENT_DENSE_H
10 
12 
13 #include "ocean/base/Frame.h"
14 #include "ocean/base/Worker.h"
15 
16 #include "ocean/cv/FramePyramid.h"
17 #include "ocean/cv/SubRegion.h"
18 
19 #include "ocean/math/Matrix.h"
21 
22 namespace Ocean
23 {
24 
25 namespace Tracking
26 {
27 
28 /**
29  * This class implements functions allowing dense image alignment.
30  * @ingroup tracking
31  */
32 class OCEAN_TRACKING_EXPORT HomographyImageAlignmentDense
33 {
34  public:
35 
36  /**
37  * Definition of an abstract base class allowing to store consistency data.
38  */
40  {
41  friend class ObjectRef<ConsistencyData>;
42 
43  public:
44 
45  /**
46  * Returns whether this object currently does not hold any consistency information.
47  * @return True, if so
48  */
49  virtual bool isEmpty() = 0;
50 
51  protected:
52 
53  /**
54  * Protected default constructor.
55  */
56  inline ConsistencyData();
57 
58  /**
59  * Disabled copy constructor.
60  * @param consistencyData Object which would be copied
61  */
62  ConsistencyData(const ConsistencyData& consistencyData) = delete;
63 
64  /**
65  * Destructs this object.
66  */
67  virtual ~ConsistencyData() = default;
68 
69  /**
70  * Disabled copy operator.
71  * @param consistencyData Object which would be copied
72  * @return Reference to this object
73  */
74  ConsistencyData& operator=(const ConsistencyData& consistencyData) = delete;
75  };
76 
77  /**
78  * Definition of an object reference holding a consistency data object.
79  */
81 
82  protected:
83 
84  // Forward declaration.
85  template <unsigned int tChannels>
87 
88  // Forward declaration.
89  template <unsigned int tChannels>
91 
92  // Forward declaration.
93  template <unsigned int tChannels>
95 
96  public:
97 
98  /**
99  * Optimizes the alignment between two images within a specified sub-region regarding a homography by application of an iterative additive delta Levenberg-Marquardt optimization approach.
100  * The resulting homography converts points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint), the given rough homography must be defined accordingly.<br>
101  * The performance of this function can be improved further if this function is invoked successively for the same template frame with identical parameters but with individual current frames.<br>
102  * In this case, an empty consistency data object must be provided for the first call, stored outside and must again be provided for the successive calls.
103  * @param templateFrame The template frame defining the reference to which the current frame will be aligned, must be valid
104  * @param templateSubRegion The sub-region defined within the template frame from which the visual content is used for the alignment, image content outside the sub-region is not investigated, must be valid
105  * @param currentFrame The current frame for which the alignment will be determine, must have the same pixel format and pixel origin as the template frame
106  * @param roughHomography An already rough homography defining the alignment between template and current frame, the homography transforms points defined in the template frame to points defined in the current frame
107  * @param homographyParameters The number of parameters used to define the homography, with range [8, 9]
108  * @param zeroMean True, to subtract the color intensities from the corresponding mean intensity before determining the error; False, to determine the error directly
109  * @param homography The resulting optimized homography for the specified template frame and current frame, with 1 in the lower right corner
110  * @param iterations The number of optimization iterations that will be applied at most, with range [1, infinity)
111  * @param lambda Initial Levenberg-Marquardt damping value which may be changed after each iteration using the damping factor, with range [0, infinity)
112  * @param lambdaFactor Levenberg-Marquardt damping factor to be applied to the damping value, with range [1, infinity)
113  * @param initialError Optional resulting initial averaged squared error between template and current frame within the sub-region
114  * @param finalError Optional resulting final averaged squared error between template and current frame within the sub-region
115  * @param intermediateErrors Optional resulting intermediate averaged squared errors, on error for each improving optimization iteration
116  * @param abort Optional abort statement allowing to abort the alignment at any time; set the value True to abort the alignment
117  * @param externalConsistencyData Optional abstract consistency data object that may be used to improve the overall performance for several successive optimization calls for individual current frames but with the same template frame
118  * @see optimizeAlignmentInverseCompositional(), optimizeAlignmentMultiResolution().
119  */
120  static bool optimizeAlignmentAdditive(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& currentFrame, const SquareMatrix3& roughHomography, const unsigned int homographyParameters, const bool zeroMean, SquareMatrix3& homography, const unsigned int iterations = 20u, Scalar lambda = 10, const Scalar lambdaFactor = 10, Scalar* initialError = nullptr, Scalar* finalError = nullptr, Scalars* intermediateErrors = nullptr, ConsistencyDataRef* externalConsistencyData = nullptr, bool* abort = nullptr);
121 
122  /**
123  * Optimizes the alignment between two images within a specified sub-region regarding a homography by application of an iterative inverse compositional delta Levenberg-Marquardt optimization approach.
124  * The resulting homography converts points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint), the given rough homography must be defined accordingly.<br>
125  * The performance of this function can be improved further if this function is invoked successively for the same template frame with identical parameters but with individual current frames.<br>
126  * In this case, an empty consistency data object must be provided for the first call, stored outside and must again be provided for the successive calls.
127  * @param templateFrame The template frame defining the reference to which the current frame will be aligned, must be valid
128  * @param templateSubRegion The sub-region defined within the template frame from which the visual content is used for the alignment, image content outside the sub-region is not investigated, must be valid
129  * @param currentFrame The current frame for which the alignment will be determine, must have the same pixel format and pixel origin as the template frame
130  * @param roughHomography An already rough homography defining the alignment between template and current frame, the homography transforms points defined in the template frame to points defined in the current frame
131  * @param homographyParameters The number of parameters used to define the homography, with range [8, 9]
132  * @param zeroMean True, to subtract the color intensities from the corresponding mean intensity before determining the error; False, to determine the error directly
133  * @param homography The resulting optimized homography for the specified template frame and current frame, with 1 in the lower right corner
134  * @param iterations The number of optimization iterations that will be applied at most, with range [1, infinity)
135  * @param lambda Initial Levenberg-Marquardt damping value which may be changed after each iteration using the damping factor, with range [0, infinity)
136  * @param lambdaFactor Levenberg-Marquardt damping factor to be applied to the damping value, with range [1, infinity)
137  * @param initialError Optional resulting initial averaged squared error between template and current frame within the sub-region
138  * @param finalError Optional resulting final averaged squared error between template and current frame within the sub-region
139  * @param intermediateErrors Optional resulting intermediate averaged squared errors, on error for each improving optimization iteration
140  * @param abort Optional abort statement allowing to abort the alignment at any time; set the value True to abort the alignment
141  * @param externalConsistencyData Optional abstract consistency data object that may be used to improve the overall performance for several successive optimization calls for individual current frames but with the same template frame
142  * @see optimizeAlignmentAdditive(), optimizeAlignmentMultiResolution().
143  */
144  static bool optimizeAlignmentInverseCompositional(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& currentFrame, const SquareMatrix3& roughHomography, const unsigned int homographyParameters, const bool zeroMean, SquareMatrix3& homography, const unsigned int iterations = 20u, Scalar lambda = 10, const Scalar lambdaFactor = 10, Scalar* initialError = nullptr, Scalar* finalError = nullptr, Scalars* intermediateErrors = nullptr, ConsistencyDataRef* externalConsistencyData = nullptr, bool* abort = nullptr);
145 
146  /**
147  * Optimizes the alignment between two images within a specified sub-region regarding a homography by applying a multi-resolution (coarse to fine approach) Gauss-Newton or a Levenberg-Marquardt optimization approach.
148  * The resulting homography converts points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint), the given rough homography must be defined accordingly.<br>
149  * The performance of this function can be improved further if this function is invoked successively for the same template frame with identical parameters but with individual current frames.<br>
150  * In this case, an empty consistency data object must be provided for the first call, stored outside and must again be provided for the successive calls.
151  * @param templateFrame The template frame, must be valid
152  * @param templateSubRegion The sub-region defined in the template frames, must be valid
153  * @param currentFrame The current frame, must have the same pixel format, pixel origin and layer number as the pyramid of the template frame, must be valid
154  * @param numberPyramidLayers The number of pyramid layers to be used, with range [1, infinity)
155  * @param homographyParameters The number of parameters representing the homography with range [8, 9]
156  * @param additiveAlignment True, to apply the additive delta optimization; False, to apply the inverse compositional delta optimization
157  * @param levenbergMarquardtOptimization True, to apply the Levenberg-Marquardt optimization; False, to apply Gauss-Newton
158  * @param zeroMean True, to apply a zero-mean optimization (color intensities will be subtracted from the mean color intensity); False, to use the color intensities directly
159  * @param roughHomography The rough homography already known between the template frame and the current frame (currentPoint = H * templatePoint)
160  * @param homography The resulting precise homography
161  * @param coarseIterations The number of optimization iterations that will be applied at most on the coarsest pyramid layer, with range [1, infinity)
162  * @param fineIterations The number of optimization iterations that will be applied at most on the finest pyramid layer, the layers between coarsest and finest layer will be handled by a linear interpolation between both iteration values, with range [1, infinity)
163  * @param downsamplingMode The down-sampling mode that is applied to create the pyramid layers
164  * @return True, if succeeded
165  * @see optimizeAlignmentAdditive(), optimizeAlignmentInverseCompositional().
166  */
167  static bool optimizeAlignmentMultiResolution(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& currentFrame, const unsigned int numberPyramidLayers, const unsigned int homographyParameters, const bool additiveAlignment, const bool levenbergMarquardtOptimization, const bool zeroMean, const SquareMatrix3& roughHomography, SquareMatrix3& homography, const unsigned int coarseIterations = 20u, const unsigned int fineIterations = 4u, const CV::FramePyramid::DownsamplingMode downsamplingMode = CV::FramePyramid::DM_FILTER_14641);
168 
169  /**
170  * Optimizes the alignment between two images within a specified sub-region regarding a homography by applying a multi-resolution (coarse to fine approach) Gauss-Newton or a Levenberg-Marquardt optimization approach.
171  * The resulting homography converts points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint), the given rough homography must be defined accordingly.<br>
172  * The performance of this function can be improved further if this function is invoked successively for the same template frame with identical parameters but with individual current frames.<br>
173  * In this case, an empty consistency data object must be provided for the first call, stored outside and must again be provided for the successive calls.
174  * @param templateFramePyramid The pyramid frame of the template frame
175  * @param templateSubRegions The multi-resolution sub-regions defined in the template frames (one sub-region for each pyramid-layer)
176  * @param currentFramePyramid The pyramid frame of the current frame, must have the same pixel format, pixel origin and layer number as the pyramid of the template frame
177  * @param layers The number of pyramid layers to be used for the alignment, with range [1, min(templateFramePyramid.layers(), currentFramePyramid.layers()]
178  * @param homographyParameters The number of parameters representing the homography with range [8, 9]
179  * @param additiveAlignment True, to apply the additive delta optimization; False, to apply the inverse compositional delta optimization
180  * @param levenbergMarquardtOptimization True, to apply the Levenberg-Marquardt optimization; False, to apply Gauss-Newton
181  * @param zeroMean True, to apply a zero-mean optimization (color intensities will be subtracted from the mean color intensity); False, to use the color intensities directly
182  * @param roughHomography The rough homography already known between the template frame and the current frame (currentPoint = H * templatePoint)
183  * @param homography The resulting precise homography
184  * @param coarseIterations The number of optimization iterations that will be applied at most on the coarsest pyramid layer, with range [1, infinity)
185  * @param fineIterations The number of optimization iterations that will be applied at most on the finest pyramid layer, the layers between coarsest and finest layer will be handled by a linear interpolation between both iteration values, with range [1, infinity)
186  * @param consistencyDatas The optional consistency data objects to improve the optimization performance, either no objects or one object per pyramid layer
187  * @return True, if succeeded
188  * @see optimizeAlignmentAdditive(), optimizeAlignmentInverseCompositional().
189  */
190  static bool optimizeAlignmentMultiResolution(const CV::FramePyramid& templateFramePyramid, const std::vector<CV::SubRegion>& templateSubRegions, const CV::FramePyramid& currentFramePyramid, const unsigned int layers, const unsigned int homographyParameters, const bool additiveAlignment, const bool levenbergMarquardtOptimization, const bool zeroMean, const SquareMatrix3& roughHomography, SquareMatrix3& homography, const unsigned int coarseIterations = 20u, const unsigned int fineIterations = 4u, std::vector<Tracking::HomographyImageAlignmentDense::ConsistencyDataRef>* consistencyDatas = nullptr);
191 
192  protected:
193 
194  /**
195  * Determines the current error for a given homography between a current frame and a template frame within a sub-region of the template frame.
196  * The homography transformed points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint).<br>
197  * We keep this implementation for debugging and for better understanding of the overall algorithm.
198  * @param templateFrame The template frame for which the error is determined, with 8 bit per pixel and 1-4 channels
199  * @param templateSubRegion The sub-region defined within the template frame
200  * @param currentFrame The current frame for which the error is determined, must have the same pixel format and pixel origin as the template frame
201  * @param homography The homography for which the error is determined, transforming points defined in the template frame to points defined in the current frame, with 1 in the lower right corner
202  * @param zeroMean True, to subtract the color intensities from the corresponding mean intensity before determining the error; False, to determine the error directly
203  * @return The resulting average squared error for all valid pixel correspondences
204  */
205  static Scalar slowDetermineError(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& currentFrame, const SquareMatrix3& homography, const bool zeroMean);
206 
207  /**
208  * Determines the current error for a given homography between a current frame and a template frame within a sub-region of the template frame.
209  * The homography transformed points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint).<br>
210  * We keep this implementation for debugging and for better understanding of the overall algorithm.
211  * @param templateFrame The template frame for which the error is determined, with 8 bit per pixel and 1-4 channels
212  * @param templateSubRegion The sub-region defined within the template frame
213  * @param currentFrame The current frame for which the error is determined, must have the same pixel format and pixel origin as the template frame
214  * @param homography The homography for which the error is determined, transforming points defined in the template frame to points defined in the current frame, with 1 in the lower right corner
215  * @param zeroMean True, to subtract the color intensities from the corresponding mean intensity before determining the error; False, to determine the error directly
216  * @return The resulting average squared error for all valid pixel correspondences
217  * @tparam tChannels The number of channels both frames have, with range [1, 4]
218  */
219  template <unsigned int tChannels>
220  static Scalar slowDetermineError8BitPerChannel(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& currentFrame, const SquareMatrix3& homography, const bool zeroMean);
221 
222  /**
223  * Determines the 8x8 or 9x9 Hessian matrix and the 8x1 or 9x1 Jacobian-Error vector for a given homography between a current frame and a template frame within a sub-region of the template frame.
224  * The homography transformed points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint).<br>
225  * We keep this implementation for debugging and for better understanding of the overall algorithm.
226  * @param templateFrame The template frame for which the Hessian and Jacobian is determined, with 8 bit per pixel and 1-4 channels
227  * @param templateSubRegion The sub-region defined within the template frame
228  * @param currentFrame The current frame for which the Hessian and Jacobian is determined, must have the same pixel format and pixel origin as the template frame
229  * @param homography The homography for which the Hessian and Jacobian is determined, transforming points defined in the template frame to points defined in the current frame, with 1 in the lower right corner
230  * @param zeroMean True, to subtract the color intensities from the corresponding mean intensity before determining the error; False, to determine the error directly
231  * @param hessian The resulting Hessian matrix
232  * @param jacobianError The resulting Jacobian-Error matrix
233  * @return True, if succeeded
234  * @tparam tParameters The number of parameters describing the homography and used to optimize it, with range [8, 9]
235  */
236  template <unsigned int tParameters>
237  static bool slowDetermineHessianAndErrorJacobian(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& currentFrame, const SquareMatrix3& homography, const bool zeroMean, Matrix& hessian, Matrix& jacobianError);
238 
239  /**
240  * Determines the 8x8 or 9x9 Hessian matrix and the 8x1 or 9x1 Jacobian-Error vector for a given homography between a current frame and a template frame within a sub-region of the template frame.
241  * The homography transformed points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint).<br>
242  * We keep this implementation for debugging and for better understanding of the overall algorithm.
243  * @param templateFrame The template frame for which the Hessian and Jacobian is determined, with 8 bit per pixel and 1-4 channels
244  * @param templateSubRegion The sub-region defined within the template frame
245  * @param currentFrame The current frame for which the Hessian and Jacobian is determined, must have the same pixel format and pixel origin as the template frame
246  * @param homography The homography for which the Hessian and Jacobian is determined, transforming points defined in the template frame to points defined in the current frame, with 1 in the lower right corner
247  * @param hessian The resulting Hessian matrix
248  * @param zeroMean True, to subtract the color intensities from the corresponding mean intensity before determining the error; False, to determine the error directly
249  * @param jacobianError The resulting Jacobian-Error matrix
250  * @return True, if succeeded
251  * @tparam tParameters The number of parameters describing the homography and used to optimize it, with range [8, 9]
252  * @tparam tChannels The number of channels both frames have, with range [1, 4]
253  */
254  template <unsigned int tParameters, unsigned int tChannels>
255  static bool slowDetermineHessianAndErrorJacobian8BitPerChannel(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& currentFrame, const SquareMatrix3& homography, const bool zeroMean, Matrix& hessian, Matrix& jacobianError);
256 
257  /**
258  * Determines the mean color intensities in the corresponding sub-regions of the current transformed frame and also optional in the template frame while optional a mask frame defines valid and invalid pixels (not counting for error determination).
259  * The homography transformed points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint).
260  * @param templateFrame The template frame, must be valid
261  * @param templateSubRegion The sub-region in which the mean color intensities are determined, defined in the template frame
262  * @param transformedCurrentSubFrame The sub-region from the transformed current frame, needs to be transformed with the homography with size and location equal to the sub-region
263  * @param transformedCurrentSubFrameMask Optional mask that has been created during the creation of the sub-region of the transformed current frame, nullptr to avoid the usage of any mask which is more efficient
264  * @param templateMeans The resulting mean color intensities in the template frame, if 'tDetermineTemplateMeans' is True
265  * @param currentMeans The resulting mean color intensities in the current transformed frame
266  * @param worker Optional worker object to distribute the computation
267  * @return True, if succeeded
268  * @tparam tChannels The number of data channels of the provided frames
269  * @tparam tDetermineTemplateMeans True, to determine the mean intensities for the current frame and the template frame; False, to determine the mean intensities for the current frame only
270  */
271  template <unsigned int tChannels, bool tDetermineTemplateMeans>
272  static inline bool determineMeans8BitPerChannel(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& transformedCurrentSubFrame, const Frame& transformedCurrentSubFrameMask, Scalar* templateMeans, Scalar* currentMeans, Worker* worker);
273 
274  /**
275  * Determines the color intensity error within a sub-region between a template frame and a transformed current frame while optional a mask frame defines valid and invalid pixels (not counting for error determination).
276  * The homography transformed points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint).
277  * @param templateFrame The frame data of the template frame, must be valid
278  * @param templateSubRegion The sub-region for which the error is determined, defined in the template frame
279  * @param transformedCurrentSubFrameData The sub-region from the transformed current frame, needs to be transformed with the homography with size and location equal to the sub-region
280  * @param transformedCurrentSubFrameMaskData Optional mask that has been created during the creation of the sub-region of the transformed current frame, nullptr to avoid the usage of a mask which is more efficient
281  * @param templateMeans The mean color intensities in the sub-region of the template frame, must be defined if 'tUseMeans' is True; otherwise nullptr
282  * @param currentMeans The mean color intensities in the current transformed frame, must be defined if 'tUseMeans' is True; otherwise nullptr
283  * @param worker Optional worker object to distribute the computation
284  * @return The average squared error for each pixel in the sub-region
285  * @tparam tChannels The number of data channels of the provided frames
286  * @tparam tUseMeans True, if the mean color intensities are used to determine the errors; False, otherwise
287  */
288  template <unsigned int tChannels, bool tUseMeans>
289  static inline Scalar determineError8BitPerChannel(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& transformedCurrentSubFrameData, const Frame& transformedCurrentSubFrameMaskData, const Scalar* templateMeans, const Scalar* currentMeans, Worker* worker);
290 
291  /**
292  * Determines the Hessian matrix and the product of transposed Jacobian matrix and error vector for a template frame and current transformed frame within a sub-region while optional a mask frame defines valid and invalid pixels (not counting for error determination).
293  * The homography transformed points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint).
294  * @param templateFrame The template frame, must be valid
295  * @param templateSubRegion The sub-region for which the error is determined, defined in the template frame
296  * @param transformedCurrentSubFrame The sub-region from the transformed current frame, needs to be transformed with the homography with size and location equal to the sub-region
297  * @param transformedCurrentSubFrameMask Optional mask that has been created during the creation of the sub-region of the transformed current frame, nullptr to avoid the usage of any mask which is more efficient
298  * @param transformedBoundingBoxLeft The left border of the bounding box of the transformed sub-region in pixel, with range [0, currentFrame.width())
299  * @param transformedBoundingBoxTop the top border of the bounding box of the transformed sub-region in pixel, with range [0, currentFrame.height())
300  * @param transformedBoundingBoxWidth The width of the bounding box of the transformed sub-region in pixel, with range [1, currentFrame.width() - transformedBoundingBoxLeft]
301  * @param transformedBoundingBoxHeight The height of the bounding box of the transformed sub-region in pixel, with range [1, currentFrame.height() - transformedBoundingBoxTop]
302  * @param gradientCurrentFrame The gradient filter responses of the current frame restricted to the location and size of the transformed bounding box, must be valid
303  * @param homography The homography to be used to transform the current frame with
304  * @param templateMeans The mean color intensities in the sub-region of the template frame, must be defined if 'tUseMeans' is True; otherwise nullptr
305  * @param currentMeans The mean color intensities in the current transformed frame, must be defined if 'tUseMeans' is True; otherwise nullptr
306  * @param hessian The resulting Hessian matrix, with dimension (tParameters x tParameters)
307  * @param jacobianError The resulting product of transposed Jacobian matrix and error vector, with dimension (tParameters x 1)
308  * @param worker Optional worker object to distribute the computation
309  * @tparam tParameters The number of parameters that are used to optimize the homography, with range [8, 9]
310  * @tparam tChannels The number of data channels of the provided frames
311  * @tparam tUseMeans True, if the mean color intensities are used to determine the errors; False, otherwise
312  */
313  template <unsigned int tParameters, unsigned int tChannels, bool tUseMeans>
314  static inline void determineHessianAndErrorJacobian8BitPerChannel(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& transformedCurrentSubFrame, const Frame& transformedCurrentSubFrameMask, const unsigned int transformedBoundingBoxLeft, const unsigned int transformedBoundingBoxTop, const unsigned int transformedBoundingBoxWidth, const unsigned int transformedBoundingBoxHeight, const Frame& gradientCurrentFrame, const SquareMatrix3& homography, const Scalar* templateMeans, const Scalar* currentMeans, Matrix& hessian, Matrix& jacobianError, Worker* worker);
315 
316  /**
317  * Determines the product of transposed Jacobian matrix and error vector for the inverse compositional optimization approach for a template frame and current transformed frame within a sub-region while optional a mask frame defines valid and invalid pixels (not counting for error determination).
318  * @param templateFrame The template frame, must be valid
319  * @param templateSubRegion The sub-region for which the error is determined, defined in the template frame
320  * @param transformedCurrentSubFrame The sub-region from the transformed current frame, needs to be transformed with the homography with size and location equal to the sub-region
321  * @param transformedCurrentSubFrameMask Optional mask that has been created during the creation of the sub-region of the transformed current frame, nullptr to avoid the usage of any mask which is more efficient
322  * @param templateMeans The mean color intensities in the sub-region of the template frame, must be defined if 'tUseMeans' is True; otherwise nullptr
323  * @param currentMeans The mean color intensities in the current transformed frame, must be defined if 'tUseMeans' is True; otherwise nullptr
324  * @param jacobianRows The already determine (and constant) Jacobian rows for each pixel and channel of the template sub-region, each row has dimension (1 x tParameters)
325  * @param jacobianError The resulting product of transposed Jacobian matrix and error vector, with dimension (tParameters x 1)
326  * @param worker Optional worker object to distribute the computation
327  * @tparam tParameters The number of parameters that are used to optimize the homography, with range [8, 9]
328  * @tparam tChannels The number of data channels of the provided frames
329  * @tparam tUseMeans True, if the mean color intensities are used to determine the errors; False, otherwise
330  */
331  template <unsigned int tParameters, unsigned int tChannels, bool tUseMeans>
332  static inline void determineErrorJacobianInverseCompositional8BitPerChannel(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& transformedCurrentSubFrame, const Frame& transformedCurrentSubFrameMask, const Scalar* templateMeans, const Scalar* currentMeans, const Scalar* jacobianRows, Matrix& jacobianError, Worker* worker);
333 
334  /**
335  * Determines the mean color intensities in a subset of the corresponding sub-regions of the current transformed frame and also optional in the template frame.
336  * The homography transformed points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint).
337  * @param templateFrame The template frame, must be valid
338  * @param templateSubRegion The sub-region in which the mean color intensities are determined, defined in the template frame
339  * @param transformedCurrentSubFrame The sub-region from the transformed current frame, needs to be transformed with the homography with size and location equal to the sub-region
340  * @param templateMeans The resulting sum of color intensities in the template frame, if 'tDetermineTemplateMeans' is True, must be initialized with 0
341  * @param currentMeans The resulting sum of color intensities in the current transformed frame, must be initialized with 0
342  * @param templateMeansDenominator The number of pixels that have been used to determine the sum of intensities in the template frame, must be initialized with 0
343  * @param currentMeansDenominator The number of pixels that have been used to determine the sum of intensities in the current transformed frame, must be initialized with 0
344  * @param lock The lock object necessary if this function is executed on multiple threads in parallel, nullptr otherwise
345  * @param threads The number of threads on which this function is executed in parallel
346  * @param threadIndex The index of the current thread, with range [0, threads)
347  * @param unused An unused parameter must be 1
348  * @tparam tChannels The number of data channels of the provided frames
349  * @tparam tDetermineTemplateMeans True, to determine the mean intensities for the current frame and the template frame; False, to determine the mean intensities for the current frame only
350  * @see determineMeans8BitPerChannel().
351  */
352  template <unsigned int tChannels, bool tDetermineTemplateMeans>
353  static void determineMeans8BitPerChannelSubset(const Frame* templateFrame, const CV::SubRegion* templateSubRegion, const Frame* transformedCurrentSubFrame, Scalar* templateMeans, Scalar* currentMeans, unsigned int* templateMeansDenominator, unsigned int* currentMeansDenominator, Lock* lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused);
354 
355  /**
356  * Determines the mean color intensities in a subset of the corresponding sub-regions of the current transformed frame and also optional in the template frame.
357  * The homography transformed points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint).
358  * @param templateFrame The template frame, must be valid
359  * @param templateSubRegion The sub-region in which the mean color intensities are determined, defined in the template frame
360  * @param transformedCurrentSubFrame The sub-region from the transformed current frame, needs to be transformed with the homography with size and location equal to the sub-region
361  * @param transformedCurrentSubFrameMask The mask that has been created during the creation of the sub-region of the transformed current frame
362  * @param templateMeans The resulting sum of color intensities in the template frame, if 'tDetermineTemplateMeans' is True, must be initialized with 0
363  * @param currentMeans The resulting sum of color intensities in the current transformed frame, must be initialized with 0
364  * @param templateMeansDenominator The number of pixels that have been used to determine the sum of intensities in the template frame, must be initialized with 0
365  * @param currentMeansDenominator The number of pixels that have been used to determine the sum of intensities in the current transformed frame, must be initialized with 0
366  * @param lock The lock object necessary if this function is executed on multiple threads in parallel, nullptr otherwise
367  * @param threads The number of threads on which this function is executed in parallel
368  * @param threadIndex The index of the current thread, with range [0, threads)
369  * @param unused An unused parameter must be 1
370  * @tparam tChannels The number of data channels of the provided frames
371  * @tparam tDetermineTemplateMeans True, to determine the mean intensities for the current frame and the template frame; False, to determine the mean intensities for the current frame only
372  * @see determineMeans8BitPerChannel().
373  */
374  template <unsigned int tChannels, bool tDetermineTemplateMeans>
375  static void determineMeansMask8BitPerChannelSubset(const Frame* templateFrame, const CV::SubRegion* templateSubRegion, const Frame* transformedCurrentSubFrame, const Frame* transformedCurrentSubFrameMask, Scalar* templateMeans, Scalar* currentMeans, unsigned int* templateMeansDenominator, unsigned int* currentMeansDenominator, Lock* lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused);
376 
377  /**
378  * Determines the color intensity error in a subset of a sub-region between a template frame and a transformed current frame.
379  * The homography transformed points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint).
380  * @param templateFrame The template frame, must be valid
381  * @param templateSubRegion The sub-region for which the error is determined, defined in the template frame
382  * @param transformedCurrentSubFrame The sub-region from the transformed current frame, needs to be transformed with the homography with size and location equal to the sub-region
383  * @param templateMeans The mean color intensities in the sub-region of the template frame, must be defined if 'tUseMeans' is True; otherwise nullptr
384  * @param currentMeans The mean color intensities in the current transformed frame, must be defined if 'tUseMeans' is True; otherwise nullptr
385  * @param squaredError The resulting sum of squared errors, must be initialized with 0
386  * @param errorDenominators The number of pixels that have been used to determine the error, must be initialized with 0
387  * @param lock The lock object necessary if this function is executed on multiple threads in parallel, nullptr otherwise
388  * @param threads The number of threads on which this function is executed in parallel
389  * @param threadIndex The index of the current thread, with range [0, threads)
390  * @param unused An unused parameter must be 1
391  * @tparam tChannels The number of data channels of the provided frames
392  * @tparam tUseMeans True, if the mean color intensities are used to determine the errors; False, otherwise
393  */
394  template <unsigned int tChannels, bool tUseMeans>
395  static void determineError8BitPerChannelSubset(const Frame* templateFrame, const CV::SubRegion* templateSubRegion, const Frame* transformedCurrentSubFrame, const Scalar* templateMeans, const Scalar* currentMeans, Scalar* squaredError, unsigned int* errorDenominators, Lock* lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused);
396 
397  /**
398  * Determines the color intensity error in a subset of a sub-region between a template frame and a transformed current frame while a mask frame defines valid and invalid pixels (not counting for error determination).
399  * The homography transformed points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint).
400  * @param templateFrame The template frame, must be valid
401  * @param templateSubRegion The sub-region for which the error is determined, defined in the template frame
402  * @param transformedCurrentSubFrame The sub-region from the transformed current frame, needs to be transformed with the homography with size and location equal to the sub-region
403  * @param transformedCurrentSubFrameMask The mask that has been created during the creation of the sub-region of the transformed current frame
404  * @param templateMeans The mean color intensities in the sub-region of the template frame, must be defined if 'tUseMeans' is True; otherwise nullptr
405  * @param currentMeans The mean color intensities in the current transformed frame, must be defined if 'tUseMeans' is True; otherwise nullptr
406  * @param squaredError The resulting sum of squared errors, must be initialized with 0
407  * @param errorDenominators The number of pixels that have been used to determine the error, must be initialized with 0
408  * @param lock The lock object necessary if this function is executed on multiple threads in parallel, nullptr otherwise
409  * @param threads The number of threads on which this function is executed in parallel
410  * @param threadIndex The index of the current thread, with range [0, threads)
411  * @param unused An unused parameter must be 1
412  * @tparam tChannels The number of data channels of the provided frames
413  * @tparam tUseMeans True, if the mean color intensities are used to determine the errors; False, otherwise
414  */
415  template <unsigned int tChannels, bool tUseMeans>
416  static void determineErrorMask8BitPerChannelSubset(const Frame* templateFrame, const CV::SubRegion* templateSubRegion, const Frame* transformedCurrentSubFrame, const Frame* transformedCurrentSubFrameMask, const Scalar* templateMeans, const Scalar* currentMeans, Scalar* squaredError, unsigned int* errorDenominators, Lock* lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused);
417 
418  /**
419  * Determines the subset-Hessian matrix and the subset-product of transposed Jacobian matrix and error vector for a template frame and current transformed frame within a sub-region.
420  * The homography transformed points defined in the template frame to points defined in the current frame (currenttPoint = H * templatePoint).
421  * @param templateFrame The template frame, must be valid
422  * @param templateSubRegion The sub-region for which the error is determined, defined in the template frame
423  * @param transformedCurrentSubFrame The sub-region from the transformed current frame, needs to be transformed with the homography with size and location equal to the sub-region
424  * @param transformedBoundingBoxLeft The left border of the bounding box of the transformed sub-region in pixel, with range [0, currentFrame.width())
425  * @param transformedBoundingBoxTop the top border of the bounding box of the transformed sub-region in pixel, with range [0, currentFrame.height())
426  * @param transformedBoundingBoxWidth The width of the bounding box of the transformed sub-region in pixel, with range [1, currentFrame.width() - transformedBoundingBoxLeft]
427  * @param transformedBoundingBoxHeight The height of the bounding box of the transformed sub-region in pixel, with range [1, currentFrame.height() - transformedBoundingBoxTop]
428  * @param gradientCurrentFrame The gradient filter responses of the current frame restricted to the location and size of the transformed bounding box, must be valid
429  * @param homography The homography to be used to transform the current frame with
430  * @param templateMeans The mean color intensities in the sub-region of the template frame, must be defined if 'tUseMeans' is True; otherwise nullptr
431  * @param currentMeans The mean color intensities in the current transformed frame, must be defined if 'tUseMeans' is True; otherwise nullptr
432  * @param hessian The resulting Hessian matrix, with dimension (tParameters x tParameters), must be initialized with 0
433  * @param jacobianError The resulting product of transposed Jacobian matrix and error vector, with dimension (tParameters x 1), must be initialized with 0
434  * @param lock The lock object necessary if this function is executed on multiple threads in parallel, nullptr otherwise
435  * @param threads The number of threads on which this function is executed in parallel
436  * @param threadIndex The index of the current thread, with range [0, threads)
437  * @param unused An unused parameter must be 1
438  * @tparam tParameters The number of parameters that are used to optimize the homography, with range [8, 9]
439  * @tparam tChannels The number of data channels of the provided frames
440  * @tparam tUseMeans True, if the mean color intensities are used to determine the errors; False, otherwise
441  */
442  template <unsigned int tParameters, unsigned int tChannels, bool tUseMeans>
443  static void determineHessianAndErrorJacobian8BitPerChannelSubset(const Frame* templateFrame, const CV::SubRegion* templateSubRegion, const Frame* transformedCurrentSubFrame, const unsigned int transformedBoundingBoxLeft, const unsigned int transformedBoundingBoxTop, const unsigned int transformedBoundingBoxWidth, const unsigned int transformedBoundingBoxHeight, const Frame* gradientCurrentFrame, const SquareMatrix3* homography, const Scalar* templateMeans, const Scalar* currentMeans, Matrix* hessian, Matrix* jacobianError, Lock* lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused);
444 
445  /**
446  * Determines the subset of the product of transposed Jacobian matrix and error vector for the inverse compositional optimization approach for a template frame and current transformed frame within a sub-region while optional a mask frame defines valid and invalid pixels (not counting for error determination).
447  * @param templateFrame The template frame, must be valid
448  * @param templateSubRegion The sub-region for which the error is determined, defined in the template frame
449  * @param transformedCurrentSubFrame The sub-region from the transformed current frame, needs to be transformed with the homography with size and location equal to the sub-region
450  * @param templateMeans The mean color intensities in the sub-region of the template frame, must be defined if 'tUseMeans' is True; otherwise nullptr
451  * @param currentMeans The mean color intensities in the current transformed frame, must be defined if 'tUseMeans' is True; otherwise nullptr
452  * @param jacobianRows The already determine (and constant) Jacobian rows for each pixel and channel of the template sub-region, each row has dimension (1 x tParameters)
453  * @param jacobianError The resulting product of transposed Jacobian matrix and error vector, with dimension (tParameters x 1), must be initialized with 0
454  * @param lock The lock object necessary if this function is executed on multiple threads in parallel, nullptr otherwise
455  * @param threads The number of threads on which this function is executed in parallel
456  * @param threadIndex The index of the current thread, with range [0, threads)
457  * @param unused An unused parameter must be 1
458  * @tparam tParameters The number of parameters that are used to optimize the homography, with range [8, 9]
459  * @tparam tChannels The number of data channels of the provided frames
460  * @tparam tUseMeans True, if the mean color intensities are used to determine the errors; False, otherwise
461  */
462  template <unsigned int tParameters, unsigned int tChannels, bool tUseMeans>
463  static void determineErrorJacobianInverseCompositional8BitPerChannelSubset(const Frame* templateFrame, const CV::SubRegion* templateSubRegion, const Frame* transformedCurrentSubFrame, const Scalar* templateMeans, const Scalar* currentMeans, const Scalar* jacobianRows, Matrix* jacobianError, Lock* lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused);
464 
465  /**
466  * Determines the subset-Hessian matrix and the subset-product of transposed Jacobian matrix and error vector for a template frame and current transformed frame within a sub-region.
467  * @param templateFrame The template frame, must be valid
468  * @param templateSubRegion The sub-region for which the error is determined, defined in the template frame
469  * @param transformedCurrentSubFrame The sub-region from the transformed current frame, needs to be transformed with the homography with size and location equal to the sub-region
470  * @param transformedCurrentSubFrameMask The mask that has been created during the creation of the sub-region of the transformed current frame
471  * @param transformedBoundingBoxLeft The left border of the bounding box of the transformed sub-region in pixel, with range [0, currentFrame.width())
472  * @param transformedBoundingBoxTop the top border of the bounding box of the transformed sub-region in pixel, with range [0, currentFrame.height())
473  * @param transformedBoundingBoxWidth The width of the bounding box of the transformed sub-region in pixel, with range [1, currentFrame.width() - transformedBoundingBoxLeft]
474  * @param transformedBoundingBoxHeight The height of the bounding box of the transformed sub-region in pixel, with range [1, currentFrame.height() - transformedBoundingBoxTop]
475  * @param gradientCurrentFrame The gradient filter responses of the current frame restricted to the location and size of the transformed bounding box, must be valid
476  * @param current_H_template The homography converting the template image to the current image, must be valid
477  * @param templateMeans The mean color intensities in the sub-region of the template frame, must be defined if 'tUseMeans' is True; otherwise nullptr
478  * @param currentMeans The mean color intensities in the current transformed frame, must be defined if 'tUseMeans' is True; otherwise nullptr
479  * @param hessian The resulting Hessian matrix, with dimension (tParameters x tParameters), must be initialized with 0
480  * @param jacobianError The resulting product of transposed Jacobian matrix and error vector, with dimension (tParameters x 1), must be initialized with 0
481  * @param lock The lock object necessary if this function is executed on multiple threads in parallel, nullptr otherwise
482  * @param threads The number of threads on which this function is executed in parallel
483  * @param threadIndex The index of the current thread, with range [0, threads)
484  * @param unused An unused parameter must be 1
485  * @tparam tParameters The number of parameters that are used to optimize the homography, with range [8, 9]
486  * @tparam tChannels The number of data channels of the provided frames
487  * @tparam tUseMeans True, if the mean color intensities are used to determine the errors; False, otherwise
488  */
489  template <unsigned int tParameters, unsigned int tChannels, bool tUseMeans>
490  static void determineHessianAndErrorJacobianMask8BitPerChannelSubset(const Frame* templateFrame, const CV::SubRegion* templateSubRegion, const Frame* transformedCurrentSubFrame, const Frame* transformedCurrentSubFrameMask, const unsigned int transformedBoundingBoxLeft, const unsigned int transformedBoundingBoxTop, const unsigned int transformedBoundingBoxWidth, const unsigned int transformedBoundingBoxHeight, const Frame* gradientCurrentFrame, const SquareMatrix3* current_H_template, const Scalar* templateMeans, const Scalar* currentMeans, Matrix* hessian, Matrix* jacobianError, Lock* lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused);
491 };
492 
494 {
495  // nothing to do here
496 }
497 
498 template <unsigned int tChannels, bool tDetermineTemplateMeans>
499 inline bool HomographyImageAlignmentDense::determineMeans8BitPerChannel(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& transformedCurrentSubFrame, const Frame& transformedCurrentSubFrameMask, Scalar* templateMeans, Scalar* currentMeans, Worker* worker)
500 {
501  ocean_assert(templateFrame.isValid() && templateFrame.channels() == tChannels && templateFrame.dataType() == FrameType::DT_UNSIGNED_INTEGER_8);
502 
503  ocean_assert(!transformedCurrentSubFrameMask.isValid() || (transformedCurrentSubFrameMask.width() == transformedCurrentSubFrame.width() && transformedCurrentSubFrameMask.height() == transformedCurrentSubFrame.height()));
504 
505  for (unsigned int n = 0u; n < tChannels; ++n)
506  {
507  currentMeans[n] = Scalar(0);
508 
509  if constexpr (tDetermineTemplateMeans)
510  {
511  templateMeans[n] = Scalar(0);
512  }
513  }
514 
515  unsigned int templateMeansDenominator = 0u;
516  unsigned int currentMeansDenominator = 0u;
517 
518  if (worker)
519  {
520  Lock lock;
521 
522  if (transformedCurrentSubFrameMask.isValid())
523  {
524  worker->executeFunction(Worker::Function::createStatic(&determineMeansMask8BitPerChannelSubset<tChannels, tDetermineTemplateMeans>, &templateFrame, &templateSubRegion, &transformedCurrentSubFrame, &transformedCurrentSubFrameMask, templateMeans, currentMeans, &templateMeansDenominator, &currentMeansDenominator, &lock, worker->threads(), 0u, 0u), 0u, worker->threads());
525  }
526  else
527  {
528  worker->executeFunction(Worker::Function::createStatic(&determineMeans8BitPerChannelSubset<tChannels, tDetermineTemplateMeans>, &templateFrame, &templateSubRegion, &transformedCurrentSubFrame, templateMeans, currentMeans, &templateMeansDenominator, &currentMeansDenominator, &lock, worker->threads(), 0u, 0u), 0u, worker->threads());
529  }
530  }
531  else
532  {
533  if (transformedCurrentSubFrameMask.isValid())
534  {
535  determineMeansMask8BitPerChannelSubset<tChannels, tDetermineTemplateMeans>(&templateFrame, &templateSubRegion, &transformedCurrentSubFrame, &transformedCurrentSubFrameMask, templateMeans, currentMeans, &templateMeansDenominator, &currentMeansDenominator, nullptr, 1u, 0u, 1u);
536  }
537  else
538  {
539  determineMeans8BitPerChannelSubset<tChannels, tDetermineTemplateMeans>(&templateFrame, &templateSubRegion, &transformedCurrentSubFrame, templateMeans, currentMeans, &templateMeansDenominator, &currentMeansDenominator, nullptr, 1u, 0u, 1u);
540  }
541  }
542 
543  if (currentMeansDenominator == 0u)
544  {
545  return false;
546  }
547 
548  const Scalar invCurrentDenominator = Scalar(1) / Scalar(currentMeansDenominator);
549 
550  for (unsigned int n = 0u; n < tChannels; ++n)
551  {
552  currentMeans[n] *= invCurrentDenominator;
553  }
554 
555  if constexpr (tDetermineTemplateMeans)
556  {
557  const Scalar invTemplateDenominator = Scalar(1) / Scalar(templateMeansDenominator);
558 
559  for (unsigned int n = 0u; n < tChannels; ++n)
560  {
561  templateMeans[n] *= invTemplateDenominator;
562  }
563  }
564 
565  return true;
566 }
567 
568 template <unsigned int tChannels, bool tUseMeans>
569 inline Scalar HomographyImageAlignmentDense::determineError8BitPerChannel(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& transformedCurrentSubFrame, const Frame& transformedCurrentSubFrameMask, const Scalar* templateMeans, const Scalar* currentMeans, Worker* worker)
570 {
571  ocean_assert(templateFrame.isValid() && templateFrame.channels() == tChannels && templateFrame.dataType() == FrameType::DT_UNSIGNED_INTEGER_8);
572 
573  Scalar errorValue = Scalar(0);
574  unsigned int errorDenominator = 0u;
575 
576  if (worker)
577  {
578  Lock lock;
579 
580  if (transformedCurrentSubFrameMask.isValid())
581  {
582  worker->executeFunction(Worker::Function::createStatic(&determineErrorMask8BitPerChannelSubset<tChannels, tUseMeans>, &templateFrame, &templateSubRegion, &transformedCurrentSubFrame, &transformedCurrentSubFrameMask, templateMeans, currentMeans, &errorValue, &errorDenominator, &lock, worker->threads(), 0u, 0u), 0u, worker->threads());
583  }
584  else
585  {
586  worker->executeFunction(Worker::Function::createStatic(&determineError8BitPerChannelSubset<tChannels, tUseMeans>, &templateFrame, &templateSubRegion, &transformedCurrentSubFrame, templateMeans, currentMeans, &errorValue, &errorDenominator, &lock, worker->threads(), 0u, 0u), 0u, worker->threads());
587  }
588  }
589  else
590  {
591  if (transformedCurrentSubFrameMask.isValid())
592  {
593  determineErrorMask8BitPerChannelSubset<tChannels, tUseMeans>(&templateFrame, &templateSubRegion, &transformedCurrentSubFrame, &transformedCurrentSubFrameMask, templateMeans, currentMeans, &errorValue, &errorDenominator, nullptr, 1u, 0u, 1u);
594  }
595  else
596  {
597  determineError8BitPerChannelSubset<tChannels, tUseMeans>(&templateFrame, &templateSubRegion, &transformedCurrentSubFrame, templateMeans, currentMeans, &errorValue, &errorDenominator, nullptr, 1u, 0u, 1u);
598  }
599  }
600 
601  if (errorDenominator == 0u)
602  {
603  return Numeric::maxValue();
604  }
605 
606  return errorValue / Scalar(errorDenominator * tChannels);
607 }
608 
609 template <unsigned int tParameters, unsigned int tChannels, bool tUseMeans>
610 inline void HomographyImageAlignmentDense::determineHessianAndErrorJacobian8BitPerChannel(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& transformedCurrentSubFrame, const Frame& transformedCurrentSubFrameMask, const unsigned int transformedBoundingBoxLeft, const unsigned int transformedBoundingBoxTop, const unsigned int transformedBoundingBoxWidth, const unsigned int transformedBoundingBoxHeight, const Frame& gradientCurrentFrame, const SquareMatrix3& homography, const Scalar* templateMeans, const Scalar* currentMeans, Matrix& hessian, Matrix& jacobianError, Worker* worker)
611 {
612  hessian = Matrix(tParameters, tParameters, false);
613  jacobianError = Matrix(tParameters, 1, false);
614 
615  if (worker)
616  {
617  Lock lock;
618 
619  if (transformedCurrentSubFrameMask.isValid())
620  {
621  worker->executeFunction(Worker::Function::createStatic(&determineHessianAndErrorJacobianMask8BitPerChannelSubset<tParameters, tChannels, tUseMeans>, &templateFrame, &templateSubRegion, &transformedCurrentSubFrame, &transformedCurrentSubFrameMask, transformedBoundingBoxLeft, transformedBoundingBoxTop, transformedBoundingBoxWidth, transformedBoundingBoxHeight, &gradientCurrentFrame, &homography, templateMeans, currentMeans, &hessian, &jacobianError, &lock, worker->threads(), 0u, 0u), 0u, worker->threads());
622  }
623  else
624  {
625  worker->executeFunction(Worker::Function::createStatic(&determineHessianAndErrorJacobian8BitPerChannelSubset<tParameters, tChannels, tUseMeans>, &templateFrame, &templateSubRegion, &transformedCurrentSubFrame, transformedBoundingBoxLeft, transformedBoundingBoxTop, transformedBoundingBoxWidth, transformedBoundingBoxHeight, &gradientCurrentFrame, &homography, templateMeans, currentMeans, &hessian, &jacobianError, &lock, worker->threads(), 0u, 0u), 0u, worker->threads());
626  }
627  }
628  else
629  {
630  if (transformedCurrentSubFrameMask.isValid())
631  {
632  determineHessianAndErrorJacobianMask8BitPerChannelSubset<tParameters, tChannels, tUseMeans>(&templateFrame, &templateSubRegion, &transformedCurrentSubFrame, &transformedCurrentSubFrameMask, transformedBoundingBoxLeft, transformedBoundingBoxTop, transformedBoundingBoxWidth, transformedBoundingBoxHeight, &gradientCurrentFrame, &homography, templateMeans, currentMeans, &hessian, &jacobianError, nullptr, 1u, 0u, 1u);
633  }
634  else
635  {
636  determineHessianAndErrorJacobian8BitPerChannelSubset<tParameters, tChannels, tUseMeans>(&templateFrame, &templateSubRegion, &transformedCurrentSubFrame, transformedBoundingBoxLeft, transformedBoundingBoxTop, transformedBoundingBoxWidth, transformedBoundingBoxHeight, &gradientCurrentFrame, &homography, templateMeans, currentMeans, &hessian, &jacobianError, nullptr, 1u, 0u, 1u);
637  }
638  }
639 }
640 
641 template <unsigned int tParameters, unsigned int tChannels, bool tUseMeans>
642 inline void HomographyImageAlignmentDense::determineErrorJacobianInverseCompositional8BitPerChannel(const Frame& templateFrame, const CV::SubRegion& templateSubRegion, const Frame& transformedCurrentSubFrame, const Frame& transformedCurrentSubFrameMask, const Scalar* templateMeans, const Scalar* currentMeans, const Scalar* jacobianRows, Matrix& jacobianError, Worker* worker)
643 {
644  jacobianError = Matrix(tParameters, 1, false);
645 
646  if (worker)
647  {
648  Lock lock;
649 
650  if (transformedCurrentSubFrameMask.isValid())
651  {
652  ocean_assert(false && "**TODO**");
653  //worker->executeFunction(Worker::Function::createStatic(&determineHessianAndErrorJacobianMaskInverseCompositional8BitPerChannelSubset<tParameters, tChannels, tUseMeans>, &templateFrame, &templateSubRegion, transformedCurrentSubFrameData, transformedCurrentSubFrameMaskData, transformedBoundingBoxLeft, transformedBoundingBoxTop, transformedBoundingBoxWidth, transformedBoundingBoxHeight, gradientCurrentData, &homography, templateMeans, currentMeans, &hessian, &jacobianError, &lock, worker->threads(), 0u, 0u), 0u, worker->threads());
654  }
655  else
656  {
657  worker->executeFunction(Worker::Function::createStatic(&determineErrorJacobianInverseCompositional8BitPerChannelSubset<tParameters, tChannels, tUseMeans>, &templateFrame, &templateSubRegion, &transformedCurrentSubFrame, templateMeans, currentMeans, jacobianRows, &jacobianError, &lock, worker->threads(), 0u, 0u), 0u, worker->threads());
658  }
659  }
660  else
661  {
662  if (transformedCurrentSubFrameMask.isValid())
663  {
664  ocean_assert(false && "**TODO**");
665  //determineHessianAndErrorJacobianMaskInverseCompositional8BitPerChannelSubset<tParameters, tChannels, tUseMeans>(&templateFrame, &templateSubRegion, transformedCurrentSubFrameData, transformedCurrentSubFrameMaskData, transformedBoundingBoxLeft, transformedBoundingBoxTop, transformedBoundingBoxWidth, transformedBoundingBoxHeight, gradientCurrentData, &homography, templateMeans, currentMeans, &hessian, &jacobianError, nullptr, 1u, 0u, 1u);
666  }
667  else
668  {
669  determineErrorJacobianInverseCompositional8BitPerChannelSubset<tParameters, tChannels, tUseMeans>(&templateFrame, &templateSubRegion, &transformedCurrentSubFrame, templateMeans, currentMeans, jacobianRows, &jacobianError, nullptr, 1u, 0u, 1u);
670  }
671  }
672 }
673 
674 }
675 
676 }
677 
678 #endif // META_OCEAN_TRACKING_IMAGE_ALIGNMENT_DENSE_H
This class implements a frame pyramid.
Definition: FramePyramid.h:37
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
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:1792
bool isValid() const
Returns whether this frame is valid.
Definition: Frame.h:4448
unsigned int width() const
Returns the width of the frame format in pixel.
Definition: Frame.h:3143
@ DT_UNSIGNED_INTEGER_8
Unsigned 8 bit integer data type (uint8_t).
Definition: Frame.h:41
unsigned int height() const
Returns the height of the frame in pixel.
Definition: Frame.h:3148
unsigned int channels() const
Returns the number of individual channels the frame has.
Definition: Frame.h:3173
DataType dataType() const
Returns the data type of the pixel format of this frame.
Definition: Frame.h:3163
This class implements a recursive lock object.
Definition: Lock.h:31
static constexpr T maxValue()
Returns the max scalar value.
Definition: Numeric.h:3244
This template class implements a object reference with an internal reference counter.
Definition: base/ObjectRef.h:58
Definition of an abstract base class allowing to store consistency data.
Definition: HomographyImageAlignmentDense.h:40
virtual bool isEmpty()=0
Returns whether this object currently does not hold any consistency information.
virtual ~ConsistencyData()=default
Destructs this object.
ConsistencyData & operator=(const ConsistencyData &consistencyData)=delete
Disabled copy operator.
ConsistencyData(const ConsistencyData &consistencyData)=delete
Disabled copy constructor.
ConsistencyData()
Protected default constructor.
Definition: HomographyImageAlignmentDense.h:493
Definition: HomographyImageAlignmentDense.h:86
This class implements functions allowing dense image alignment.
Definition: HomographyImageAlignmentDense.h:33
static Scalar slowDetermineError8BitPerChannel(const Frame &templateFrame, const CV::SubRegion &templateSubRegion, const Frame &currentFrame, const SquareMatrix3 &homography, const bool zeroMean)
Determines the current error for a given homography between a current frame and a template frame with...
static bool slowDetermineHessianAndErrorJacobian(const Frame &templateFrame, const CV::SubRegion &templateSubRegion, const Frame &currentFrame, const SquareMatrix3 &homography, const bool zeroMean, Matrix &hessian, Matrix &jacobianError)
Determines the 8x8 or 9x9 Hessian matrix and the 8x1 or 9x1 Jacobian-Error vector for a given homogra...
static void determineErrorJacobianInverseCompositional8BitPerChannelSubset(const Frame *templateFrame, const CV::SubRegion *templateSubRegion, const Frame *transformedCurrentSubFrame, const Scalar *templateMeans, const Scalar *currentMeans, const Scalar *jacobianRows, Matrix *jacobianError, Lock *lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused)
Determines the subset of the product of transposed Jacobian matrix and error vector for the inverse c...
static bool optimizeAlignmentAdditive(const Frame &templateFrame, const CV::SubRegion &templateSubRegion, const Frame &currentFrame, const SquareMatrix3 &roughHomography, const unsigned int homographyParameters, const bool zeroMean, SquareMatrix3 &homography, const unsigned int iterations=20u, Scalar lambda=10, const Scalar lambdaFactor=10, Scalar *initialError=nullptr, Scalar *finalError=nullptr, Scalars *intermediateErrors=nullptr, ConsistencyDataRef *externalConsistencyData=nullptr, bool *abort=nullptr)
Optimizes the alignment between two images within a specified sub-region regarding a homography by ap...
static void determineErrorJacobianInverseCompositional8BitPerChannel(const Frame &templateFrame, const CV::SubRegion &templateSubRegion, const Frame &transformedCurrentSubFrame, const Frame &transformedCurrentSubFrameMask, const Scalar *templateMeans, const Scalar *currentMeans, const Scalar *jacobianRows, Matrix &jacobianError, Worker *worker)
Determines the product of transposed Jacobian matrix and error vector for the inverse compositional o...
Definition: HomographyImageAlignmentDense.h:642
static bool optimizeAlignmentInverseCompositional(const Frame &templateFrame, const CV::SubRegion &templateSubRegion, const Frame &currentFrame, const SquareMatrix3 &roughHomography, const unsigned int homographyParameters, const bool zeroMean, SquareMatrix3 &homography, const unsigned int iterations=20u, Scalar lambda=10, const Scalar lambdaFactor=10, Scalar *initialError=nullptr, Scalar *finalError=nullptr, Scalars *intermediateErrors=nullptr, ConsistencyDataRef *externalConsistencyData=nullptr, bool *abort=nullptr)
Optimizes the alignment between two images within a specified sub-region regarding a homography by ap...
static Scalar determineError8BitPerChannel(const Frame &templateFrame, const CV::SubRegion &templateSubRegion, const Frame &transformedCurrentSubFrameData, const Frame &transformedCurrentSubFrameMaskData, const Scalar *templateMeans, const Scalar *currentMeans, Worker *worker)
Determines the color intensity error within a sub-region between a template frame and a transformed c...
Definition: HomographyImageAlignmentDense.h:569
static bool determineMeans8BitPerChannel(const Frame &templateFrame, const CV::SubRegion &templateSubRegion, const Frame &transformedCurrentSubFrame, const Frame &transformedCurrentSubFrameMask, Scalar *templateMeans, Scalar *currentMeans, Worker *worker)
Determines the mean color intensities in the corresponding sub-regions of the current transformed fra...
Definition: HomographyImageAlignmentDense.h:499
static bool optimizeAlignmentMultiResolution(const CV::FramePyramid &templateFramePyramid, const std::vector< CV::SubRegion > &templateSubRegions, const CV::FramePyramid &currentFramePyramid, const unsigned int layers, const unsigned int homographyParameters, const bool additiveAlignment, const bool levenbergMarquardtOptimization, const bool zeroMean, const SquareMatrix3 &roughHomography, SquareMatrix3 &homography, const unsigned int coarseIterations=20u, const unsigned int fineIterations=4u, std::vector< Tracking::HomographyImageAlignmentDense::ConsistencyDataRef > *consistencyDatas=nullptr)
Optimizes the alignment between two images within a specified sub-region regarding a homography by ap...
static void determineHessianAndErrorJacobian8BitPerChannel(const Frame &templateFrame, const CV::SubRegion &templateSubRegion, const Frame &transformedCurrentSubFrame, const Frame &transformedCurrentSubFrameMask, const unsigned int transformedBoundingBoxLeft, const unsigned int transformedBoundingBoxTop, const unsigned int transformedBoundingBoxWidth, const unsigned int transformedBoundingBoxHeight, const Frame &gradientCurrentFrame, const SquareMatrix3 &homography, const Scalar *templateMeans, const Scalar *currentMeans, Matrix &hessian, Matrix &jacobianError, Worker *worker)
Determines the Hessian matrix and the product of transposed Jacobian matrix and error vector for a te...
Definition: HomographyImageAlignmentDense.h:610
static void determineMeansMask8BitPerChannelSubset(const Frame *templateFrame, const CV::SubRegion *templateSubRegion, const Frame *transformedCurrentSubFrame, const Frame *transformedCurrentSubFrameMask, Scalar *templateMeans, Scalar *currentMeans, unsigned int *templateMeansDenominator, unsigned int *currentMeansDenominator, Lock *lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused)
Determines the mean color intensities in a subset of the corresponding sub-regions of the current tra...
static Scalar slowDetermineError(const Frame &templateFrame, const CV::SubRegion &templateSubRegion, const Frame &currentFrame, const SquareMatrix3 &homography, const bool zeroMean)
Determines the current error for a given homography between a current frame and a template frame with...
static bool optimizeAlignmentMultiResolution(const Frame &templateFrame, const CV::SubRegion &templateSubRegion, const Frame &currentFrame, const unsigned int numberPyramidLayers, const unsigned int homographyParameters, const bool additiveAlignment, const bool levenbergMarquardtOptimization, const bool zeroMean, const SquareMatrix3 &roughHomography, SquareMatrix3 &homography, const unsigned int coarseIterations=20u, const unsigned int fineIterations=4u, const CV::FramePyramid::DownsamplingMode downsamplingMode=CV::FramePyramid::DM_FILTER_14641)
Optimizes the alignment between two images within a specified sub-region regarding a homography by ap...
static void determineErrorMask8BitPerChannelSubset(const Frame *templateFrame, const CV::SubRegion *templateSubRegion, const Frame *transformedCurrentSubFrame, const Frame *transformedCurrentSubFrameMask, const Scalar *templateMeans, const Scalar *currentMeans, Scalar *squaredError, unsigned int *errorDenominators, Lock *lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused)
Determines the color intensity error in a subset of a sub-region between a template frame and a trans...
static void determineMeans8BitPerChannelSubset(const Frame *templateFrame, const CV::SubRegion *templateSubRegion, const Frame *transformedCurrentSubFrame, Scalar *templateMeans, Scalar *currentMeans, unsigned int *templateMeansDenominator, unsigned int *currentMeansDenominator, Lock *lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused)
Determines the mean color intensities in a subset of the corresponding sub-regions of the current tra...
static void determineHessianAndErrorJacobian8BitPerChannelSubset(const Frame *templateFrame, const CV::SubRegion *templateSubRegion, const Frame *transformedCurrentSubFrame, const unsigned int transformedBoundingBoxLeft, const unsigned int transformedBoundingBoxTop, const unsigned int transformedBoundingBoxWidth, const unsigned int transformedBoundingBoxHeight, const Frame *gradientCurrentFrame, const SquareMatrix3 *homography, const Scalar *templateMeans, const Scalar *currentMeans, Matrix *hessian, Matrix *jacobianError, Lock *lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused)
Determines the subset-Hessian matrix and the subset-product of transposed Jacobian matrix and error v...
ObjectRef< ConsistencyData > ConsistencyDataRef
Definition of an object reference holding a consistency data object.
Definition: HomographyImageAlignmentDense.h:80
static void determineError8BitPerChannelSubset(const Frame *templateFrame, const CV::SubRegion *templateSubRegion, const Frame *transformedCurrentSubFrame, const Scalar *templateMeans, const Scalar *currentMeans, Scalar *squaredError, unsigned int *errorDenominators, Lock *lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused)
Determines the color intensity error in a subset of a sub-region between a template frame and a trans...
static bool slowDetermineHessianAndErrorJacobian8BitPerChannel(const Frame &templateFrame, const CV::SubRegion &templateSubRegion, const Frame &currentFrame, const SquareMatrix3 &homography, const bool zeroMean, Matrix &hessian, Matrix &jacobianError)
Determines the 8x8 or 9x9 Hessian matrix and the 8x1 or 9x1 Jacobian-Error vector for a given homogra...
static void determineHessianAndErrorJacobianMask8BitPerChannelSubset(const Frame *templateFrame, const CV::SubRegion *templateSubRegion, const Frame *transformedCurrentSubFrame, const Frame *transformedCurrentSubFrameMask, const unsigned int transformedBoundingBoxLeft, const unsigned int transformedBoundingBoxTop, const unsigned int transformedBoundingBoxWidth, const unsigned int transformedBoundingBoxHeight, const Frame *gradientCurrentFrame, const SquareMatrix3 *current_H_template, const Scalar *templateMeans, const Scalar *currentMeans, Matrix *hessian, Matrix *jacobianError, Lock *lock, const unsigned int threads, const unsigned int threadIndex, const unsigned int unused)
Determines the subset-Hessian matrix and the subset-product of transposed Jacobian matrix and error v...
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
unsigned int threads() const
Returns the number of threads this worker uses.
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.
float Scalar
Definition of a scalar type.
Definition: Math.h:128
MatrixT< Scalar > Matrix
Definition of the Matrix object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single ...
Definition: Matrix.h:18
std::vector< Scalar > Scalars
Definition of a vector holding Scalar objects.
Definition: Math.h:144
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15