8#ifndef META_OCEAN_CV_MOTION_H
9#define META_OCEAN_CV_MOTION_H
28template <
typename TMetric>
58template <
typename TMetric = SumSquareDifferences>
84 template <
unsigned int tPatchSize>
85 static bool trackPointsInPyramidMirroredBorder(
const Frame& previousFrame,
const Frame& currentFrame,
const PixelPositions& previousPoints,
const PixelPositions& roughPoints,
PixelPositions& currentPoints,
const unsigned int maximalOffset,
const unsigned int coarsestLayerRadiusX,
const unsigned int coarsestLayerRadiusY,
const FramePyramid::DownsamplingMode downsamplingMode =
FramePyramid::DM_FILTER_14641,
Worker* worker =
nullptr, std::vector<uint32_t>* metricResults =
nullptr, std::vector<uint32_t>* metricIdentityResults =
nullptr);
105 template <
unsigned int tPatchSize>
129 template <
unsigned int tChannels,
unsigned int tPatchSize>
130 static PixelPosition pointMotionInFrameMirroredBorder(
const uint8_t*
const frame0,
const uint8_t*
const frame1,
const unsigned int width0,
const unsigned int height0,
const unsigned int width1,
const unsigned int height1,
const PixelPosition& position0,
const unsigned int radiusX,
const unsigned int radiusY,
const unsigned int frame0PaddingElements,
const unsigned int frame1PaddingElements,
const PixelPosition& rough1 =
PixelPosition(), uint32_t*
const metricResult =
nullptr, uint32_t*
const metricIdentityResult =
nullptr);
153 template <
unsigned int tPatchSize>
154 static inline PixelPosition pointMotionInFrameMirroredBorder(
const uint8_t*
const frame0,
const uint8_t*
const frame1,
const unsigned int channels,
const unsigned int width0,
const unsigned int height0,
const unsigned int width1,
const unsigned int height1,
const PixelPosition& position0,
const unsigned int radiusX,
const unsigned int radiusY,
const unsigned int frame0PaddingElements,
const unsigned int frame1PaddingElements,
const PixelPosition& rough1 =
PixelPosition(), uint32_t*
const metricResult =
nullptr, uint32_t*
const metricIdentityResult =
nullptr);
176 template <
unsigned int tPatchSize>
177 static void trackPointsInPyramidMirroredBorderSubset(
const FramePyramid* previousPyramid,
const FramePyramid* currentPyramid,
const unsigned int numberLayers,
const PixelPositions* previousPoints,
const PixelPositions* roughPoints,
PixelPositions* currentPoints,
const unsigned int coarsestLayerRadiusX,
const unsigned int coarsestLayerRadiusY, uint32_t* metricResults, uint32_t* metricIdentityResults,
const unsigned int firstPoint,
const unsigned int numberPoints);
180template <
typename TMetric>
181template <
unsigned int tPatchSize>
182bool MotionT<TMetric>::trackPointsInPyramidMirroredBorder(
const Frame& previousFrame,
const Frame& currentFrame,
const PixelPositions& previousPoints,
const PixelPositions& roughPoints,
PixelPositions& currentPoints,
const unsigned int maximalOffset,
const unsigned int coarsestLayerRadiusX,
const unsigned int coarsestLayerRadiusY,
const FramePyramid::DownsamplingMode downsamplingMode,
Worker* worker, std::vector<uint32_t>* metricResults, std::vector<uint32_t>* metricIdentityResults)
184 static_assert(tPatchSize % 2u == 1u,
"Invalid image patch size, must be odd!");
185 static_assert(tPatchSize >= 3u,
"Invalid image patch size!");
187 ocean_assert(previousFrame && currentFrame);
192 ocean_assert(previousPoints.size() == roughPoints.size());
196 if (idealLayers == 0u)
201 const FramePyramid previousPyramid(previousFrame, downsamplingMode, idealLayers,
false , worker);
202 const FramePyramid currentPyramid(currentFrame, downsamplingMode, idealLayers,
false , worker);
204 return trackPointsInPyramidMirroredBorder<tPatchSize>(previousPyramid, currentPyramid, previousPoints, roughPoints, currentPoints, coarsestLayerRadiusX, coarsestLayerRadiusY, worker, metricResults, metricIdentityResults);
207template <
typename TMetric>
208template <
unsigned int tPatchSize>
211 static_assert(tPatchSize % 2u == 1u,
"Invalid image patch size, must be odd!");
212 static_assert(tPatchSize >= 3u,
"Invalid image patch size, must be larger than 2!");
218 const unsigned int numberLayers = std::min(std::min(previousPyramid.
layers(), currentPyramid.
layers()), idealLayers);
220 if (numberLayers == 0u)
225 currentPoints.resize(previousPoints.size());
227 if (metricResults !=
nullptr)
229 metricResults->resize(previousPoints.size());
232 if (metricIdentityResults !=
nullptr)
234 metricIdentityResults->resize(previousPoints.size());
237 if (worker !=
nullptr)
239 worker->
executeFunction(
Worker::Function::createStatic(&MotionT::trackPointsInPyramidMirroredBorderSubset<tPatchSize>, &previousPyramid, ¤tPyramid, numberLayers, &previousPoints, &roughPoints, ¤tPoints, coarsestLayerRadiusX, coarsestLayerRadiusY, metricResults ? metricResults->data() :
nullptr, metricIdentityResults ? metricIdentityResults->data() :
nullptr, 0u, 0u), 0u, (
unsigned int)(previousPoints.size()));
243 trackPointsInPyramidMirroredBorderSubset<tPatchSize>(&previousPyramid, ¤tPyramid, numberLayers, &previousPoints, &roughPoints, ¤tPoints, coarsestLayerRadiusX, coarsestLayerRadiusY, metricResults ? metricResults->data() :
nullptr, metricIdentityResults ? metricIdentityResults->data() :
nullptr, 0u, (
unsigned int)(previousPoints.size()));
249template <
typename TMetric>
250template <
unsigned int tChannels,
unsigned int tPatchSize>
251PixelPosition MotionT<TMetric>::pointMotionInFrameMirroredBorder(
const uint8_t*
const frame0,
const uint8_t*
const frame1,
const unsigned int width0,
const unsigned int height0,
const unsigned int width1,
const unsigned int height1,
const PixelPosition& position0,
const unsigned int radiusX,
const unsigned int radiusY,
const unsigned int frame0PaddingElements,
const unsigned int frame1PaddingElements,
const PixelPosition& rough1, uint32_t*
const metricResult, uint32_t*
const metricIdentityResult)
253 static_assert(tChannels != 0u,
"Invalid number of data channels!");
254 static_assert(tPatchSize % 2u == 1u,
"Invalid size of the image patch, must be odd!");
256 constexpr unsigned int tPatchSize_2 = tPatchSize / 2u;
258 ocean_assert(frame0 !=
nullptr && frame1 !=
nullptr);
259 ocean_assert(radiusX != 0u || radiusY != 0u);
261 ocean_assert(width0 >= tPatchSize_2 && height0 >= tPatchSize_2);
262 ocean_assert(width1 >= tPatchSize_2 && height1 >= tPatchSize_2);
264 ocean_assert(position0.
x() < width0);
265 ocean_assert(position0.
y() < height0);
267 const PixelPosition position1((rough1 && rough1.
x() < width1 && rough1.
y() < height1) ? rough1 : position0);
268 ocean_assert(position1.
x() < width1);
269 ocean_assert(position1.
y() < height1);
271 const unsigned int leftCenter1 = (
unsigned int)(max(0,
int(position1.
x() - radiusX)));
272 const unsigned int topCenter1 = (
unsigned int)(max(0,
int(position1.
y() - radiusY)));
274 const unsigned int rightCenter1 = min(position1.
x() + radiusX, width1 - 1u);
275 const unsigned int bottomCenter1 = min(position1.
y() + radiusY, height1 - 1u);
277 ocean_assert(leftCenter1 < width1 && leftCenter1 <= rightCenter1 && rightCenter1 < width1);
278 ocean_assert(topCenter1 < height1 && topCenter1 <= bottomCenter1 && bottomCenter1 < height1);
281 uint32_t bestMetric = uint32_t(-1);
282 uint32_t bestSqrDistance = uint32_t(-1);
285 if ((position0.
x() >= tPatchSize_2 && position0.
y() >= tPatchSize_2 && position0.
x() + tPatchSize_2 < width0 && position0.
y() + tPatchSize_2 < height0))
287 for (
unsigned int y1 = topCenter1; y1 <= bottomCenter1; ++y1)
289 for (
unsigned int x1 = leftCenter1; x1 <= rightCenter1; ++x1)
293 const uint32_t metric = (x1 - tPatchSize_2 < width1 - (tPatchSize - 1u) && y1 - tPatchSize_2 < height1 - (tPatchSize - 1u)) ?
294 TMetric::template patch8BitPerChannel<tChannels, tPatchSize>(frame0, frame1, width0, width1, position0.
x(), position0.
y(), x1, y1, frame0PaddingElements, frame1PaddingElements) :
295 TMetric::template patchMirroredBorder8BitPerChannel<tChannels, tPatchSize>(frame0, frame1, width0, height0, width1, height1, position0.
x(), position0.
y(), x1, y1, frame0PaddingElements, frame1PaddingElements);
299 if (metric < bestMetric || (metric == bestMetric && position1.
sqrDistance(position) < bestSqrDistance))
302 bestPosition = position;
307 if (metricIdentityResult && x1 == position1.
x() && y1 == position1.
y())
309 *metricIdentityResult = metric;
316 for (
unsigned int y1 = topCenter1; y1 <= bottomCenter1; ++y1)
318 for (
unsigned int x1 = leftCenter1; x1 <= rightCenter1; ++x1)
320 const uint32_t metric = TMetric::template patchMirroredBorder8BitPerChannel<tChannels, tPatchSize>(frame0, frame1, width0, height0, width1, height1, position0.
x(), position0.
y(), x1, y1, frame0PaddingElements, frame1PaddingElements);
324 if (metric < bestMetric || (metric == bestMetric && position1.
sqrDistance(position) < bestSqrDistance))
327 bestPosition = position;
332 if (metricIdentityResult && x1 == position1.
x() && y1 == position1.
y())
334 *metricIdentityResult = metric;
340 ocean_assert(bestMetric != uint32_t(-1) && bestPosition.
isValid());
344 *metricResult = bestMetric;
347 ocean_assert(abs(
int(bestPosition.
x()) -
int(position1.
x())) <=
int(radiusX));
348 ocean_assert(abs(
int(bestPosition.
y()) -
int(position1.
y())) <=
int(radiusY));
353template <
typename TMetric>
354template <
unsigned int tPatchSize>
355inline PixelPosition MotionT<TMetric>::pointMotionInFrameMirroredBorder(
const uint8_t*
const frame0,
const uint8_t*
const frame1,
const unsigned int channels,
const unsigned int width0,
const unsigned int height0,
const unsigned int width1,
const unsigned int height1,
const PixelPosition& position0,
const unsigned int radiusX,
const unsigned int radiusY,
const unsigned int frame0PaddingElements,
const unsigned int frame1PaddingElements,
const PixelPosition& rough1, uint32_t*
const metricResult, uint32_t*
const metricIdentityResult)
357 ocean_assert(channels >= 1u);
362 return pointMotionInFrameMirroredBorder<1u, tPatchSize>(frame0, frame1, width0, height0, width1, height1, position0, radiusX, radiusY, frame0PaddingElements, frame1PaddingElements, rough1, metricResult, metricIdentityResult);
365 return pointMotionInFrameMirroredBorder<2u, tPatchSize>(frame0, frame1, width0, height0, width1, height1, position0, radiusX, radiusY, frame0PaddingElements, frame1PaddingElements, rough1, metricResult, metricIdentityResult);
368 return pointMotionInFrameMirroredBorder<3u, tPatchSize>(frame0, frame1, width0, height0, width1, height1, position0, radiusX, radiusY, frame0PaddingElements, frame1PaddingElements, rough1, metricResult, metricIdentityResult);
371 return pointMotionInFrameMirroredBorder<4u, tPatchSize>(frame0, frame1, width0, height0, width1, height1, position0, radiusX, radiusY, frame0PaddingElements, frame1PaddingElements, rough1, metricResult, metricIdentityResult);
374 ocean_assert(
false &&
"Invalid pixel format!");
378template <
typename TMetric>
379template <
unsigned int tPatchSize>
380void MotionT<TMetric>::trackPointsInPyramidMirroredBorderSubset(
const FramePyramid* previousPyramid,
const FramePyramid* currentPyramid,
const unsigned int numberLayers,
const PixelPositions* previousPoints,
const PixelPositions* roughPoints,
PixelPositions* currentPoints,
const unsigned int coarsestLayerRadiusX,
const unsigned int coarsestLayerRadiusY, uint32_t* metricResults, uint32_t* metricIdentityResults,
const unsigned int firstPoint,
const unsigned int numberPoints)
382 static_assert(tPatchSize % 2u == 1u,
"Invalid image patch size!");
383 static_assert(tPatchSize >= 3u,
"Invalid image patch size!");
385 ocean_assert(previousPyramid && currentPyramid);
386 ocean_assert(previousPoints && roughPoints && currentPoints);
388 ocean_assert(*previousPyramid && *currentPyramid);
393 ocean_assert(previousPyramid->
layers() >= 1u && currentPyramid->
layers() >= 1u);
395 ocean_assert(previousPoints->size() == roughPoints->size());
396 ocean_assert(currentPoints->size() == previousPoints->size());
398 ocean_assert(coarsestLayerRadiusX != 0u || coarsestLayerRadiusY != 0u);
400 ocean_assert(firstPoint + numberPoints <= previousPoints->size());
402 ocean_assert(numberLayers >= 1u);
403 ocean_assert(numberLayers <= previousPyramid->layers());
404 ocean_assert(numberLayers <= currentPyramid->layers());
406 ocean_assert(previousPyramid->
layer(numberLayers - 1u).
width() >= tPatchSize / 2u);
407 ocean_assert(previousPyramid->
layer(numberLayers - 1u).
height() >= tPatchSize / 2u);
411 const unsigned int lowestCurrentWidth = currentPyramid->
layer(numberLayers - 1u).
width();
412 const unsigned int lowestCurrentHeight = currentPyramid->
layer(numberLayers - 1u).
height();
413 const unsigned int lowestLayerFactor = currentPyramid->
sizeFactor(numberLayers - 1u);
414 ocean_assert(lowestCurrentWidth >= 1u && lowestCurrentHeight >= 1u);
417 ocean_assert(channels >= 1u && channels <= 4u);
419 for (
unsigned int n = firstPoint; n < firstPoint + numberPoints; ++n)
423 const unsigned int x = min((roughPoint.
x() + lowestLayerFactor / 2u) / lowestLayerFactor, lowestCurrentWidth - 1u);
424 const unsigned int y = min((roughPoint.
y() + lowestLayerFactor / 2u) / lowestLayerFactor, lowestCurrentHeight - 1u);
429 unsigned int layerRadiusX = coarsestLayerRadiusX;
430 unsigned int layerRadiusY = coarsestLayerRadiusY;
432 for (
unsigned int layerIndex = numberLayers - 1u; layerIndex < numberLayers; --layerIndex)
434 const Frame& previousFrame = (*previousPyramid)[layerIndex];
435 const Frame& currentFrame = (*currentPyramid)[layerIndex];
437 const unsigned int previousWidth = previousFrame.
width();
438 const unsigned int previousHeight = previousFrame.
height();
440 const unsigned int currentWidth = currentFrame.
width();
441 const unsigned int currentHeight = currentFrame.
height();
443 for (
unsigned int i = firstPoint; i < firstPoint + numberPoints; ++i)
445 ocean_assert(intermediateRoughPoints[i].x() < currentWidth && intermediateRoughPoints[i].y() < currentHeight);
447 PixelPosition& intermediateRoughPoint = intermediateRoughPoints[i];
449 uint32_t*
const metricResult = metricResults ? metricResults + i :
nullptr;
450 uint32_t*
const metricIdentityResult = (layerIndex == 0u && metricIdentityResults) ? metricIdentityResults + i :
nullptr;
452 ocean_assert(layerIndex < 31u);
453 const unsigned int layerFactor = 1u << layerIndex;
455 const PixelPosition previousPosition(min(((*previousPoints)[i].x() + layerFactor / 2u) / layerFactor, previousWidth - 1u), min(((*previousPoints)[i].y() + layerFactor / 2u) / layerFactor, previousHeight - 1u));
457 if (previousPosition.
x() < previousWidth && previousPosition.
y() < previousHeight)
459 const PixelPosition position(pointMotionInFrameMirroredBorder<tPatchSize>(previousFrame.
constdata<uint8_t>(), currentFrame.
constdata<uint8_t>(), channels, previousWidth, previousHeight, currentWidth, currentHeight, previousPosition, layerRadiusX, layerRadiusY, previousFrame.
paddingElements(), currentFrame.
paddingElements(), intermediateRoughPoint, metricResult, metricIdentityResult));
461 ocean_assert(position.
x() < currentWidth && position.
y() < currentHeight);
464 if (layerIndex == 0u)
466 ocean_assert(i < currentPoints->size());
467 (*currentPoints)[i] = position;
472 const unsigned int higherWidth = currentPyramid->
layer(layerIndex - 1u).
width();
473 const unsigned int higherHeight = currentPyramid->
layer(layerIndex - 1u).
height();
475 intermediateRoughPoint =
PixelPosition(min(position.
x() * 2u, higherWidth - 1u), min(position.
y() * 2u, higherHeight - 1u));
481 if (layerIndex == 0u)
483 ocean_assert(i < currentPoints->size());
484 (*currentPoints)[i] = intermediateRoughPoint;
488 intermediateRoughPoint =
PixelPosition((intermediateRoughPoint.
x() * 2u + layerFactor / 2u) / layerFactor, (intermediateRoughPoint.
y() * 2u + layerFactor / 2u) / layerFactor);
This class implements a frame pyramid.
Definition FramePyramid.h:46
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.
unsigned int finestWidth() const
Returns the width of the finest (first) layer.
Definition FramePyramid.h:828
DownsamplingMode
Definition of individual down sampling modes.
Definition FramePyramid.h:53
@ DM_FILTER_14641
Down sampling is realized by a 5x5 Gaussian filter.
Definition FramePyramid.h:81
static constexpr unsigned int sizeFactor(const unsigned int layerIndex)
Returns the size factor of a specified layer in relation to the finest layer.
Definition FramePyramid.h:884
unsigned int layers() const
Returns the number of layers this pyramid holds.
Definition FramePyramid.h:811
const FrameType & frameType() const
Returns the frame type of the finest layer.
Definition FramePyramid.h:861
unsigned int finestHeight() const
Returns the height of the finest (first) layer.
Definition FramePyramid.h:834
const Frame & layer(const unsigned int layer) const
Returns the frame of a specified layer.
Definition FramePyramid.h:773
This class implements patch-based motion techniques.
Definition Motion.h:60
static void trackPointsInPyramidMirroredBorderSubset(const FramePyramid *previousPyramid, const FramePyramid *currentPyramid, const unsigned int numberLayers, const PixelPositions *previousPoints, const PixelPositions *roughPoints, PixelPositions *currentPoints, const unsigned int coarsestLayerRadiusX, const unsigned int coarsestLayerRadiusY, uint32_t *metricResults, uint32_t *metricIdentityResults, const unsigned int firstPoint, const unsigned int numberPoints)
Tracks a subset of given points between two frame pyramids.
Definition Motion.h:380
static PixelPosition pointMotionInFrameMirroredBorder(const uint8_t *const frame0, const uint8_t *const frame1, const unsigned int width0, const unsigned int height0, const unsigned int width1, const unsigned int height1, const PixelPosition &position0, const unsigned int radiusX, const unsigned int radiusY, const unsigned int frame0PaddingElements, const unsigned int frame1PaddingElements, const PixelPosition &rough1=PixelPosition(), uint32_t *const metricResult=nullptr, uint32_t *const metricIdentityResult=nullptr)
Determines the motion for one given point between two frames by application of an image patch.
Definition Motion.h:251
static bool trackPointsInPyramidMirroredBorder(const Frame &previousFrame, const Frame ¤tFrame, const PixelPositions &previousPoints, const PixelPositions &roughPoints, PixelPositions ¤tPoints, const unsigned int maximalOffset, const unsigned int coarsestLayerRadiusX, const unsigned int coarsestLayerRadiusY, const FramePyramid::DownsamplingMode downsamplingMode=FramePyramid::DM_FILTER_14641, Worker *worker=nullptr, std::vector< uint32_t > *metricResults=nullptr, std::vector< uint32_t > *metricIdentityResults=nullptr)
Tracks a set of given points between two frames with pixel accuracy.
Definition Motion.h:182
bool isValid() const
Returns whether this pixel position object holds two valid parameters.
T y() const
Returns the vertical coordinate position of this object.
Definition PixelPosition.h:468
unsigned int sqrDistance(const PixelPositionT< T > &position) const
Returns the square difference between two pixel positions.
Definition PixelPosition.h:487
T x() const
Returns the horizontal coordinate position of this object.
Definition PixelPosition.h:456
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:2877
This class implements Ocean's image class.
Definition Frame.h:1879
const T * constdata(const unsigned int planeIndex=0u) const
Returns a pointer to the read-only pixel data of a specific plane.
Definition Frame.h:4332
const FrameType & frameType() const
Returns the frame type of this frame.
Definition Frame.h:3936
unsigned int paddingElements(const unsigned int planeIndex=0u) const
Returns the optional number of padding elements at the end of each row for a specific plane.
Definition Frame.h:4206
unsigned int width() const
Returns the width of the frame format in pixel.
Definition Frame.h:3241
PixelOrigin pixelOrigin() const
Returns the pixel origin of the frame.
Definition Frame.h:3286
PixelFormat pixelFormat() const
Returns the pixel format of the frame.
Definition Frame.h:3251
unsigned int height() const
Returns the height of the frame in pixel.
Definition Frame.h:3246
unsigned int channels() const
Returns the number of individual channels the frame has.
Definition Frame.h:3271
This class implements a vector with shifted elements.
Definition ShiftVector.h:27
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< PixelPosition > PixelPositions
Definition of a vector holding pixel positions (with positive coordinate values).
Definition PixelPosition.h:46
PixelPositionT< unsigned int > PixelPosition
Definition of the default PixelPosition object with a data type allowing only positive coordinate val...
Definition PixelPosition.h:32
The namespace covering the entire Ocean framework.
Definition Accessor.h:15