// Copyright (c) 2012-2017 VideoStitch SAS // Copyright (c) 2018 stitchEm #include "../surface.hpp" #include "../context.hpp" #include "../kernel.hpp" namespace { #include "cubemapMapKernel.xxd" INDIRECT_REGISTER_OPENCL_PROGRAM(cubemapMapKernel, false); #include "undistortKernel.xxd" INDIRECT_REGISTER_OPENCL_PROGRAM(undistortKernel, false); #include "warpCoordKernel.xxd" INDIRECT_REGISTER_OPENCL_PROGRAM(warpCoordKernel, false); #include "warpCoordInputKernel.xxd" INDIRECT_REGISTER_OPENCL_PROGRAM(warpCoordInputKernel, false); #include "warpFaceKernel_x.xxd" INDIRECT_REGISTER_OPENCL_PROGRAM(warpFaceKernel_x, false); #include "warpFaceKernel_y.xxd" INDIRECT_REGISTER_OPENCL_PROGRAM(warpFaceKernel_y, false); #include "warpFaceKernel_z.xxd" INDIRECT_REGISTER_OPENCL_PROGRAM(warpFaceKernel_z, false); #include "warpLookupKernel.xxd" INDIRECT_REGISTER_OPENCL_PROGRAM(warpLookupKernel, false); #include "warpKernel.xxd" INDIRECT_REGISTER_OPENCL_PROGRAM(warpKernel, true); #include "zoneKernel.xxd" INDIRECT_REGISTER_OPENCL_PROGRAM(zoneKernel, true); } // namespace #define STRING(str) QUOTE(str) #define QUOTE(str) #str #ifdef CL_ARGS_WORKAROUND #define GET_DISTORTION(params) (*(cl_float16*)¶ms.getDistortion()) #else #define GET_DISTORTION(params) (params.getDistortion()) #endif namespace VideoStitch { namespace Core { namespace { #define MAPBUFFER_PANO3(MERGER, INPUTPROJECTION, DISTORTIONMETERS, DISTORTIONPIXELS, ISWITHIN, PHOTORESPONSE) \ Status \ mapBuffer_##MERGER##_##INPUTPROJECTION##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##ISWITHIN##_##PHOTORESPONSE( \ int time, GPU::Buffer<uint32_t> devOut, GPU::Surface& panoSurf, const unsigned char* mask, \ const Rect& outputBounds, const PanoDefinition& pano, const InputDefinition& im, GPU::Surface& surface, \ GPU::Stream gpuStream) const { \ GeometryDefinition geometry = im.getGeometries().at(time); \ TransformGeoParams params(im, geometry, pano); \ const float3 colorMult = \ PhotoTransform::ColorCorrectionParams(im.getExposureValue().at(time), im.getRedCB().at(time), \ im.getGreenCB().at(time), im.getBlueCB().at(time)) \ .computeColorMultiplier(pano.getExposureValue().at(time), pano.getRedCB().at(time), \ pano.getGreenCB().at(time), pano.getBlueCB().at(time)); \ const cl_float3 colorMultPadded{{colorMult.x, colorMult.y, colorMult.z}}; \ const unsigned height = ((mergeformat == ImageMerger::Format::Gradient) && \ (outputBounds.getHeight() > (pano.getHeight() - outputBounds.top()))) \ ? (unsigned)(pano.getHeight() - outputBounds.top()) \ : (unsigned)outputBounds.getHeight(); \ \ float2 center, iscale, pscale; \ center.x = (float)im.getCenterX(geometry); \ center.y = (float)im.getCenterY(geometry); \ iscale.x = (float)geometry.getHorizontalFocal(); \ iscale.y = (float)geometry.getVerticalFocal(); \ pscale.x = TransformGeoParams::computePanoScale(PanoProjection::Equirectangular, pano.getWidth(), 360.f); \ pscale.y = 2 * TransformGeoParams::computePanoScale(PanoProjection::Equirectangular, pano.getHeight(), 360.f); \ auto kernel2D = \ GPU::Kernel::get( \ PROGRAM(warpKernel), \ "warpKernel_" QUOTE( \ MERGER##_##INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##PHOTORESPONSE)) \ .setup2D(gpuStream, (unsigned)outputBounds.getWidth(), (unsigned)outputBounds.getHeight()); \ return kernel2D.enqueueWithKernelArgs( \ devOut.get(), panoSurf.get(), mask, surface.get(), (unsigned)im.getWidth(), (unsigned)im.getHeight(), \ (unsigned)outputBounds.getWidth(), height, (unsigned)outputBounds.left(), (unsigned)outputBounds.top(), \ (unsigned)pano.getWidth(), (unsigned)pano.getHeight(), (unsigned)im.getCropLeft(), \ (unsigned)im.getCropRight(), (unsigned)im.getCropTop(), (unsigned)im.getCropBottom(), pscale, \ params.getPose(), iscale, GET_DISTORTION(params), center, colorMultPadded, \ photo->getDevicePhotoParam().floatParam, photo->getDevicePhotoParam().transformData, \ (float)im.getVignettingCenterX(), (float)im.getVignettingCenterY(), \ (float)TransformGeoParams::getInverseDemiDiagonalSquared(im), (float)im.getVignettingCoeff0(), \ (float)im.getVignettingCoeff1(), (float)im.getVignettingCoeff2(), (float)im.getVignettingCoeff3()); \ } #define WARP_CUBEMAP3(INPUTPROJECTION, DISTORTIONMETERS, DISTORTIONPIXELS, ISWITHIN, PHOTORESPONSE, EQUIANGULAR) \ Status \ warpCubemap_##INPUTPROJECTION##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##ISWITHIN##_##PHOTORESPONSE##_##EQUIANGULAR( \ int time, GPU::Buffer<uint32_t> xPos, const Rect& xPosBB, GPU::Buffer<uint32_t> xNeg, const Rect& xNegBB, \ GPU::Buffer<uint32_t> yPos, const Rect& yPosBB, GPU::Buffer<uint32_t> yNeg, const Rect& yNegBB, \ GPU::Buffer<uint32_t> zPos, const Rect& zPosBB, GPU::Buffer<uint32_t> zNeg, const Rect& zNegBB, \ const PanoDefinition& pano, const InputDefinition& im, GPU::Surface& surface, GPU::Stream gpuStream) const { \ GeometryDefinition geometry = im.getGeometries().at(time); \ TransformGeoParams params(im, geometry, pano); \ const float3 colorMult = \ PhotoTransform::ColorCorrectionParams(im.getExposureValue().at(time), im.getRedCB().at(time), \ im.getGreenCB().at(time), im.getBlueCB().at(time)) \ .computeColorMultiplier(pano.getExposureValue().at(time), pano.getRedCB().at(time), \ pano.getGreenCB().at(time), pano.getBlueCB().at(time)); \ const cl_float3 colorMultPadded{{colorMult.x, colorMult.y, colorMult.z}}; \ \ float2 center, iscale; \ center.x = (float)im.getCenterX(geometry); \ center.y = (float)im.getCenterY(geometry); \ iscale.x = (float)geometry.getHorizontalFocal(); \ iscale.y = (float)geometry.getVerticalFocal(); \ \ if (!xPosBB.empty()) { \ auto kernel2D = \ GPU::Kernel::get( \ PROGRAM(warpFaceKernel_x), \ "warpKernel_XPos_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##PHOTORESPONSE##_##EQUIANGULAR)) \ .setup2D(gpuStream, (unsigned)pano.getLength(), (unsigned)pano.getLength()); \ return kernel2D.enqueueWithKernelArgs( \ xPos.get(), surface.get(), (unsigned)im.getWidth(), (unsigned)im.getHeight(), (unsigned)xPosBB.getWidth(), \ (unsigned)xPosBB.getHeight(), (unsigned)xPosBB.left(), (unsigned)xPosBB.top(), (unsigned)pano.getLength(), \ (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), (unsigned)im.getCropTop(), \ (unsigned)im.getCropBottom(), params.getPose(), iscale, GET_DISTORTION(params), center, colorMultPadded, \ photo->getDevicePhotoParam().floatParam, photo->getDevicePhotoParam().transformData, \ (float)im.getVignettingCenterX(), (float)im.getVignettingCenterY(), \ (float)TransformGeoParams::getInverseDemiDiagonalSquared(im), (float)im.getVignettingCoeff0(), \ (float)im.getVignettingCoeff1(), (float)im.getVignettingCoeff2(), (float)im.getVignettingCoeff3()); \ } \ if (!xNegBB.empty()) { \ auto kernel2D = \ GPU::Kernel::get( \ PROGRAM(warpFaceKernel_x), \ "warpKernel_XNeg_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##PHOTORESPONSE##_##EQUIANGULAR)) \ .setup2D(gpuStream, (unsigned)pano.getLength(), (unsigned)pano.getLength()); \ return kernel2D.enqueueWithKernelArgs( \ xNeg.get(), surface.get(), (unsigned)im.getWidth(), (unsigned)im.getHeight(), (unsigned)xNegBB.getWidth(), \ (unsigned)xNegBB.getHeight(), (unsigned)xNegBB.left(), (unsigned)xNegBB.top(), (unsigned)pano.getLength(), \ (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), (unsigned)im.getCropTop(), \ (unsigned)im.getCropBottom(), params.getPose(), iscale, GET_DISTORTION(params), center, colorMultPadded, \ photo->getDevicePhotoParam().floatParam, photo->getDevicePhotoParam().transformData, \ (float)im.getVignettingCenterX(), (float)im.getVignettingCenterY(), \ (float)TransformGeoParams::getInverseDemiDiagonalSquared(im), (float)im.getVignettingCoeff0(), \ (float)im.getVignettingCoeff1(), (float)im.getVignettingCoeff2(), (float)im.getVignettingCoeff3()); \ } \ if (!yPosBB.empty()) { \ auto kernel2D = \ GPU::Kernel::get( \ PROGRAM(warpFaceKernel_y), \ "warpKernel_YPos_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##PHOTORESPONSE##_##EQUIANGULAR)) \ .setup2D(gpuStream, (unsigned)pano.getLength(), (unsigned)pano.getLength()); \ return kernel2D.enqueueWithKernelArgs( \ yPos.get(), surface.get(), (unsigned)im.getWidth(), (unsigned)im.getHeight(), (unsigned)yPosBB.getWidth(), \ (unsigned)yPosBB.getHeight(), (unsigned)yPosBB.left(), (unsigned)yPosBB.top(), (unsigned)pano.getLength(), \ (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), (unsigned)im.getCropTop(), \ (unsigned)im.getCropBottom(), params.getPose(), iscale, GET_DISTORTION(params), center, colorMultPadded, \ photo->getDevicePhotoParam().floatParam, photo->getDevicePhotoParam().transformData, \ (float)im.getVignettingCenterX(), (float)im.getVignettingCenterY(), \ (float)TransformGeoParams::getInverseDemiDiagonalSquared(im), (float)im.getVignettingCoeff0(), \ (float)im.getVignettingCoeff1(), (float)im.getVignettingCoeff2(), (float)im.getVignettingCoeff3()); \ } \ if (!yNegBB.empty()) { \ auto kernel2D = \ GPU::Kernel::get( \ PROGRAM(warpFaceKernel_y), \ "warpKernel_YNeg_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##PHOTORESPONSE##_##EQUIANGULAR)) \ .setup2D(gpuStream, (unsigned)pano.getLength(), (unsigned)pano.getLength()); \ return kernel2D.enqueueWithKernelArgs( \ yNeg.get(), surface.get(), (unsigned)im.getWidth(), (unsigned)im.getHeight(), (unsigned)yNegBB.getWidth(), \ (unsigned)yNegBB.getHeight(), (unsigned)yNegBB.left(), (unsigned)yNegBB.top(), (unsigned)pano.getLength(), \ (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), (unsigned)im.getCropTop(), \ (unsigned)im.getCropBottom(), params.getPose(), iscale, GET_DISTORTION(params), center, colorMultPadded, \ photo->getDevicePhotoParam().floatParam, photo->getDevicePhotoParam().transformData, \ (float)im.getVignettingCenterX(), (float)im.getVignettingCenterY(), \ (float)TransformGeoParams::getInverseDemiDiagonalSquared(im), (float)im.getVignettingCoeff0(), \ (float)im.getVignettingCoeff1(), (float)im.getVignettingCoeff2(), (float)im.getVignettingCoeff3()); \ } \ if (!zPosBB.empty()) { \ auto kernel2D = \ GPU::Kernel::get( \ PROGRAM(warpFaceKernel_z), \ "warpKernel_ZPos_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##PHOTORESPONSE##_##EQUIANGULAR)) \ .setup2D(gpuStream, (unsigned)pano.getLength(), (unsigned)pano.getLength()); \ return kernel2D.enqueueWithKernelArgs( \ zPos.get(), surface.get(), (unsigned)im.getWidth(), (unsigned)im.getHeight(), (unsigned)zPosBB.getWidth(), \ (unsigned)zPosBB.getHeight(), (unsigned)zPosBB.left(), (unsigned)zPosBB.top(), (unsigned)pano.getLength(), \ (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), (unsigned)im.getCropTop(), \ (unsigned)im.getCropBottom(), params.getPose(), iscale, GET_DISTORTION(params), center, colorMultPadded, \ photo->getDevicePhotoParam().floatParam, photo->getDevicePhotoParam().transformData, \ (float)im.getVignettingCenterX(), (float)im.getVignettingCenterY(), \ (float)TransformGeoParams::getInverseDemiDiagonalSquared(im), (float)im.getVignettingCoeff0(), \ (float)im.getVignettingCoeff1(), (float)im.getVignettingCoeff2(), (float)im.getVignettingCoeff3()); \ } \ if (!zNegBB.empty()) { \ auto kernel2D = \ GPU::Kernel::get( \ PROGRAM(warpFaceKernel_z), \ "warpKernel_ZNeg_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##PHOTORESPONSE##_##EQUIANGULAR)) \ .setup2D(gpuStream, (unsigned)pano.getLength(), (unsigned)pano.getLength()); \ return kernel2D.enqueueWithKernelArgs( \ zNeg.get(), surface.get(), (unsigned)im.getWidth(), (unsigned)im.getHeight(), (unsigned)zNegBB.getWidth(), \ (unsigned)zNegBB.getHeight(), (unsigned)zNegBB.left(), (unsigned)zNegBB.top(), (unsigned)pano.getLength(), \ (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), (unsigned)im.getCropTop(), \ (unsigned)im.getCropBottom(), params.getPose(), iscale, GET_DISTORTION(params), center, colorMultPadded, \ photo->getDevicePhotoParam().floatParam, photo->getDevicePhotoParam().transformData, \ (float)im.getVignettingCenterX(), (float)im.getVignettingCenterY(), \ (float)TransformGeoParams::getInverseDemiDiagonalSquared(im), (float)im.getVignettingCoeff0(), \ (float)im.getVignettingCoeff1(), (float)im.getVignettingCoeff2(), (float)im.getVignettingCoeff3()); \ } \ \ return Status::OK(); \ } #define MAPBUFFERLOOKUP_PANO3(MERGER, ISWITHIN, PHOTORESPONSE) \ Status mapBufferLookup_##MERGER##_##ISWITHIN##_##PHOTORESPONSE( \ int time, GPU::Buffer<uint32_t> devOut, GPU::Surface& panoSurf, const unsigned char* mask, \ const GPU::Surface& coordIn, const float coordShrinkFactor, const Rect& outputBounds, \ const PanoDefinition& pano, const InputDefinition& im, GPU::Surface& surface, GPU::Stream gpuStream) const { \ GeometryDefinition geometry = im.getGeometries().at(time); \ TransformGeoParams params(im, geometry, pano); \ const float3 colorMult = \ PhotoTransform::ColorCorrectionParams(im.getExposureValue().at(time), im.getRedCB().at(time), \ im.getGreenCB().at(time), im.getBlueCB().at(time)) \ .computeColorMultiplier(pano.getExposureValue().at(time), pano.getRedCB().at(time), \ pano.getGreenCB().at(time), pano.getBlueCB().at(time)); \ const cl_float3 colorMultPadded{{colorMult.x, colorMult.y, colorMult.z}}; \ const unsigned height = ((mergeformat == ImageMerger::Format::Gradient) && \ (outputBounds.getHeight() > (pano.getHeight() - outputBounds.top()))) \ ? (unsigned)(pano.getHeight() - outputBounds.top()) \ : (unsigned)outputBounds.getHeight(); \ \ auto kernel2D = \ GPU::Kernel::get(PROGRAM(warpLookupKernel), "warpLookupKernel_" QUOTE(MERGER##_##ISWITHIN##_##PHOTORESPONSE)) \ .setup2D(gpuStream, (unsigned)outputBounds.getWidth(), (unsigned)outputBounds.getHeight()); \ return kernel2D.enqueueWithKernelArgs( \ devOut.get(), panoSurf.get(), mask, coordIn.get(), coordShrinkFactor, surface.get(), (unsigned)im.getWidth(), \ (unsigned)im.getHeight(), (unsigned)outputBounds.getWidth(), height, (unsigned)outputBounds.left(), \ (unsigned)outputBounds.top(), (unsigned)pano.getWidth(), (unsigned)pano.getHeight(), \ (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), (unsigned)im.getCropTop(), \ (unsigned)im.getCropBottom(), colorMultPadded, photo->getDevicePhotoParam().floatParam, \ photo->getDevicePhotoParam().transformData, (float)im.getVignettingCenterX(), \ (float)im.getVignettingCenterY(), (float)TransformGeoParams::getInverseDemiDiagonalSquared(im), \ (float)im.getVignettingCoeff0(), (float)im.getVignettingCoeff1(), (float)im.getVignettingCoeff2(), \ (float)im.getVignettingCoeff3()); \ } #define MAPBUFFERCOORD_PANO3(INPUTPROJECTION, DISTORTIONMETERS, DISTORTIONPIXELS, ISWITHIN) \ Status mapBufferCoord_##INPUTPROJECTION##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##ISWITHIN( \ int time, GPU::Surface& devOut, const Rect& outputBounds, const PanoDefinition& pano, const InputDefinition& im, \ GPU::Stream gpuStream) const { \ GeometryDefinition geometry = im.getGeometries().at(time); \ TransformGeoParams params(im, geometry, pano); \ \ float2 center, iscale, pscale; \ unsigned panoWidth = (unsigned)(pano.getWidth() / pano.getPrecomputedCoordinateShrinkFactor()); \ unsigned panoHeight = (unsigned)(pano.getHeight() / pano.getPrecomputedCoordinateShrinkFactor()); \ center.x = (float)im.getCenterX(geometry); \ center.y = (float)im.getCenterY(geometry); \ iscale.x = (float)geometry.getHorizontalFocal(); \ iscale.y = (float)geometry.getVerticalFocal(); \ pscale.x = TransformGeoParams::computePanoScale(PanoProjection::Equirectangular, panoWidth, 360.f); \ pscale.y = 2 * TransformGeoParams::computePanoScale(PanoProjection::Equirectangular, panoHeight, 360.f); \ \ auto kernel2D = \ GPU::Kernel::get( \ PROGRAM(warpCoordKernel), \ "warpCoordKernel_" QUOTE(INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS)) \ .setup2D(gpuStream, (unsigned)outputBounds.getWidth(), (unsigned)outputBounds.getHeight()); \ return kernel2D.enqueueWithKernelArgs( \ devOut.get(), (unsigned)im.getWidth(), (unsigned)im.getHeight(), (unsigned)im.getCropLeft(), \ (unsigned)im.getCropRight(), (unsigned)im.getCropTop(), (unsigned)im.getCropBottom(), \ (unsigned)outputBounds.getWidth(), (unsigned)outputBounds.getHeight(), (unsigned)outputBounds.left(), \ (unsigned)outputBounds.top(), panoWidth, panoHeight, (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), \ (unsigned)im.getCropTop(), (unsigned)im.getCropBottom(), pscale, params.getPose(), iscale, \ GET_DISTORTION(params), center); \ } #define MAPCOORDINPUT_PANO3(INPUTPROJECTION, INVERSEDISTORTIONMETERS, INVERSEDISTORTIONPIXELS, ISWITHIN) \ Status mapCoordInput_##INPUTPROJECTION##_##INVERSEDISTORTIONMETERS##_##INVERSEDISTORTIONPIXELS##_##ISWITHIN( \ int time, const int scaleFactor, GPU::Buffer<float2> inputCoord, const PanoDefinition& pano, \ const InputDefinition& im, GPU::Stream gpuStream) const { \ GeometryDefinition geometry = im.getGeometries().at(time); \ TransformGeoParams params(im, geometry, pano); \ \ float2 center, iscale, pscale; \ center.x = (float)im.getCenterX(geometry); \ center.y = (float)im.getCenterY(geometry); \ iscale.x = (float)geometry.getHorizontalFocal(); \ iscale.y = (float)geometry.getVerticalFocal(); \ pscale.x = TransformGeoParams::computePanoScale(PanoProjection::Equirectangular, pano.getWidth(), 360.f); \ pscale.y = 2 * TransformGeoParams::computePanoScale(PanoProjection::Equirectangular, pano.getHeight(), 360.f); \ \ auto kernel2D = \ GPU::Kernel::get(PROGRAM(warpCoordInputKernel), \ "warpCoordInputKernel_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##INVERSEDISTORTIONMETERS##_##INVERSEDISTORTIONPIXELS)) \ .setup2D(gpuStream, (unsigned)im.getWidth(), (unsigned)im.getHeight()); \ return kernel2D.enqueueWithKernelArgs( \ inputCoord.get(), scaleFactor, (unsigned)im.getWidth(), (unsigned)im.getHeight(), (unsigned)im.getCropLeft(), \ (unsigned)im.getCropRight(), (unsigned)im.getCropTop(), (unsigned)im.getCropBottom(), \ (unsigned)pano.getWidth(), (unsigned)pano.getHeight(), pscale, params.getPoseInverse(), \ (float)pano.getSphereScale(), iscale, GET_DISTORTION(params), center); \ } #define COMPUTEZONE_PANO3(INPUTPROJECTION, DISTORTIONMETERS, DISTORTIONPIXELS, ISWITHIN) \ Status computeZone_##INPUTPROJECTION##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##ISWITHIN( \ GPU::Buffer<uint32_t> devOut, const PanoDefinition& pano, const InputDefinition& im, unsigned imId, \ GPU::Buffer<const unsigned char> maskDevBuffer, GPU::Stream stream) const { \ GeometryDefinition geometry = im.getGeometries().at(0); \ TransformGeoParams params(im, geometry, pano); \ float2 center, iscale, pscale; \ center.x = (float)im.getCenterX(geometry); \ center.y = (float)im.getCenterY(geometry); \ iscale.x = (float)geometry.getHorizontalFocal(); \ iscale.y = (float)geometry.getVerticalFocal(); \ pscale.x = TransformGeoParams::computePanoScale(PanoProjection::Equirectangular, pano.getWidth(), 360.f); \ pscale.y = 2 * TransformGeoParams::computePanoScale(PanoProjection::Equirectangular, pano.getHeight(), 360.f); \ \ std::string kernelName = \ "zoneKernel_" QUOTE(INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS); \ auto kernel2D = GPU::Kernel::get(PROGRAM(zoneKernel), kernelName) \ .setup2D(stream, (unsigned)pano.getWidth(), (unsigned)pano.getHeight()); \ \ return kernel2D.enqueueWithKernelArgs( \ devOut.get(), maskDevBuffer.get(), ((uint32_t)1 << imId), (unsigned)im.getWidth(), (unsigned)im.getHeight(), \ (unsigned)pano.getWidth(), (unsigned)pano.getHeight(), (unsigned)im.getCropLeft(), \ (unsigned)im.getCropRight(), (unsigned)im.getCropTop(), (unsigned)im.getCropBottom(), pscale, \ params.getPose(), iscale, GET_DISTORTION(params), center); \ } #define CUBEMAPMAP_PANO4(INPUTPROJECTION, DISTORTIONMETERS, DISTORTIONPIXELS, ISWITHIN, EQUIANGULAR) \ Status cubemapMap_##INPUTPROJECTION##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##ISWITHIN##_##EQUIANGULAR( \ GPU::Buffer<uint32_t> xPos, GPU::Buffer<uint32_t> xNeg, GPU::Buffer<uint32_t> yPos, GPU::Buffer<uint32_t> yNeg, \ GPU::Buffer<uint32_t> zPos, GPU::Buffer<uint32_t> zNeg, const PanoDefinition& pano, const InputDefinition& im, \ videoreaderid_t imId, GPU::Buffer<const unsigned char> maskDevBuffer, GPU::Stream gpuStream) const { \ GeometryDefinition geometry = im.getGeometries().at(0); \ TransformGeoParams params(im, geometry, pano); \ \ float2 center, iscale; \ center.x = (float)im.getCenterX(geometry); \ center.y = (float)im.getCenterY(geometry); \ iscale.x = (float)geometry.getHorizontalFocal(); \ iscale.y = (float)geometry.getVerticalFocal(); \ \ auto kernXPos = \ GPU::Kernel::get(PROGRAM(cubemapMapKernel), \ "cubemapMapKernel_XPos_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##EQUIANGULAR)) \ .setup2D(gpuStream, (unsigned)pano.getLength(), (unsigned)pano.getLength()); \ FAIL_RETURN(kernXPos.enqueueWithKernelArgs( \ xPos.get(), maskDevBuffer.get(), ((uint32_t)1 << imId), (unsigned)im.getWidth(), (unsigned)im.getHeight(), \ (unsigned)pano.getLength(), (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), \ (unsigned)im.getCropTop(), (unsigned)im.getCropBottom(), params.getPose(), iscale, GET_DISTORTION(params), \ center)); \ auto kernXNeg = \ GPU::Kernel::get(PROGRAM(cubemapMapKernel), \ "cubemapMapKernel_XNeg_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##EQUIANGULAR)) \ .setup2D(gpuStream, (unsigned)pano.getLength(), (unsigned)pano.getLength()); \ FAIL_RETURN(kernXNeg.enqueueWithKernelArgs( \ xNeg.get(), maskDevBuffer.get(), ((uint32_t)1 << imId), (unsigned)im.getWidth(), (unsigned)im.getHeight(), \ (unsigned)pano.getLength(), (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), \ (unsigned)im.getCropTop(), (unsigned)im.getCropBottom(), params.getPose(), iscale, GET_DISTORTION(params), \ center)); \ auto kernYPos = \ GPU::Kernel::get(PROGRAM(cubemapMapKernel), \ "cubemapMapKernel_YPos_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##EQUIANGULAR)) \ .setup2D(gpuStream, (unsigned)pano.getLength(), (unsigned)pano.getLength()); \ FAIL_RETURN(kernYPos.enqueueWithKernelArgs( \ yPos.get(), maskDevBuffer.get(), ((uint32_t)1 << imId), (unsigned)im.getWidth(), (unsigned)im.getHeight(), \ (unsigned)pano.getLength(), (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), \ (unsigned)im.getCropTop(), (unsigned)im.getCropBottom(), params.getPose(), iscale, GET_DISTORTION(params), \ center)); \ auto kernYNeg = \ GPU::Kernel::get(PROGRAM(cubemapMapKernel), \ "cubemapMapKernel_YNeg_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##EQUIANGULAR)) \ .setup2D(gpuStream, (unsigned)pano.getLength(), (unsigned)pano.getLength()); \ FAIL_RETURN(kernYNeg.enqueueWithKernelArgs( \ yNeg.get(), maskDevBuffer.get(), ((uint32_t)1 << imId), (unsigned)im.getWidth(), (unsigned)im.getHeight(), \ (unsigned)pano.getLength(), (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), \ (unsigned)im.getCropTop(), (unsigned)im.getCropBottom(), params.getPose(), iscale, GET_DISTORTION(params), \ center)); \ auto kernZPos = \ GPU::Kernel::get(PROGRAM(cubemapMapKernel), \ "cubemapMapKernel_ZPos_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##EQUIANGULAR)) \ .setup2D(gpuStream, (unsigned)pano.getLength(), (unsigned)pano.getLength()); \ FAIL_RETURN(kernZPos.enqueueWithKernelArgs( \ zPos.get(), maskDevBuffer.get(), ((uint32_t)1 << imId), (unsigned)im.getWidth(), (unsigned)im.getHeight(), \ (unsigned)pano.getLength(), (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), \ (unsigned)im.getCropTop(), (unsigned)im.getCropBottom(), params.getPose(), iscale, GET_DISTORTION(params), \ center)); \ auto kernZNeg = \ GPU::Kernel::get(PROGRAM(cubemapMapKernel), \ "cubemapMapKernel_ZNeg_" QUOTE( \ INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##EQUIANGULAR)) \ .setup2D(gpuStream, (unsigned)pano.getLength(), (unsigned)pano.getLength()); \ FAIL_RETURN(kernZNeg.enqueueWithKernelArgs( \ zNeg.get(), maskDevBuffer.get(), ((uint32_t)1 << imId), (unsigned)im.getWidth(), (unsigned)im.getHeight(), \ (unsigned)pano.getLength(), (unsigned)im.getCropLeft(), (unsigned)im.getCropRight(), \ (unsigned)im.getCropTop(), (unsigned)im.getCropBottom(), params.getPose(), iscale, GET_DISTORTION(params), \ center)); \ \ return Status::OK(); \ } #define MAPDISTORTION_PANO3(INPUTPROJECTION, DISTORTIONMETERS, DISTORTIONPIXELS, ISWITHIN) \ Status mapDistortion_##INPUTPROJECTION##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##ISWITHIN( \ int time, GPU::Buffer<unsigned char> devOut, const Rect& outputBounds, const PanoDefinition& pano, \ const InputDefinition& im, GPU::Stream stream) const { \ GeometryDefinition geometry = im.getGeometries().at(time); \ TransformGeoParams params(im, geometry, pano); \ /*NOTE: here we assume that height and width are multiples of dimBlock.x and dimblock.y*/ \ float2 center, iscale, pscale; \ center.x = (float)im.getCenterX(geometry); \ center.y = (float)im.getCenterY(geometry); \ iscale.x = (float)geometry.getHorizontalFocal(); \ iscale.y = (float)geometry.getVerticalFocal(); \ pscale.x = TransformGeoParams::computePanoScale(PanoProjection::Equirectangular, pano.getWidth(), 360.f); \ pscale.y = 2 * TransformGeoParams::computePanoScale(PanoProjection::Equirectangular, pano.getHeight(), 360.f); \ \ std::string kernelName = \ "distortionKernel_" QUOTE(INPUTPROJECTION##_##ISWITHIN##_##DISTORTIONMETERS##_##DISTORTIONPIXELS); \ auto kernel2D = GPU::Kernel::get(PROGRAM(distortionKernel), kernelName) \ .setup2D(stream, (unsigned)pano.getWidth(), (unsigned)pano.getHeight()); \ return kernel2D.enqueueWithKernelArgs( \ devOut.get(), (unsigned)im.getWidth(), (unsigned)im.getHeight(), (unsigned)outputBounds.getWidth(), \ (unsigned)outputBounds.getHeight(), (unsigned)outputBounds.left(), (unsigned)outputBounds.top(), \ (unsigned)pano.getWidth(), (unsigned)pano.getHeight(), (unsigned)im.getCropLeft(), \ (unsigned)im.getCropRight(), (unsigned)im.getCropTop(), (unsigned)im.getCropBottom(), pscale, \ params.getPose(), iscale, GET_DISTORTION(params), center); \ } #define UNDISTORT_INPUT5(INPROJECTION, DISTORTIONMETERS, DISTORTIONPIXELS, ISWITHIN, OUTPROJECTION, PHOTORESPONSE) \ Status \ undistortInput_##INPROJECTION##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##ISWITHIN##_##OUTPROJECTION##_##PHOTORESPONSE( \ int time, GPU::Surface& dst, const GPU::Surface& src, const PanoDefinition& pano, \ const InputDefinition& recordedInput, const InputDefinition& undistortedOutput, GPU::Stream& stream) const { \ GeometryDefinition inGeometry = recordedInput.getGeometries().at(time); \ /* let's have rig center == camera center for the mapping */ \ inGeometry.setTranslationX(0); \ inGeometry.setTranslationY(0); \ inGeometry.setTranslationZ(0); \ \ TransformGeoParams inParams(recordedInput, inGeometry, pano); \ \ GeometryDefinition outGeometry = undistortedOutput.getGeometries().at(time); \ /* let's have rig center == camera center for the mapping */ \ outGeometry.setTranslationX(0); \ outGeometry.setTranslationY(0); \ outGeometry.setTranslationZ(0); \ \ TransformGeoParams outParams(undistortedOutput, outGeometry, pano); \ \ const float2 inScale{(float)inGeometry.getHorizontalFocal(), (float)inGeometry.getVerticalFocal()}; \ const float2 outScale{(float)outGeometry.getHorizontalFocal(), (float)outGeometry.getVerticalFocal()}; \ \ auto distortion = GET_DISTORTION(inParams); \ const float2 center{(float)recordedInput.getCenterX(inGeometry), (float)recordedInput.getCenterY(inGeometry)}; \ \ const float3 colorMult = PhotoTransform::ColorCorrectionParams( \ recordedInput.getExposureValue().at(time), recordedInput.getRedCB().at(time), \ recordedInput.getGreenCB().at(time), recordedInput.getBlueCB().at(time)) \ .computeColorMultiplier(pano.getExposureValue().at(time), pano.getRedCB().at(time), \ pano.getGreenCB().at(time), pano.getBlueCB().at(time)); \ const cl_float3 colorMultPadded{{colorMult.x, colorMult.y, colorMult.z}}; \ \ std::string kernelName = "warpInputKernel_" QUOTE( \ INPROJECTION##_##DISTORTIONMETERS##_##DISTORTIONPIXELS##_##ISWITHIN##_##OUTPROJECTION##_##PHOTORESPONSE); \ auto kernel2D = \ GPU::Kernel::get(PROGRAM(undistortKernel), kernelName) \ .setup2D(stream, (unsigned)undistortedOutput.getWidth(), (unsigned)undistortedOutput.getHeight()); \ return kernel2D.enqueueWithKernelArgs( \ dst.get(), src.get(), (unsigned)recordedInput.getWidth(), (unsigned)recordedInput.getHeight(), \ (unsigned)undistortedOutput.getWidth(), (unsigned)undistortedOutput.getHeight(), \ (unsigned)recordedInput.getCropLeft(), (unsigned)recordedInput.getCropRight(), \ (unsigned)recordedInput.getCropTop(), (unsigned)recordedInput.getCropBottom(), inParams.getPose(), \ outParams.getPoseInverse(), distortion, center, inScale, outScale, colorMultPadded, \ photo->getDevicePhotoParam().floatParam, photo->getDevicePhotoParam().transformData, \ (float)recordedInput.getVignettingCenterX(), (float)recordedInput.getVignettingCenterY(), \ (float)TransformGeoParams::getInverseDemiDiagonalSquared(recordedInput), \ (float)recordedInput.getVignettingCoeff0(), (float)recordedInput.getVignettingCoeff1(), \ (float)recordedInput.getVignettingCoeff2(), (float)recordedInput.getVignettingCoeff3()); \ } /*Namespaces end*/ } // namespace } // namespace Core } // namespace VideoStitch #include "backend/common/core1/transform.impl" namespace VideoStitch { namespace Core { Transform* Transform::create(const InputDefinition& im) { return createTransform(im, ImageMerger::Format::None); } Transform* Transform::create(const InputDefinition& im, const ImageMerger::Format type) { return createTransform(im, type); } } // namespace Core } // namespace VideoStitch