8 #ifndef META_OCEAN_CV_MOTION_H
9 #define META_OCEAN_CV_MOTION_H
28 template <
typename TMetric>
class Motion;
57 template <
typename TMetric = SumSquareDifferences>
83 template <
unsigned int tPatchSize>
84 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);
104 template <
unsigned int tPatchSize>
128 template <
unsigned int tChannels,
unsigned int tPatchSize>
129 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);
152 template <
unsigned int tPatchSize>
153 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);
175 template <
unsigned int tPatchSize>
176 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);
179 template <
typename TMetric>
180 template <
unsigned int tPatchSize>
181 bool Motion<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)
183 static_assert(tPatchSize % 2u == 1u,
"Invalid image patch size, must be odd!");
184 static_assert(tPatchSize >= 3u,
"Invalid image patch size!");
186 ocean_assert(previousFrame && currentFrame);
191 ocean_assert(previousPoints.size() == roughPoints.size());
195 if (idealLayers == 0u)
200 const FramePyramid previousPyramid(previousFrame, downsamplingMode, idealLayers,
false , worker);
201 const FramePyramid currentPyramid(currentFrame, downsamplingMode, idealLayers,
false , worker);
203 return trackPointsInPyramidMirroredBorder<tPatchSize>(previousPyramid, currentPyramid, previousPoints, roughPoints, currentPoints, coarsestLayerRadiusX, coarsestLayerRadiusY, worker, metricResults, metricIdentityResults);
206 template <
typename TMetric>
207 template <
unsigned int tPatchSize>
210 static_assert(tPatchSize % 2u == 1u,
"Invalid image patch size, must be odd!");
211 static_assert(tPatchSize >= 3u,
"Invalid image patch size, must be larger than 2!");
217 const unsigned int numberLayers = std::min(std::min(previousPyramid.
layers(), currentPyramid.
layers()), idealLayers);
219 if (numberLayers == 0u)
224 currentPoints.resize(previousPoints.size());
228 metricResults->resize(previousPoints.size());
231 if (metricIdentityResults)
233 metricIdentityResults->resize(previousPoints.size());
238 worker->
executeFunction(
Worker::Function::createStatic(&Motion::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()));
242 trackPointsInPyramidMirroredBorderSubset<tPatchSize>(&previousPyramid, ¤tPyramid, numberLayers, &previousPoints, &roughPoints, ¤tPoints, coarsestLayerRadiusX, coarsestLayerRadiusY, metricResults ? metricResults->data() :
nullptr, metricIdentityResults ? metricIdentityResults->data() :
nullptr, 0u, (
unsigned int)(previousPoints.size()));
248 template <
typename TMetric>
249 template <
unsigned int tChannels,
unsigned int tPatchSize>
250 PixelPosition Motion<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)
252 static_assert(tChannels != 0u,
"Invalid number of data channels!");
253 static_assert(tPatchSize % 2u == 1u,
"Invalid size of the image patch, must be odd!");
255 constexpr
unsigned int tPatchSize_2 = tPatchSize / 2u;
257 ocean_assert(frame0 !=
nullptr && frame1 !=
nullptr);
258 ocean_assert(radiusX != 0u || radiusY != 0u);
260 ocean_assert(width0 >= tPatchSize_2 && height0 >= tPatchSize_2);
261 ocean_assert(width1 >= tPatchSize_2 && height1 >= tPatchSize_2);
263 ocean_assert(position0.
x() < width0);
264 ocean_assert(position0.
y() < height0);
266 const PixelPosition position1((rough1 && rough1.
x() < width1 && rough1.
y() < height1) ? rough1 : position0);
267 ocean_assert(position1.
x() < width1);
268 ocean_assert(position1.
y() < height1);
270 const unsigned int leftCenter1 = (
unsigned int)(max(0,
int(position1.
x() - radiusX)));
271 const unsigned int topCenter1 = (
unsigned int)(max(0,
int(position1.
y() - radiusY)));
273 const unsigned int rightCenter1 = min(position1.
x() + radiusX, width1 - 1u);
274 const unsigned int bottomCenter1 = min(position1.
y() + radiusY, height1 - 1u);
276 ocean_assert(leftCenter1 < width1 && leftCenter1 <= rightCenter1 && rightCenter1 < width1);
277 ocean_assert(topCenter1 < height1 && topCenter1 <= bottomCenter1 && bottomCenter1 < height1);
280 uint32_t bestMetric = uint32_t(-1);
281 uint32_t bestSqrDistance = uint32_t(-1);
284 if ((position0.
x() >= tPatchSize_2 && position0.
y() >= tPatchSize_2 && position0.
x() + tPatchSize_2 < width0 && position0.
y() + tPatchSize_2 < height0))
286 for (
unsigned int y1 = topCenter1; y1 <= bottomCenter1; ++y1)
288 for (
unsigned int x1 = leftCenter1; x1 <= rightCenter1; ++x1)
292 const uint32_t metric = (x1 - tPatchSize_2 < width1 - (tPatchSize - 1u) && y1 - tPatchSize_2 < height1 - (tPatchSize - 1u)) ?
293 TMetric::template patch8BitPerChannel<tChannels, tPatchSize>(frame0, frame1, width0, width1, position0.
x(), position0.
y(), x1, y1, frame0PaddingElements, frame1PaddingElements) :
294 TMetric::template patchMirroredBorder8BitPerChannel<tChannels, tPatchSize>(frame0, frame1, width0, height0, width1, height1, position0.
x(), position0.
y(), x1, y1, frame0PaddingElements, frame1PaddingElements);
298 if (metric < bestMetric || (metric == bestMetric && position1.
sqrDistance(position) < bestSqrDistance))
301 bestPosition = position;
306 if (metricIdentityResult && x1 == position1.
x() && y1 == position1.
y())
308 *metricIdentityResult = metric;
315 for (
unsigned int y1 = topCenter1; y1 <= bottomCenter1; ++y1)
317 for (
unsigned int x1 = leftCenter1; x1 <= rightCenter1; ++x1)
319 const uint32_t metric = TMetric::template patchMirroredBorder8BitPerChannel<tChannels, tPatchSize>(frame0, frame1, width0, height0, width1, height1, position0.
x(), position0.
y(), x1, y1, frame0PaddingElements, frame1PaddingElements);
323 if (metric < bestMetric || (metric == bestMetric && position1.
sqrDistance(position) < bestSqrDistance))
326 bestPosition = position;
331 if (metricIdentityResult && x1 == position1.
x() && y1 == position1.
y())
333 *metricIdentityResult = metric;
339 ocean_assert(bestMetric != uint32_t(-1) && bestPosition.
isValid());
343 *metricResult = bestMetric;
346 ocean_assert(abs(
int(bestPosition.
x()) -
int(position1.
x())) <=
int(radiusX));
347 ocean_assert(abs(
int(bestPosition.
y()) -
int(position1.
y())) <=
int(radiusY));
352 template <
typename TMetric>
353 template <
unsigned int tPatchSize>
354 inline PixelPosition Motion<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)
356 ocean_assert(channels >= 1u);
361 return pointMotionInFrameMirroredBorder<1u, tPatchSize>(frame0, frame1, width0, height0, width1, height1, position0, radiusX, radiusY, frame0PaddingElements, frame1PaddingElements, rough1, metricResult, metricIdentityResult);
364 return pointMotionInFrameMirroredBorder<2u, tPatchSize>(frame0, frame1, width0, height0, width1, height1, position0, radiusX, radiusY, frame0PaddingElements, frame1PaddingElements, rough1, metricResult, metricIdentityResult);
367 return pointMotionInFrameMirroredBorder<3u, tPatchSize>(frame0, frame1, width0, height0, width1, height1, position0, radiusX, radiusY, frame0PaddingElements, frame1PaddingElements, rough1, metricResult, metricIdentityResult);
370 return pointMotionInFrameMirroredBorder<4u, tPatchSize>(frame0, frame1, width0, height0, width1, height1, position0, radiusX, radiusY, frame0PaddingElements, frame1PaddingElements, rough1, metricResult, metricIdentityResult);
373 ocean_assert(
false &&
"Invalid pixel format!");
377 template <
typename TMetric>
378 template <
unsigned int tPatchSize>
379 void Motion<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)
381 static_assert(tPatchSize % 2u == 1u,
"Invalid image patch size!");
382 static_assert(tPatchSize >= 3u,
"Invalid image patch size!");
384 ocean_assert(previousPyramid && currentPyramid);
385 ocean_assert(previousPoints && roughPoints && currentPoints);
387 ocean_assert(*previousPyramid && *currentPyramid);
392 ocean_assert(previousPyramid->
layers() >= 1u && currentPyramid->
layers() >= 1u);
394 ocean_assert(previousPoints->size() == roughPoints->size());
395 ocean_assert(currentPoints->size() == previousPoints->size());
397 ocean_assert(coarsestLayerRadiusX != 0u || coarsestLayerRadiusY != 0u);
399 ocean_assert(firstPoint + numberPoints <= previousPoints->size());
401 ocean_assert(numberLayers >= 1u);
402 ocean_assert(numberLayers <= previousPyramid->layers());
403 ocean_assert(numberLayers <= currentPyramid->layers());
405 ocean_assert(previousPyramid->
layer(numberLayers - 1u).
width() >= tPatchSize / 2u);
406 ocean_assert(previousPyramid->
layer(numberLayers - 1u).
height() >= tPatchSize / 2u);
410 const unsigned int lowestCurrentWidth = currentPyramid->
layer(numberLayers - 1u).
width();
411 const unsigned int lowestCurrentHeight = currentPyramid->
layer(numberLayers - 1u).
height();
412 const unsigned int lowestLayerFactor = currentPyramid->
sizeFactor(numberLayers - 1u);
413 ocean_assert(lowestCurrentWidth >= 1u && lowestCurrentHeight >= 1u);
416 ocean_assert(channels >= 1u && channels <= 4u);
418 for (
unsigned int n = firstPoint; n < firstPoint + numberPoints; ++n)
422 const unsigned int x = min((roughPoint.
x() + lowestLayerFactor / 2u) / lowestLayerFactor, lowestCurrentWidth - 1u);
423 const unsigned int y = min((roughPoint.
y() + lowestLayerFactor / 2u) / lowestLayerFactor, lowestCurrentHeight - 1u);
428 unsigned int layerRadiusX = coarsestLayerRadiusX;
429 unsigned int layerRadiusY = coarsestLayerRadiusY;
431 for (
unsigned int layerIndex = numberLayers - 1u; layerIndex < numberLayers; --layerIndex)
433 const Frame& previousFrame = (*previousPyramid)[layerIndex];
434 const Frame& currentFrame = (*currentPyramid)[layerIndex];
436 const unsigned int previousWidth = previousFrame.
width();
437 const unsigned int previousHeight = previousFrame.
height();
439 const unsigned int currentWidth = currentFrame.
width();
440 const unsigned int currentHeight = currentFrame.
height();
442 for (
unsigned int i = firstPoint; i < firstPoint + numberPoints; ++i)
444 ocean_assert(intermediateRoughPoints[i].x() < currentWidth && intermediateRoughPoints[i].y() < currentHeight);
446 PixelPosition& intermediateRoughPoint = intermediateRoughPoints[i];
448 uint32_t*
const metricResult = metricResults ? metricResults + i :
nullptr;
449 uint32_t*
const metricIdentityResult = (layerIndex == 0u && metricIdentityResults) ? metricIdentityResults + i :
nullptr;
451 ocean_assert(layerIndex < 31u);
452 const unsigned int layerFactor = 1u << layerIndex;
454 const PixelPosition previousPosition(min(((*previousPoints)[i].x() + layerFactor / 2u) / layerFactor, previousWidth - 1u), min(((*previousPoints)[i].y() + layerFactor / 2u) / layerFactor, previousHeight - 1u));
456 if (previousPosition.
x() < previousWidth && previousPosition.
y() < previousHeight)
458 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));
460 ocean_assert(position.
x() < currentWidth && position.
y() < currentHeight);
463 if (layerIndex == 0u)
465 ocean_assert(i < currentPoints->size());
466 (*currentPoints)[i] = position;
471 const unsigned int higherWidth = currentPyramid->
layer(layerIndex - 1u).
width();
472 const unsigned int higherHeight = currentPyramid->
layer(layerIndex - 1u).
height();
474 intermediateRoughPoint =
PixelPosition(min(position.
x() * 2u, higherWidth - 1u), min(position.
y() * 2u, higherHeight - 1u));
480 if (layerIndex == 0u)
482 ocean_assert(i < currentPoints->size());
483 (*currentPoints)[i] = intermediateRoughPoint;
487 intermediateRoughPoint =
PixelPosition((intermediateRoughPoint.
x() * 2u + layerFactor / 2u) / layerFactor, (intermediateRoughPoint.
y() * 2u + layerFactor / 2u) / layerFactor);
This class implements a frame pyramid.
Definition: FramePyramid.h:37
static unsigned int idealLayers(const unsigned int width, const unsigned int height, const unsigned int invalidCoarsestWidthOrHeight, unsigned int *coarsestLayerWidth=nullptr, unsigned int *coarsestLayerHeight=nullptr)
Determines the number of layers until an invalid frame size would be reached in the next layer.
unsigned int finestWidth() const
Returns the width of the finest (first) layer.
Definition: FramePyramid.h:778
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
unsigned int layers() const
Returns the number of layers this pyramid holds.
Definition: FramePyramid.h:761
const FrameType & frameType() const
Returns the frame type of the finest layer.
Definition: FramePyramid.h:811
unsigned int finestHeight() const
Returns the height of the finest (first) layer.
Definition: FramePyramid.h:784
static constexpr unsigned int sizeFactor(const unsigned int layer)
Returns the size factor of a specified layer in relation to the finest layer.
Definition: FramePyramid.h:834
const Frame & layer(const unsigned int layer) const
Returns the frame of a specified layer.
Definition: FramePyramid.h:723
This class implements patch-based motion techniques.
Definition: Motion.h:59
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:250
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:379
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:181
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:470
unsigned int sqrDistance(const PixelPositionT< T > &position) const
Returns the square difference between two pixel positions.
Definition: PixelPosition.h:489
T x() const
Returns the horizontal coordinate position of this object.
Definition: PixelPosition.h:458
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
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:4168
const FrameType & frameType() const
Returns the frame type of this frame.
Definition: Frame.h:3775
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:4042
unsigned int width() const
Returns the width of the frame format in pixel.
Definition: Frame.h:3143
PixelOrigin pixelOrigin() const
Returns the pixel origin of the frame.
Definition: Frame.h:3188
PixelFormat pixelFormat() const
Returns the pixel format of the frame.
Definition: Frame.h:3153
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
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.
Motion< ZeroMeanSumSquareDifferences > MotionZeroMeanSSD
Definition of a Motion class that applies zero-mean sum square difference calculations as metric.
Definition: Motion.h:49
std::vector< PixelPosition > PixelPositions
Definition of a vector holding pixel positions (with positive coordinate values).
Definition: PixelPosition.h:48
Motion< SumAbsoluteDifferences > MotionSAD
Definition of a Motion class that applies sum absolute difference calculations as metric.
Definition: Motion.h:28
Motion< SumSquareDifferences > MotionSSD
Definition of a Motion class that applies sum square difference calculations as metric.
Definition: Motion.h:42
PixelPositionT< unsigned int > PixelPosition
Definition of the default PixelPosition object with a data type allowing only positive coordinate val...
Definition: PixelPosition.h:27
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15