// Copyright (c) 2012-2017 VideoStitch SAS // Copyright (c) 2018 stitchEm #pragma once #include "gpu/buffer.hpp" #include "gpu/stream.hpp" #include "gpu/uniqueBuffer.hpp" #include "libvideostitch/status.hpp" #include "libvideostitch/ptv.hpp" #include "core/rect.hpp" #include "core1/textureTarget.hpp" namespace VideoStitch { namespace Core { class StereoRigDefinition; } namespace Util { class ImageProcessingGPU { public: /** * @brief Down sample an image by a certain "levelCount" using nearest ("isNearest" == true) or bilinear interpolation * ("isNearest" == false) */ template <typename T> static Status downSampleImages(const int levelCount, int& bufferWidth, int& bufferHeight, GPU::Buffer<T> buffer, GPU::Stream stream, const bool isNearest = false); /** * @brief Calculate sum of all elements ("output") and count the total of non-zero entries ("mask") */ static Status calculateSum(const int numElement, const GPU::Buffer<const float> buffer, const unsigned blockSize, GPU::Stream stream, float& output, float& mask); /** * @brief Convert RGB-gradient to normalizedLAB-gradient (3 bytes-1 byte). * Note that pixels with value Image::RGBA::pack(1, 2, 3, 0) represent black color with alpha = 0 */ static Status convertRGBandGradientToNormalizedLABandGradient(const int2 bufferSize, GPU::Buffer<uint32_t> colorBuffer, GPU::Stream stream); /** * @brief Convert RGB210 buffer to RGB-gradient (3 bytes-1 byte). * Note that in the final buffer, original pixels with alpha = 0 are set to value Image::RGBA::pack(1, 2, 3, 0) */ static Status convertRGB210ToRGBandGradient(const int2 bufferSize, const GPU::Buffer<const uint32_t> inputBuffer, GPU::Buffer<uint32_t> colorBuffer, GPU::Stream stream); /** * @brief Convert RGB210 buffer to RGBA buffer */ static Status convertRGB210ToRGBA(const int2 bufferSize, GPU::Buffer<uint32_t> buffer, GPU::Stream stream); /** * @brief normalizedLAB-gradient (3 bytes-1 byte) to RGBA. * Note that pixels with value Image::RGBA::pack(1, 2, 3, 0) represent black color with alpha = 0 */ static Status convertNormalizedLABandGradientToRGBA(const int2 bufferSize, GPU::Buffer<uint32_t> colorBuffer, GPU::Stream stream); /** * @brief Extract a buffer channel from a RGBA buffer, used for debugging purpose * Note: "inputBuffer" stored as Image::RGBA format */ static Status extractChannel(const int2 bufferSize, const GPU::Buffer<const uint32_t> inputBuffer, const int channelIndex, GPU::Buffer<unsigned char> outputBuffer, GPU::Stream stream); /** * Convert a RGB buffer into normalized LAB buffer * @param size The size of input buffer. * @param inputRGBBuffer Input RGB buffer. * @param outputNormalizedLABBuffer The output buffer in normalized LAB color space. * @param stream CUDA stream for the operation. */ static Status convertRGBToNormalizedLAB(const int2 size, const GPU::Buffer<const uint32_t> inputRGBBuffer, GPU::Buffer<uint32_t> outputNormalizedLABBuffer, GPU::Stream gpuStream); /** * Convert a RGB buffer into luminance * @param size The size of input buffer. * @param inputBuffer Input RGB buffer. * @param outputLuminanceBuffer The output luminance buffer. * @param stream CUDA stream for the operation. */ static Status findLuminance(const int2 size, const GPU::Buffer<const uint32_t> inputBuffer, GPU::Buffer<float> outputLuminanceBuffer, GPU::Stream gpuStream); /** * Find gradient of an RGB buffer * @param size The size of input buffer. * @param inputBuffer Input RGB buffer. * @param outputGradientBuffer The output gradient buffer. * @param stream CUDA stream for the operation. */ static Status findGradient(const int2 size, const GPU::Buffer<const uint32_t> inputBuffer, GPU::Buffer<float> outputGradientBuffer, GPU::Stream gpuStream); /** * Alpha-aware blending of two input buffers. * @param dstRect The bounding rect of the dst buffer. * @param weight0 Weight of the first buffer. * @param src0Rect The bounding rect of the first buffer. * @param src0 The first buffer. * @param weight1 Weight of the second buffer. * @param src1Rect The bounding rect of the second buffer. * @param src1 The second buffer. */ static Status buffer2DRGBACompactBlendOffsetOperator(const Core::Rect& dstRect, GPU::Buffer<uint32_t> dst, const float weight0, const Core::Rect& src0Rect, const GPU::Buffer<const uint32_t> src0, const float weight1, const Core::Rect& src1Rect, const GPU::Buffer<const uint32_t> src1, GPU::Stream gpuStream); /** * Convert a buffer into binary * @param size The size of input buffer. * @param inputMask Input buffer. * @param binarizedMask The output buffer, 1 if the input value is not 0. * @param stream CUDA stream for the operation. */ static Status binarizeMask(const int2 size, const GPU::Buffer<const uint32_t> inputMask, GPU::Buffer<uint32_t> binarizedMask, GPU::Stream gpuStream); /** * Find bounding box of on non-zero value in @maskBuffer. * @param width The width of input buffer. * @param height The height of input buffer. * @param maskBuffer Input buffer. * @param boundingRect The output bounding rect of @maskBuffer. * @param stream CUDA stream for the operation. */ static Status findBBox(Core::TextureTarget, const bool canWarp, const Core::StereoRigDefinition* rigDef, const int width, const int height, const GPU::Buffer<const uint32_t>& maskBuffer, Core::Rect& boundingRect, GPU::Stream gpuStream); /** * Down sample coordinate mapping buffer and its weight buffer. * @param inputWidth Width of buffer. * @param inputHeight Height of buffer. * @param levelCount The level of down sampling. * @param coordBuffer The input coordinate buffer. * @param weightBuffer The input weight buffer. * @param stream CUDA stream for the operation. */ static Status downSampleCoordImage(const int inputWidth, const int inputHeight, const int levelCount, GPU::UniqueBuffer<float2>& coordBuffer, GPU::UniqueBuffer<uint32_t>& weightBuffer, GPU::Stream stream); /** * Perform pixel-wise AND operator of two input buffers. * @param warpWidth Width of the canvas. * @param boundingRect0 The bounding rect of the first buffer. * @param buffer0 The first buffer. * @param boundingRect1 The bounding rect of the second buffer. * @param buffer1 The second buffer. * @param stream CUDA stream for the operation. */ static Status onBothBufferOperator(const int warpWidth, const Core::Rect boundingRect0, const GPU::Buffer<const uint32_t> buffer0, const Core::Rect boundingRect1, const GPU::Buffer<const uint32_t> buffer1, const Core::Rect boundingRectBuffer, GPU::Buffer<uint32_t> buffer, GPU::Stream stream); /** * Given two buffers, compute a tight bounding box of the overlapping area. * @param warpWidth Width of the canvas. * @param boundingRect0 The bounding rect of the first buffer. * @param buffer0 The first buffer. * @param boundingRect1 The bounding rect of the second buffer. * @param buffer1 The second buffer. * @param stream CUDA stream for the operation. */ static Status computeTightOverlappingRect(Core::TextureTarget, const int warpWidth, const Core::Rect& boundingRect0, const GPU::Buffer<const uint32_t>& buffer0, const Core::Rect& boundingRect1, const GPU::Buffer<const uint32_t>& buffer1, Core::Rect& overlappingRect, GPU::Stream stream); /** * @brief Set a buffer to a constant value */ template <typename T> static Status setConstantBuffer(const int2 size, GPU::Buffer<T> buffer, const T value, GPU::Stream gpuStream); /** * @brief Pack a buffer inside another buffer. */ template <typename T> static Status packBuffer(const int warpWidth, const T invalidValue, const Core::Rect inputRect, const GPU::Buffer<const T> inputBuffer, const Core::Rect outputRect, GPU::Buffer<T> outputBuffer, GPU::Stream gpuStream); /** * @brief Thresholding an input buffer, set value < thresholdValue to minBoundValue * and maxBoundValue otherwise */ template <typename T> static Status thresholdingBuffer(const int2 size, const T thresholdValue, const T minBoundValue, const T maxBoundValue, GPU::Buffer<T> inputBuffer, GPU::Stream gpuStream); private: /** * @brief Down sample an image by 1 level using nearest ("isNearest" == true) or bilinear interpolation ("isNearest" * == false) */ template <typename T> static Status subsampleImage(GPU::Buffer<T> dst, GPU::Buffer<const T> src, std::size_t srcWidth, std::size_t srcHeight, GPU::Stream gpuStream, const bool isNearest = false); }; } // namespace Util } // namespace VideoStitch