// Copyright (c) 2012-2017 VideoStitch SAS // Copyright (c) 2018 stitchEm #include "./imageFlow.hpp" #include "./mergerPair.hpp" #include "./noFlow.hpp" #ifndef VS_OPENCL #include "./simpleFlow.hpp" #endif #include "gpu/buffer.hpp" #include "gpu/stream.hpp" #include "gpu/memcpy.hpp" #ifndef NDEBUG #include "util/debugUtils.hpp" #include #endif namespace VideoStitch { namespace Core { Potential ImageFlow::factor(const ImageFlowAlgorithm e, std::shared_ptr& mergerPair, const std::map& parameters) { std::unique_ptr flowPtr; switch (e) { #ifndef VS_OPENCL case ImageFlowAlgorithm::SimpleFlow: flowPtr.reset(new SimpleFlow(parameters)); break; #endif case ImageFlowAlgorithm::NoFlow: flowPtr.reset(new NoFlow(parameters)); break; default: flowPtr.reset(new NoFlow(parameters)); break; } FAIL_RETURN(flowPtr->init(mergerPair)); return Potential(flowPtr.release()); } ImageFlow::ImageFlow(const std::map& parameters) : parameters(parameters) {} ImageFlow::~ImageFlow() {} Status ImageFlow::findExtrapolatedImageFlow(const int2&, const int2&, const GPU::Buffer&, const GPU::Buffer&, const int2&, const int2&, const GPU::Buffer&, const int2&, const int2&, GPU::Buffer, GPU::Stream) { return Status::OK(); } Rect ImageFlow::getFlowRect(const int level) const { return mergerPair->getBoundingInterRect(0, level); } int2 ImageFlow::getLookupOffset(const int level) const { return make_int2((int)mergerPair->getBoundingInterRect(1, level).left(), (int)mergerPair->getBoundingInterRect(1, level).top()); } Status ImageFlow::init(std::shared_ptr& inMergerPair) { this->mergerPair = inMergerPair; int firstLevelWidth = (int)mergerPair->getInterToInputSpaceCoordMappingLaplacianPyramid(0)->getLevel(0).width(); int firstLevelHeight = (int)mergerPair->getInterToInputSpaceCoordMappingLaplacianPyramid(0)->getLevel(0).height(); int numLevels = (int)mergerPair->getInterToInputSpaceCoordMappingLaplacianPyramid(0)->numLevels(); auto potflowLaplacianPyramid = LaplacianPyramid::create( std::string("flow"), firstLevelWidth, firstLevelHeight, numLevels, LaplacianPyramid::InternalFirstLevel, LaplacianPyramid::SingleShot, 2, 1, false); FAIL_RETURN(potflowLaplacianPyramid.status()); flowLaplacianPyramid.reset(potflowLaplacianPyramid.release()); const Rect interRect1 = mergerPair->getBoundingInterRect(1, 0); auto potExtraFlowLaplacianPyramid = LaplacianPyramid::create( std::string("extraFlow"), interRect1.getWidth(), interRect1.getHeight(), numLevels, LaplacianPyramid::InternalFirstLevel, LaplacianPyramid::SingleShot, 2, 1, false); FAIL_RETURN(potExtraFlowLaplacianPyramid.status()); extrapolatedFlowLaplacianPyramid.reset(potExtraFlowLaplacianPyramid.release()); extrapolatedImage1.alloc(interRect1.getArea(), "Optical Flow Pair"); // Set the extrapolated flow rect equals to the intermediate rect 1. // Smaller size can be considered for better performance but I strongly recommend "no" extrapolatedFlowRects = mergerPair->getBoundingInterRect1s(); FAIL_RETURN(allocMemory()); return Status::OK(); } Status ImageFlow::allocMemory() { const int maxSize0 = (int)(mergerPair->getInterToInputSpaceCoordMappingLaplacianPyramid(0)->getLevel(0).width() * mergerPair->getInterToInputSpaceCoordMappingLaplacianPyramid(0)->getLevel(0).height()); const int maxSize1 = (int)(mergerPair->getInterToInputSpaceCoordMappingLaplacianPyramid(1)->getLevel(0).width() * mergerPair->getInterToInputSpaceCoordMappingLaplacianPyramid(1)->getLevel(0).height()); FAIL_RETURN(image0.alloc(maxSize0, "Optical Flow Pair")); FAIL_RETURN(image1.alloc(maxSize1, "Optical Flow Pair")); FAIL_RETURN(finalFlow.alloc(maxSize0, "Optical Flow Pair")); return Status::OK(); } Status ImageFlow::findMultiScaleImageFlow(const frameid_t, const int, const int2&, const GPU::Buffer&, const int2&, const GPU::Buffer&, GPU::Stream) { return Status::OK(); } Status ImageFlow::cacheFlowSequence(const frameid_t, const int, const int2&, const GPU::Buffer&, const int2&, const GPU::Buffer&, GPU::Stream) const { return {Origin::ImageFlow, ErrType::ImplementationError, "Implementation Error"}; } Status ImageFlow::findMultiScaleImageFlow(const frameid_t, const int, const int2&, const GPU::Buffer&, const int2&, const GPU::Buffer&, GPU::Buffer, GPU::Stream) { return Status::OK(); } Status ImageFlow::findTemporalCoherentFlow(const frameid_t, const int2&, GPU::Buffer, GPU::Stream) { return Status::OK(); } const MergerPair* ImageFlow::getMergerPair() const { return mergerPair.get(); } const GPU::Buffer ImageFlow::getFinalFlowBuffer() const { return finalFlow.borrow_const(); } const GPU::Buffer ImageFlow::getFinalExtrapolatedFlowBuffer() const { return extrapolatedFlowLaplacianPyramid->getLevel(0).data(); } Rect ImageFlow::getExtrapolatedFlowRect(const int level) const { return extrapolatedFlowRects[level]; } #ifndef NDEBUG Status ImageFlow::dumpDebugImages(const int, const int, const GPU::Buffer&, const int, const int, const GPU::Buffer&, GPU::Stream) const { return Status::OK(); } #endif } // namespace Core } // namespace VideoStitch