1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright (c) 2012-2017 VideoStitch SAS
// Copyright (c) 2018 stitchEm
#pragma once
#include "gpu/buffer.hpp"
#include "gpu/stream.hpp"
#include "libvideostitch/status.hpp"
#include "libvideostitch/ptv.hpp"
#include "core/rect.hpp"
#include <vector>
namespace VideoStitch {
namespace Util {
class OpticalFlow {
public:
static Status putOverOriginalFlow(const int2 inputOffset, const int2 inputSize,
const GPU::Buffer<const float2> inputFlow, const int2 outputOffset,
const int2 outputSize, GPU::Buffer<float2> outputFlow, GPU::Stream gpuStream);
static Status backwardCoordLookup(const int2 inputOffset, const int2 inputSize,
const GPU::Buffer<const float2> inputCoordBuffer, const int2 outputOffset,
const int2 outputSize, GPU::Buffer<float2> outputCoordBuffer,
GPU::Stream gpuStream);
static Status forwardCoordLookup(const int2 inputOffset, const int2 inputSize,
const GPU::Buffer<const float2> inputCoordBuffer, const int2 originalOffset,
const int2 originalSize, const GPU::Buffer<const float2> originalCoordBuffer,
const int2 outputOffset, const int2 outputSize,
GPU::Buffer<float2> outputCoordBuffer, GPU::Stream gpuStream);
/**
* @brief This function is used for debugging purpose.
*/
static Status outwardCoordLookup(const int2 offset1, const int2 size1, const GPU::Buffer<const float2> coordBuffer,
const int2 offset0, const int2 size0, const GPU::Buffer<const uint32_t> inputBuffer,
GPU::Buffer<uint32_t> outputBuffer, GPU::Stream gpuStream);
/**
* @brief Lookup RGBA image pixel from a flow buffer
*/
static Status coordLookup(const int outputWidth, const int outputHeight, const GPU::Buffer<const float2> coordBuffer,
const int inputWidth, const int inputHeight, const GPU::Buffer<const uint32_t> inputBuffer,
GPU::Buffer<uint32_t> outputBuffer, GPU::Stream gpuStream);
/**
* @brief Generate identity flow buffer
*/
static Status generateIdentityFlow(const int2 size, GPU::Buffer<float2> coordBuffer, GPU::Stream gpuStream,
const bool normalizedFlow = false);
/**
* Transform an offset to flow field.
* @param size0 Size of the buffer
* @param offset0 Offset of the first buffer
* @param offset1 Offset of the second buffer.
* @param buffer The offset buffer --> The output flow buffer.
* @param gpuStream CUDA stream for the operation.
*/
static Status transformOffsetToFlow(const int2 size0, const int2 offset0, const int2 offset1,
GPU::Buffer<float2> buffer, GPU::Stream gpuStream);
/**
* Transform an offset field to flow field.
* @param size0 Size of the buffer.
* @param offset0 Offset of the first buffer.
* @param offset1 Offset of the second buffer.
* @param inputBuffer The input offset buffer.
* @param outputBuffer The output flow buffer.
* @param gpuStream CUDA stream for the operation.
*/
static Status transformOffsetToFlow(const int2 size0, const int2 offset0, const int2 offset1,
const GPU::Buffer<const float2> inputBuffer, GPU::Buffer<float2> outputBuffer,
GPU::Stream gpuStream);
/**
* Transform a flow field to an offset field.
* @param size0 Size of the buffer.
* @param offset0 Offset of the first buffer.
* @param offset1 Offset of the second buffer.
* @param inputBuffer The input flow buffer.
* @param outputBuffer The output offset buffer.
* @param gpuStream CUDA stream for the operation.
*/
static Status transformFlowToOffset(const int2 size0, const int2 offset0, const int2 offset1,
const GPU::Buffer<const float2> inputBuffer, GPU::Buffer<float2> outputBuffer,
GPU::Stream gpuStream);
/**
* @brief Multiply a flow buffer with a constant. Do nothing on pixel with invalid flow.
*/
static Status mulFlowOperator(GPU::Buffer<float2> dst, const float2 toMul, std::size_t size, GPU::Stream stream);
/**
* @brief Multiply two flow buffers. Do nothing on pixel with invalid flow value.
*/
static Status mulFlowOperator(GPU::Buffer<float2> dst, GPU::Buffer<const float2> src, const float2 toMul,
std::size_t size, GPU::Stream stream);
/**
* @brief Perform flow upsampling using bilinear interpolation.
* Make sure invalid flow value is not propagated into the interpolate function.
*/
static Status upsampleFlow22(GPU::Buffer<float2> dst, GPU::Buffer<const float2> src, std::size_t dstWidth,
std::size_t dstHeight, bool wrap, unsigned blockSize, GPU::Stream stream);
/**
* @brief This function is used for debugging purpose in the Visualizer
*/
static Status interCoordLookup(const int warpWidth, const int interOffsetX, const int interOffsetY,
const int interWidth, const int interHeight,
const GPU::Buffer<const uint32_t> inputBuffer, const int coordWidth,
const int coordHeight, const GPU::Buffer<const float2> coordBuffer,
GPU::Buffer<uint32_t> output, GPU::Stream gpuStream);
/**
* @brief Convert the flow buffer into a RGBA buffer for dumping
*/
static Status convertFlowToRGBA(const int2 size, const GPU::Buffer<const float2> src, const int2 maxFlowValue,
GPU::Buffer<uint32_t> dst, GPU::Stream stream);
/**
* @brief Given a RGBA "colorBuffer" and a "flowBuffer" of the same size
* if a pixel's alpha value is 0, set the correspondent flow value to INVALID_FLOW_VALUE
*/
static Status setAlphaToFlowBuffer(const int2 size, const GPU::Buffer<const uint32_t> colorBuffer,
GPU::Buffer<float2> flowBuffer, GPU::Stream gpuStream);
};
} // namespace Util
} // namespace VideoStitch