vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
if(IOS OR WINRT OR (NOT HAVE_CUDA AND NOT BUILD_CUDA_STUBS))
|
||||
ocv_module_disable(cudawarping)
|
||||
endif()
|
||||
|
||||
set(the_description "CUDA-accelerated Image Warping")
|
||||
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127 /wd4324 /wd4512 -Wundef -Wmissing-declarations -Wshadow)
|
||||
|
||||
set(build_libs "")
|
||||
if(ENABLE_CUDA_FIRST_CLASS_LANGUAGE)
|
||||
list(APPEND build_libs CUDA::cudart${CUDA_LIB_EXT} CUDA::nppial${CUDA_LIB_EXT} CUDA::nppig${CUDA_LIB_EXT})
|
||||
endif()
|
||||
|
||||
ocv_add_module(cudawarping opencv_core opencv_imgproc opencv_geometry OPTIONAL opencv_cudev WRAP python)
|
||||
|
||||
ocv_module_include_directories()
|
||||
ocv_glob_module_sources()
|
||||
|
||||
ocv_create_module(${build_libs})
|
||||
|
||||
set(test_libs "")
|
||||
if(ENABLE_CUDA_FIRST_CLASS_LANGUAGE)
|
||||
list(APPEND test_libs CUDA::cudart${CUDA_LIB_EXT})
|
||||
endif()
|
||||
ocv_add_accuracy_tests(${test_libs})
|
||||
ocv_add_perf_tests()
|
||||
@@ -0,0 +1,260 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef OPENCV_CUDAWARPING_HPP
|
||||
#define OPENCV_CUDAWARPING_HPP
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error cudawarping.hpp header must be compiled as C++
|
||||
#endif
|
||||
|
||||
#include "opencv2/core/cuda.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
/**
|
||||
@addtogroup cuda
|
||||
@{
|
||||
@defgroup cudawarping Image Warping
|
||||
@}
|
||||
*/
|
||||
|
||||
namespace cv { namespace cuda {
|
||||
|
||||
//! @addtogroup cudawarping
|
||||
//! @{
|
||||
|
||||
/** @brief Applies a generic geometrical transformation to an image.
|
||||
|
||||
@param src Source image.
|
||||
@param dst Destination image with the size the same as xmap and the type the same as src .
|
||||
@param xmap X values. Only CV_32FC1 type is supported.
|
||||
@param ymap Y values. Only CV_32FC1 type is supported.
|
||||
@param interpolation Interpolation method (see resize ). INTER_NEAREST , INTER_LINEAR and
|
||||
INTER_CUBIC are supported for now.
|
||||
The extra flag WARP_RELATIVE_MAP can be ORed to the interpolation method
|
||||
(e.g. INTER_LINEAR | WARP_RELATIVE_MAP)
|
||||
@param borderMode Pixel extrapolation method (see borderInterpolate ). BORDER_REFLECT101 ,
|
||||
BORDER_REPLICATE , BORDER_CONSTANT , BORDER_REFLECT and BORDER_WRAP are supported for now.
|
||||
@param borderValue Value used in case of a constant border. By default, it is 0.
|
||||
@param stream Stream for the asynchronous version.
|
||||
|
||||
The function transforms the source image using the specified map:
|
||||
|
||||
\f[\texttt{dst} (x,y) = \texttt{src} (xmap(x,y), ymap(x,y))\f]
|
||||
|
||||
with the WARP_RELATIVE_MAP flag :
|
||||
|
||||
\f[\texttt{dst} (x,y) = \texttt{src} (x+map_x(x,y),y+map_y(x,y))\f]
|
||||
|
||||
Values of pixels with non-integer coordinates are computed using the bilinear interpolation.
|
||||
|
||||
@sa remap
|
||||
*/
|
||||
CV_EXPORTS_W void remap(InputArray src, OutputArray dst, InputArray xmap, InputArray ymap,
|
||||
int interpolation, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar(),
|
||||
Stream& stream = Stream::Null());
|
||||
|
||||
/** @brief Resizes an image.
|
||||
|
||||
@param src Source image.
|
||||
@param dst Destination image with the same type as src . The size is dsize (when it is non-zero)
|
||||
or the size is computed from src.size() , fx , and fy .
|
||||
@param dsize Destination image size. If it is zero, it is computed as:
|
||||
\f[\texttt{dsize = Size(round(fx*src.cols), round(fy*src.rows))}\f]
|
||||
Either dsize or both fx and fy must be non-zero.
|
||||
@param fx Scale factor along the horizontal axis. If it is zero, it is computed as:
|
||||
\f[\texttt{(double)dsize.width/src.cols}\f]
|
||||
@param fy Scale factor along the vertical axis. If it is zero, it is computed as:
|
||||
\f[\texttt{(double)dsize.height/src.rows}\f]
|
||||
@param interpolation Interpolation method. INTER_NEAREST , INTER_LINEAR , INTER_CUBIC , and INTER_AREA are
|
||||
supported.
|
||||
@param stream Stream for the asynchronous version.
|
||||
|
||||
@sa resize
|
||||
*/
|
||||
CV_EXPORTS_W void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation = INTER_LINEAR, Stream& stream = Stream::Null());
|
||||
|
||||
/** @brief Applies an affine transformation to an image.
|
||||
|
||||
@param src Source image. CV_8U , CV_16U , CV_32S , or CV_32F depth and 1, 3, or 4 channels are
|
||||
supported.
|
||||
@param dst Destination image with the same type as src . The size is dsize .
|
||||
**In-place operation (src == dst) is not supported and will result in an error.**
|
||||
@param M *2x3* Mat or UMat transformation matrix.
|
||||
@param dsize Size of the destination image.
|
||||
@param flags Combination of interpolation methods (see resize) and the optional flag
|
||||
WARP_INVERSE_MAP specifying that M is an inverse transformation ( dst=\>src ). Only
|
||||
INTER_NEAREST , INTER_LINEAR , and INTER_CUBIC interpolation methods are supported.
|
||||
@param borderMode
|
||||
@param borderValue
|
||||
@param stream Stream for the asynchronous version.
|
||||
|
||||
@note In-place operation is not supported. If src and dst refer to the same data, the behavior is undefined.
|
||||
@sa warpAffine
|
||||
*/
|
||||
CV_EXPORTS void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags = INTER_LINEAR,
|
||||
int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar(), Stream& stream = Stream::Null());
|
||||
|
||||
CV_WRAP inline void warpAffine(InputArray src, OutputArray dst, UMat M, Size dsize, int flags = INTER_LINEAR,
|
||||
int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar(), Stream& stream = Stream::Null()) {
|
||||
warpAffine(src, dst, InputArray(M), dsize, flags, borderMode, borderValue, stream);
|
||||
}
|
||||
|
||||
CV_WRAP inline void warpAffine(InputArray src, OutputArray dst, Mat M, Size dsize, int flags = INTER_LINEAR,
|
||||
int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar(), Stream& stream = Stream::Null()) {
|
||||
warpAffine(src, dst, InputArray(M), dsize, flags, borderMode, borderValue, stream);
|
||||
}
|
||||
|
||||
/** @brief Builds transformation maps for affine transformation.
|
||||
|
||||
@param M *2x3* Mat or UMat transformation matrix.
|
||||
@param inverse Flag specifying that M is an inverse transformation ( dst=\>src ).
|
||||
@param dsize Size of the destination image.
|
||||
@param xmap X values with CV_32FC1 type.
|
||||
@param ymap Y values with CV_32FC1 type.
|
||||
@param stream Stream for the asynchronous version.
|
||||
|
||||
@sa cuda::warpAffine , cuda::remap
|
||||
*/
|
||||
CV_EXPORTS void buildWarpAffineMaps(InputArray M, bool inverse, Size dsize, OutputArray xmap, OutputArray ymap, Stream& stream = Stream::Null());
|
||||
|
||||
CV_WRAP inline void buildWarpAffineMaps(UMat M, bool inverse, Size dsize, CV_OUT GpuMat& xmap, CV_OUT GpuMat& ymap, Stream& stream = Stream::Null()) {
|
||||
buildWarpAffineMaps(InputArray(M), inverse, dsize, OutputArray(xmap), OutputArray(ymap), stream);
|
||||
}
|
||||
|
||||
CV_WRAP inline void buildWarpAffineMaps(Mat M, bool inverse, Size dsize, CV_OUT GpuMat& xmap, CV_OUT GpuMat& ymap, Stream& stream = Stream::Null()) {
|
||||
buildWarpAffineMaps(InputArray(M), inverse, dsize, OutputArray(xmap), OutputArray(ymap), stream);
|
||||
}
|
||||
|
||||
/** @brief Applies a perspective transformation to an image.
|
||||
|
||||
@param src Source image. CV_8U , CV_16U , CV_32S , or CV_32F depth and 1, 3, or 4 channels are
|
||||
supported.
|
||||
@param dst Destination image with the same type as src . The size is dsize .
|
||||
@param M *3x3* Mat or UMat transformation matrix.
|
||||
@param dsize Size of the destination image.
|
||||
@param flags Combination of interpolation methods (see resize ) and the optional flag
|
||||
WARP_INVERSE_MAP specifying that M is the inverse transformation ( dst =\> src ). Only
|
||||
INTER_NEAREST , INTER_LINEAR , and INTER_CUBIC interpolation methods are supported.
|
||||
@param borderMode
|
||||
@param borderValue
|
||||
@param stream Stream for the asynchronous version.
|
||||
|
||||
@sa warpPerspective
|
||||
*/
|
||||
CV_EXPORTS void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags = INTER_LINEAR,
|
||||
int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar(), Stream& stream = Stream::Null());
|
||||
|
||||
CV_WRAP inline void warpPerspective(InputArray src, OutputArray dst, UMat M, Size dsize, int flags = INTER_LINEAR,
|
||||
int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar(), Stream& stream = Stream::Null()) {
|
||||
warpPerspective(src, dst, InputArray(M), dsize, flags, borderMode, borderValue, stream);
|
||||
}
|
||||
|
||||
CV_WRAP inline void warpPerspective(InputArray src, OutputArray dst, Mat M, Size dsize, int flags = INTER_LINEAR,
|
||||
int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar(), Stream& stream = Stream::Null()) {
|
||||
warpPerspective(src, dst, InputArray(M), dsize, flags, borderMode, borderValue, stream);
|
||||
}
|
||||
|
||||
/** @brief Builds transformation maps for perspective transformation.
|
||||
|
||||
@param M *3x3* Mat or UMat transformation matrix.
|
||||
@param inverse Flag specifying that M is an inverse transformation ( dst=\>src ).
|
||||
@param dsize Size of the destination image.
|
||||
@param xmap X values with CV_32FC1 type.
|
||||
@param ymap Y values with CV_32FC1 type.
|
||||
@param stream Stream for the asynchronous version.
|
||||
|
||||
@sa cuda::warpPerspective , cuda::remap
|
||||
*/
|
||||
CV_EXPORTS void buildWarpPerspectiveMaps(InputArray M, bool inverse, Size dsize, OutputArray xmap, OutputArray ymap, Stream& stream = Stream::Null());
|
||||
|
||||
CV_WRAP inline void buildWarpPerspectiveMaps(UMat M, bool inverse, Size dsize, CV_OUT GpuMat& xmap, CV_OUT GpuMat& ymap, Stream& stream = Stream::Null()) {
|
||||
buildWarpPerspectiveMaps(InputArray(M), inverse, dsize, OutputArray(xmap), OutputArray(ymap), stream);
|
||||
}
|
||||
|
||||
CV_WRAP inline void buildWarpPerspectiveMaps(Mat M, bool inverse, Size dsize, CV_OUT GpuMat& xmap, CV_OUT GpuMat& ymap, Stream& stream = Stream::Null()) {
|
||||
buildWarpPerspectiveMaps(InputArray(M), inverse, dsize, OutputArray(xmap), OutputArray(ymap), stream);
|
||||
}
|
||||
|
||||
/** @brief Rotates an image around the origin (0,0) and then shifts it.
|
||||
|
||||
@param src Source image. Supports 1, 3 or 4 channels images with CV_8U , CV_16U or CV_32F
|
||||
depth.
|
||||
@param dst Destination image with the same type as src . The size is dsize .
|
||||
@param dsize Size of the destination image.
|
||||
@param angle Angle of rotation in degrees.
|
||||
@param xShift Shift along the horizontal axis.
|
||||
@param yShift Shift along the vertical axis.
|
||||
@param interpolation Interpolation method. Only INTER_NEAREST , INTER_LINEAR , and INTER_CUBIC
|
||||
are supported.
|
||||
@param stream Stream for the asynchronous version.
|
||||
|
||||
@sa cuda::warpAffine
|
||||
*/
|
||||
CV_EXPORTS_W void rotate(InputArray src, OutputArray dst, Size dsize, double angle, double xShift = 0, double yShift = 0,
|
||||
int interpolation = INTER_LINEAR, Stream& stream = Stream::Null());
|
||||
|
||||
/** @brief Smoothes an image and downsamples it.
|
||||
|
||||
@param src Source image.
|
||||
@param dst Destination image. Will have Size((src.cols+1)/2, (src.rows+1)/2) size and the same
|
||||
type as src .
|
||||
@param stream Stream for the asynchronous version.
|
||||
|
||||
@sa pyrDown
|
||||
*/
|
||||
CV_EXPORTS_W void pyrDown(InputArray src, OutputArray dst, Stream& stream = Stream::Null());
|
||||
|
||||
/** @brief Upsamples an image and then smoothes it.
|
||||
|
||||
@param src Source image.
|
||||
@param dst Destination image. Will have Size(src.cols\*2, src.rows\*2) size and the same type as
|
||||
src .
|
||||
@param stream Stream for the asynchronous version.
|
||||
*/
|
||||
CV_EXPORTS_W void pyrUp(InputArray src, OutputArray dst, Stream& stream = Stream::Null());
|
||||
|
||||
//! @}
|
||||
|
||||
}} // namespace cv { namespace cuda {
|
||||
|
||||
#endif /* OPENCV_CUDAWARPING_HPP */
|
||||
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python
|
||||
import os
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
|
||||
from tests_common import NewOpenCVTests, unittest
|
||||
|
||||
def create_affine_transform_matrix(size,angle):
|
||||
return np.array([[np.cos(angle), -np.sin(angle), size[1]/2], [np.sin(angle), np.cos(angle), 0]])
|
||||
def create_perspective_transform_matrix(size,angle):
|
||||
return np.vstack([create_affine_transform_matrix(size,angle),[0, 0, 1]])
|
||||
|
||||
class cudawarping_test(NewOpenCVTests):
|
||||
def setUp(self):
|
||||
super(cudawarping_test, self).setUp()
|
||||
if not cv.cuda.getCudaEnabledDeviceCount():
|
||||
self.skipTest("No CUDA-capable device is detected")
|
||||
|
||||
def test_resize(self):
|
||||
dstSz = (256,256)
|
||||
interp = cv.INTER_NEAREST
|
||||
npMat = (np.random.random((128,128,3))*255).astype(np.uint8)
|
||||
|
||||
cuMat = cv.cuda_GpuMat(npMat)
|
||||
cuMatDst = cv.cuda_GpuMat(dstSz,cuMat.type())
|
||||
|
||||
self.assertTrue(np.allclose(cv.cuda.resize(cuMat,dstSz,interpolation=interp).download(),
|
||||
cv.resize(npMat,dstSz,interpolation=interp)))
|
||||
|
||||
cv.cuda.resize(cuMat,dstSz,cuMatDst,interpolation=interp)
|
||||
self.assertTrue(np.allclose(cuMatDst.download(),cv.resize(npMat,dstSz,interpolation=interp)))
|
||||
|
||||
def test_warp(self):
|
||||
npMat = (np.random.random((128,128,3))*255).astype(np.uint8)
|
||||
size = npMat.shape[:2]
|
||||
M1 = create_affine_transform_matrix(size,np.pi/2)
|
||||
|
||||
cuMat = cv.cuda_GpuMat(npMat)
|
||||
cuMatDst = cv.cuda_GpuMat(size,cuMat.type())
|
||||
|
||||
borderType = cv.BORDER_REFLECT101
|
||||
self.assertTrue(np.allclose(cv.cuda.warpAffine(cuMat,M1,size,borderMode=borderType).download(),
|
||||
cv.warpAffine(npMat,M1,size, borderMode=borderType)))
|
||||
cv.cuda.warpAffine(cuMat,M1,size,cuMatDst,borderMode=borderType)
|
||||
self.assertTrue(np.allclose(cuMatDst.download(),cv.warpAffine(npMat,M1,size,borderMode=borderType)))
|
||||
|
||||
interpolation = cv.INTER_NEAREST
|
||||
flags = interpolation | cv.WARP_INVERSE_MAP
|
||||
dst_gold = cv.warpAffine(npMat, M1, size, flags = flags)
|
||||
cuMaps = cv.cuda.buildWarpAffineMaps(M1,True,size)
|
||||
dst = cv.remap(npMat, cuMaps[0].download(), cuMaps[1].download(),interpolation)
|
||||
self.assertTrue(np.allclose(dst,dst_gold))
|
||||
|
||||
xmap = cv.cuda_GpuMat(size,cv.CV_32FC1)
|
||||
ymap = cv.cuda_GpuMat(size,cv.CV_32FC1)
|
||||
cv.cuda.buildWarpAffineMaps(M1,True,size,xmap,ymap)
|
||||
dst = cv.remap(npMat, xmap.download(), ymap.download(),interpolation)
|
||||
self.assertTrue(np.allclose(dst,dst_gold))
|
||||
|
||||
M2 = create_perspective_transform_matrix(size,np.pi/2)
|
||||
np.allclose(cv.cuda.warpPerspective(cuMat,M2,size,borderMode=borderType).download(),
|
||||
cv.warpPerspective(npMat,M2,size,borderMode=borderType))
|
||||
cv.cuda.warpPerspective(cuMat,M2,size,cuMatDst,borderMode=borderType)
|
||||
self.assertTrue(np.allclose(cuMatDst.download(),cv.warpPerspective(npMat,M2,size,borderMode=borderType)))
|
||||
|
||||
dst_gold = cv.warpPerspective(npMat, M2, size, flags = flags)
|
||||
cuMaps = cv.cuda.buildWarpPerspectiveMaps(M2,True,size)
|
||||
dst = cv.remap(npMat, cuMaps[0].download(), cuMaps[1].download(),interpolation)
|
||||
self.assertTrue(np.allclose(dst,dst_gold))
|
||||
|
||||
cv.cuda.buildWarpPerspectiveMaps(M2,True,size,xmap,ymap)
|
||||
dst = cv.remap(npMat, xmap.download(), ymap.download(),interpolation)
|
||||
self.assertTrue(np.allclose(dst,dst_gold))
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -0,0 +1,47 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
using namespace perf;
|
||||
|
||||
CV_PERF_TEST_CUDA_MAIN(cudawarping)
|
||||
@@ -0,0 +1,55 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_PERF_PRECOMP_HPP__
|
||||
#define __OPENCV_PERF_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts.hpp"
|
||||
#include "opencv2/ts/cuda_perf.hpp"
|
||||
|
||||
#include "opencv2/cudawarping.hpp"
|
||||
|
||||
namespace opencv_test {
|
||||
using namespace perf;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,487 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "perf_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Remap
|
||||
|
||||
enum { HALF_SIZE=0, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH };
|
||||
CV_ENUM(RemapMode, HALF_SIZE, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH)
|
||||
|
||||
void generateMap(cv::Mat& map_x, cv::Mat& map_y, int remapMode)
|
||||
{
|
||||
for (int j = 0; j < map_x.rows; ++j)
|
||||
{
|
||||
for (int i = 0; i < map_x.cols; ++i)
|
||||
{
|
||||
switch (remapMode)
|
||||
{
|
||||
case HALF_SIZE:
|
||||
if (i > map_x.cols*0.25 && i < map_x.cols*0.75 && j > map_x.rows*0.25 && j < map_x.rows*0.75)
|
||||
{
|
||||
map_x.at<float>(j,i) = 2.f * (i - map_x.cols * 0.25f) + 0.5f;
|
||||
map_y.at<float>(j,i) = 2.f * (j - map_x.rows * 0.25f) + 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
map_x.at<float>(j,i) = 0.f;
|
||||
map_y.at<float>(j,i) = 0.f;
|
||||
}
|
||||
break;
|
||||
case UPSIDE_DOWN:
|
||||
map_x.at<float>(j,i) = static_cast<float>(i);
|
||||
map_y.at<float>(j,i) = static_cast<float>(map_x.rows - j);
|
||||
break;
|
||||
case REFLECTION_X:
|
||||
map_x.at<float>(j,i) = static_cast<float>(map_x.cols - i);
|
||||
map_y.at<float>(j,i) = static_cast<float>(j);
|
||||
break;
|
||||
case REFLECTION_BOTH:
|
||||
map_x.at<float>(j,i) = static_cast<float>(map_x.cols - i);
|
||||
map_y.at<float>(j,i) = static_cast<float>(map_x.rows - j);
|
||||
break;
|
||||
} // end of switch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEF_PARAM_TEST(Sz_Depth_Cn_Inter_Border_Mode, cv::Size, MatDepth, MatCn, Interpolation, BorderMode, RemapMode);
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn_Inter_Border_Mode, Remap,
|
||||
Combine(CUDA_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
CUDA_CHANNELS_1_3_4,
|
||||
Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
|
||||
ALL_BORDER_MODES,
|
||||
RemapMode::all()))
|
||||
{
|
||||
declare.time(20.0);
|
||||
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
const int channels = GET_PARAM(2);
|
||||
const int interpolation = GET_PARAM(3);
|
||||
const int borderMode = GET_PARAM(4);
|
||||
const int remapMode = GET_PARAM(5);
|
||||
|
||||
const int type = CV_MAKE_TYPE(depth, channels);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
declare.in(src, WARMUP_RNG);
|
||||
|
||||
cv::Mat xmap(size, CV_32FC1);
|
||||
cv::Mat ymap(size, CV_32FC1);
|
||||
generateMap(xmap, ymap, remapMode);
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
const cv::cuda::GpuMat d_src(src);
|
||||
const cv::cuda::GpuMat d_xmap(xmap);
|
||||
const cv::cuda::GpuMat d_ymap(ymap);
|
||||
cv::cuda::GpuMat dst;
|
||||
|
||||
TEST_CYCLE() cv::cuda::remap(d_src, dst, d_xmap, d_ymap, interpolation, borderMode);
|
||||
|
||||
CUDA_SANITY_CHECK(dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat dst;
|
||||
|
||||
TEST_CYCLE() cv::remap(src, dst, xmap, ymap, interpolation, borderMode);
|
||||
|
||||
CPU_SANITY_CHECK(dst);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Resize
|
||||
|
||||
DEF_PARAM_TEST(Sz_Depth_Cn_Inter_Scale, cv::Size, MatDepth, MatCn, Interpolation, double);
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn_Inter_Scale, Resize,
|
||||
Combine(CUDA_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
CUDA_CHANNELS_1_3_4,
|
||||
Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
|
||||
Values(0.5, 0.3, 2.0)))
|
||||
{
|
||||
declare.time(20.0);
|
||||
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
const int channels = GET_PARAM(2);
|
||||
const int interpolation = GET_PARAM(3);
|
||||
const double f = GET_PARAM(4);
|
||||
|
||||
const int type = CV_MAKE_TYPE(depth, channels);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
declare.in(src, WARMUP_RNG);
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
const cv::cuda::GpuMat d_src(src);
|
||||
cv::cuda::GpuMat dst;
|
||||
|
||||
TEST_CYCLE() cv::cuda::resize(d_src, dst, cv::Size(), f, f, interpolation);
|
||||
|
||||
CUDA_SANITY_CHECK(dst, 1e-3, ERROR_RELATIVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat dst;
|
||||
|
||||
TEST_CYCLE() cv::resize(src, dst, cv::Size(), f, f, interpolation);
|
||||
|
||||
CPU_SANITY_CHECK(dst);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// ResizeLanczos
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn_Inter_Scale, ResizeLanczos,
|
||||
Combine(CUDA_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_32F),
|
||||
CUDA_CHANNELS_1_3_4,
|
||||
Values(Interpolation(cv::INTER_LANCZOS4)),
|
||||
Values(0.5, 1.5, 2.0)))
|
||||
{
|
||||
declare.time(20.0);
|
||||
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
const int channels = GET_PARAM(2);
|
||||
const int interpolation = GET_PARAM(3);
|
||||
const double f = GET_PARAM(4);
|
||||
|
||||
const int type = CV_MAKE_TYPE(depth, channels);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
declare.in(src, WARMUP_RNG);
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
const cv::cuda::GpuMat d_src(src);
|
||||
cv::cuda::GpuMat dst;
|
||||
cv::Size dsize(cv::saturate_cast<int>(src.cols * f), cv::saturate_cast<int>(src.rows * f));
|
||||
cv::Mat host_dst(dsize, type);
|
||||
|
||||
declare.out(host_dst);
|
||||
|
||||
TEST_CYCLE() cv::cuda::resize(d_src, dst, cv::Size(), f, f, interpolation);
|
||||
|
||||
dst.download(host_dst);
|
||||
|
||||
CUDA_SANITY_CHECK(dst, 1e-3, ERROR_RELATIVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Size dsize(cv::saturate_cast<int>(src.cols * f), cv::saturate_cast<int>(src.rows * f));
|
||||
cv::Mat dst(dsize, type);
|
||||
|
||||
declare.out(dst);
|
||||
|
||||
TEST_CYCLE() cv::resize(src, dst, cv::Size(), f, f, interpolation);
|
||||
|
||||
CPU_SANITY_CHECK(dst);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// ResizeArea
|
||||
|
||||
DEF_PARAM_TEST(Sz_Depth_Cn_Scale, cv::Size, MatDepth, MatCn, double);
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn_Scale, ResizeArea,
|
||||
Combine(CUDA_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
CUDA_CHANNELS_1_3_4,
|
||||
Values(0.2, 0.1, 0.05)))
|
||||
{
|
||||
declare.time(1.0);
|
||||
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
const int channels = GET_PARAM(2);
|
||||
const int interpolation = cv::INTER_AREA;
|
||||
const double f = GET_PARAM(3);
|
||||
|
||||
const int type = CV_MAKE_TYPE(depth, channels);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
declare.in(src, WARMUP_RNG);
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
const cv::cuda::GpuMat d_src(src);
|
||||
cv::cuda::GpuMat dst;
|
||||
|
||||
TEST_CYCLE() cv::cuda::resize(d_src, dst, cv::Size(), f, f, interpolation);
|
||||
|
||||
CUDA_SANITY_CHECK(dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat dst;
|
||||
|
||||
TEST_CYCLE() cv::resize(src, dst, cv::Size(), f, f, interpolation);
|
||||
|
||||
CPU_SANITY_CHECK(dst);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// WarpAffine
|
||||
|
||||
DEF_PARAM_TEST(Sz_Depth_Cn_Inter_Border, cv::Size, MatDepth, MatCn, Interpolation, BorderMode);
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn_Inter_Border, WarpAffine,
|
||||
Combine(CUDA_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
CUDA_CHANNELS_1_3_4,
|
||||
Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
|
||||
ALL_BORDER_MODES))
|
||||
{
|
||||
declare.time(20.0);
|
||||
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
const int channels = GET_PARAM(2);
|
||||
const int interpolation = GET_PARAM(3);
|
||||
const int borderMode = GET_PARAM(4);
|
||||
|
||||
const int type = CV_MAKE_TYPE(depth, channels);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
declare.in(src, WARMUP_RNG);
|
||||
|
||||
const double aplha = CV_PI / 4;
|
||||
const double mat[2 * 3] =
|
||||
{
|
||||
std::cos(aplha), -std::sin(aplha), static_cast<double>(src.cols) / 2.0,
|
||||
std::sin(aplha), std::cos(aplha), 0
|
||||
};
|
||||
const cv::Mat M(2, 3, CV_64F, (void*) mat);
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
const cv::cuda::GpuMat d_src(src);
|
||||
cv::cuda::GpuMat dst;
|
||||
|
||||
TEST_CYCLE() cv::cuda::warpAffine(d_src, dst, M, size, interpolation, borderMode);
|
||||
|
||||
CUDA_SANITY_CHECK(dst, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat dst;
|
||||
|
||||
TEST_CYCLE() cv::warpAffine(src, dst, M, size, interpolation, borderMode);
|
||||
|
||||
CPU_SANITY_CHECK(dst);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// WarpPerspective
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn_Inter_Border, WarpPerspective,
|
||||
Combine(CUDA_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
CUDA_CHANNELS_1_3_4,
|
||||
Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
|
||||
ALL_BORDER_MODES))
|
||||
{
|
||||
declare.time(20.0);
|
||||
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
const int channels = GET_PARAM(2);
|
||||
const int interpolation = GET_PARAM(3);
|
||||
const int borderMode = GET_PARAM(4);
|
||||
|
||||
const int type = CV_MAKE_TYPE(depth, channels);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
declare.in(src, WARMUP_RNG);
|
||||
|
||||
const double aplha = CV_PI / 4;
|
||||
double mat[3][3] = { {std::cos(aplha), -std::sin(aplha), static_cast<double>(src.cols) / 2.0},
|
||||
{std::sin(aplha), std::cos(aplha), 0},
|
||||
{0.0, 0.0, 1.0}};
|
||||
const cv::Mat M(3, 3, CV_64F, (void*) mat);
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
const cv::cuda::GpuMat d_src(src);
|
||||
cv::cuda::GpuMat dst;
|
||||
|
||||
TEST_CYCLE() cv::cuda::warpPerspective(d_src, dst, M, size, interpolation, borderMode);
|
||||
|
||||
CUDA_SANITY_CHECK(dst, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat dst;
|
||||
|
||||
TEST_CYCLE() cv::warpPerspective(src, dst, M, size, interpolation, borderMode);
|
||||
|
||||
CPU_SANITY_CHECK(dst);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Rotate
|
||||
|
||||
DEF_PARAM_TEST(Sz_Depth_Cn_Inter, cv::Size, MatDepth, MatCn, Interpolation);
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn_Inter, Rotate,
|
||||
Combine(CUDA_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
CUDA_CHANNELS_1_3_4,
|
||||
Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC))))
|
||||
{
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
const int channels = GET_PARAM(2);
|
||||
const int interpolation = GET_PARAM(3);
|
||||
|
||||
const int type = CV_MAKE_TYPE(depth, channels);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
declare.in(src, WARMUP_RNG);
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
const cv::cuda::GpuMat d_src(src);
|
||||
cv::cuda::GpuMat dst;
|
||||
|
||||
TEST_CYCLE() cv::cuda::rotate(d_src, dst, size, 30.0, 0, 0, interpolation);
|
||||
|
||||
CUDA_SANITY_CHECK(dst, 1e-3, ERROR_RELATIVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL_NO_CPU();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// PyrDown
|
||||
|
||||
DEF_PARAM_TEST(Sz_Depth_Cn, cv::Size, MatDepth, MatCn);
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, PyrDown,
|
||||
Combine(CUDA_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
CUDA_CHANNELS_1_3_4))
|
||||
{
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
const int channels = GET_PARAM(2);
|
||||
|
||||
const int type = CV_MAKE_TYPE(depth, channels);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
declare.in(src, WARMUP_RNG);
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
const cv::cuda::GpuMat d_src(src);
|
||||
cv::cuda::GpuMat dst;
|
||||
|
||||
TEST_CYCLE() cv::cuda::pyrDown(d_src, dst);
|
||||
|
||||
CUDA_SANITY_CHECK(dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat dst;
|
||||
|
||||
TEST_CYCLE() cv::pyrDown(src, dst);
|
||||
|
||||
CPU_SANITY_CHECK(dst);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// PyrUp
|
||||
|
||||
PERF_TEST_P(Sz_Depth_Cn, PyrUp,
|
||||
Combine(CUDA_TYPICAL_MAT_SIZES,
|
||||
Values(CV_8U, CV_16U, CV_32F),
|
||||
CUDA_CHANNELS_1_3_4))
|
||||
{
|
||||
const cv::Size size = GET_PARAM(0);
|
||||
const int depth = GET_PARAM(1);
|
||||
const int channels = GET_PARAM(2);
|
||||
|
||||
const int type = CV_MAKE_TYPE(depth, channels);
|
||||
|
||||
cv::Mat src(size, type);
|
||||
declare.in(src, WARMUP_RNG);
|
||||
|
||||
if (PERF_RUN_CUDA())
|
||||
{
|
||||
const cv::cuda::GpuMat d_src(src);
|
||||
cv::cuda::GpuMat dst;
|
||||
|
||||
TEST_CYCLE() cv::cuda::pyrUp(d_src, dst);
|
||||
|
||||
CUDA_SANITY_CHECK(dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat dst;
|
||||
|
||||
TEST_CYCLE() cv::pyrUp(src, dst);
|
||||
|
||||
CPU_SANITY_CHECK(dst);
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,228 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#if !defined CUDA_DISABLER
|
||||
|
||||
#include "opencv2/core/cuda/common.hpp"
|
||||
#include "opencv2/core/cuda/border_interpolate.hpp"
|
||||
#include "opencv2/core/cuda/vec_traits.hpp"
|
||||
#include "opencv2/core/cuda/vec_math.hpp"
|
||||
#include "opencv2/core/cuda/saturate_cast.hpp"
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
template <typename T, typename B> __global__ void pyrDown(const PtrStepSz<T> src, PtrStep<T> dst, const B b, int dst_cols)
|
||||
{
|
||||
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type work_t;
|
||||
|
||||
__shared__ work_t smem[256 + 4];
|
||||
|
||||
const int x = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
const int y = blockIdx.y;
|
||||
|
||||
const int src_y = 2 * y;
|
||||
|
||||
if (src_y >= 2 && src_y < src.rows - 2 && x >= 2 && x < src.cols - 2)
|
||||
{
|
||||
{
|
||||
work_t sum;
|
||||
|
||||
sum = 0.0625f * src(src_y - 2, x);
|
||||
sum = sum + 0.25f * src(src_y - 1, x);
|
||||
sum = sum + 0.375f * src(src_y , x);
|
||||
sum = sum + 0.25f * src(src_y + 1, x);
|
||||
sum = sum + 0.0625f * src(src_y + 2, x);
|
||||
|
||||
smem[2 + threadIdx.x] = sum;
|
||||
}
|
||||
|
||||
if (threadIdx.x < 2)
|
||||
{
|
||||
const int left_x = x - 2;
|
||||
|
||||
work_t sum;
|
||||
|
||||
sum = 0.0625f * src(src_y - 2, left_x);
|
||||
sum = sum + 0.25f * src(src_y - 1, left_x);
|
||||
sum = sum + 0.375f * src(src_y , left_x);
|
||||
sum = sum + 0.25f * src(src_y + 1, left_x);
|
||||
sum = sum + 0.0625f * src(src_y + 2, left_x);
|
||||
|
||||
smem[threadIdx.x] = sum;
|
||||
}
|
||||
|
||||
if (threadIdx.x > 253)
|
||||
{
|
||||
const int right_x = x + 2;
|
||||
|
||||
work_t sum;
|
||||
|
||||
sum = 0.0625f * src(src_y - 2, right_x);
|
||||
sum = sum + 0.25f * src(src_y - 1, right_x);
|
||||
sum = sum + 0.375f * src(src_y , right_x);
|
||||
sum = sum + 0.25f * src(src_y + 1, right_x);
|
||||
sum = sum + 0.0625f * src(src_y + 2, right_x);
|
||||
|
||||
smem[4 + threadIdx.x] = sum;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
work_t sum;
|
||||
|
||||
sum = 0.0625f * src(b.idx_row_low (src_y - 2), b.idx_col_high(x));
|
||||
sum = sum + 0.25f * src(b.idx_row_low (src_y - 1), b.idx_col_high(x));
|
||||
sum = sum + 0.375f * src(src_y , b.idx_col_high(x));
|
||||
sum = sum + 0.25f * src(b.idx_row_high(src_y + 1), b.idx_col_high(x));
|
||||
sum = sum + 0.0625f * src(b.idx_row_high(src_y + 2), b.idx_col_high(x));
|
||||
|
||||
smem[2 + threadIdx.x] = sum;
|
||||
}
|
||||
|
||||
if (threadIdx.x < 2)
|
||||
{
|
||||
const int left_x = x - 2;
|
||||
|
||||
work_t sum;
|
||||
|
||||
sum = 0.0625f * src(b.idx_row_low (src_y - 2), b.idx_col(left_x));
|
||||
sum = sum + 0.25f * src(b.idx_row_low (src_y - 1), b.idx_col(left_x));
|
||||
sum = sum + 0.375f * src(src_y , b.idx_col(left_x));
|
||||
sum = sum + 0.25f * src(b.idx_row_high(src_y + 1), b.idx_col(left_x));
|
||||
sum = sum + 0.0625f * src(b.idx_row_high(src_y + 2), b.idx_col(left_x));
|
||||
|
||||
smem[threadIdx.x] = sum;
|
||||
}
|
||||
|
||||
if (threadIdx.x > 253)
|
||||
{
|
||||
const int right_x = x + 2;
|
||||
|
||||
work_t sum;
|
||||
|
||||
sum = 0.0625f * src(b.idx_row_low (src_y - 2), b.idx_col_high(right_x));
|
||||
sum = sum + 0.25f * src(b.idx_row_low (src_y - 1), b.idx_col_high(right_x));
|
||||
sum = sum + 0.375f * src(src_y , b.idx_col_high(right_x));
|
||||
sum = sum + 0.25f * src(b.idx_row_high(src_y + 1), b.idx_col_high(right_x));
|
||||
sum = sum + 0.0625f * src(b.idx_row_high(src_y + 2), b.idx_col_high(right_x));
|
||||
|
||||
smem[4 + threadIdx.x] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
if (threadIdx.x < 128)
|
||||
{
|
||||
const int tid2 = threadIdx.x * 2;
|
||||
|
||||
work_t sum;
|
||||
|
||||
sum = 0.0625f * smem[2 + tid2 - 2];
|
||||
sum = sum + 0.25f * smem[2 + tid2 - 1];
|
||||
sum = sum + 0.375f * smem[2 + tid2 ];
|
||||
sum = sum + 0.25f * smem[2 + tid2 + 1];
|
||||
sum = sum + 0.0625f * smem[2 + tid2 + 2];
|
||||
|
||||
const int dst_x = (blockIdx.x * blockDim.x + tid2) / 2;
|
||||
|
||||
if (dst_x < dst_cols)
|
||||
dst.ptr(y)[dst_x] = saturate_cast<T>(sum);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, template <typename> class B> void pyrDown_caller(PtrStepSz<T> src, PtrStepSz<T> dst, cudaStream_t stream)
|
||||
{
|
||||
const dim3 block(256);
|
||||
const dim3 grid(divUp(src.cols, block.x), dst.rows);
|
||||
|
||||
B<T> b(src.rows, src.cols);
|
||||
|
||||
pyrDown<T><<<grid, block, 0, stream>>>(src, dst, b, dst.cols);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
template <typename T> void pyrDown_gpu(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream)
|
||||
{
|
||||
pyrDown_caller<T, BrdReflect101>(static_cast< PtrStepSz<T> >(src), static_cast< PtrStepSz<T> >(dst), stream);
|
||||
}
|
||||
|
||||
template void pyrDown_gpu<uchar>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrDown_gpu<uchar2>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrDown_gpu<uchar3>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrDown_gpu<uchar4>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
|
||||
//template void pyrDown_gpu<schar>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrDown_gpu<char2>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrDown_gpu<char3>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrDown_gpu<char4>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
|
||||
template void pyrDown_gpu<ushort>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrDown_gpu<ushort2>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrDown_gpu<ushort3>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrDown_gpu<ushort4>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
|
||||
template void pyrDown_gpu<short>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrDown_gpu<short2>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrDown_gpu<short3>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrDown_gpu<short4>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
|
||||
template void pyrDown_gpu<int>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrDown_gpu<int2>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrDown_gpu<int3>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrDown_gpu<int4>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
|
||||
template void pyrDown_gpu<float>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrDown_gpu<float2>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrDown_gpu<float3>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrDown_gpu<float4>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
} // namespace imgproc
|
||||
}}} // namespace cv { namespace cuda { namespace cudev
|
||||
|
||||
|
||||
#endif /* CUDA_DISABLER */
|
||||
@@ -0,0 +1,196 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#if !defined CUDA_DISABLER
|
||||
|
||||
#include "opencv2/core/cuda/common.hpp"
|
||||
#include "opencv2/core/cuda/border_interpolate.hpp"
|
||||
#include "opencv2/core/cuda/vec_traits.hpp"
|
||||
#include "opencv2/core/cuda/vec_math.hpp"
|
||||
#include "opencv2/core/cuda/saturate_cast.hpp"
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
template <typename T> __global__ void pyrUp(const PtrStepSz<T> src, PtrStepSz<T> dst)
|
||||
{
|
||||
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type sum_t;
|
||||
|
||||
const int x = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
const int y = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
|
||||
__shared__ sum_t s_srcPatch[10][10];
|
||||
__shared__ sum_t s_dstPatch[20][16];
|
||||
|
||||
if (threadIdx.x < 10 && threadIdx.y < 10)
|
||||
{
|
||||
int srcx = static_cast<int>((blockIdx.x * blockDim.x) / 2 + threadIdx.x) - 1;
|
||||
int srcy = static_cast<int>((blockIdx.y * blockDim.y) / 2 + threadIdx.y) - 1;
|
||||
|
||||
srcx = ::abs(srcx);
|
||||
srcx = ::min(src.cols - 1, srcx);
|
||||
|
||||
srcy = ::abs(srcy);
|
||||
srcy = ::min(src.rows - 1, srcy);
|
||||
|
||||
s_srcPatch[threadIdx.y][threadIdx.x] = saturate_cast<sum_t>(src(srcy, srcx));
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
sum_t sum = VecTraits<sum_t>::all(0);
|
||||
|
||||
const int evenFlag = static_cast<int>((threadIdx.x & 1) == 0);
|
||||
const int oddFlag = static_cast<int>((threadIdx.x & 1) != 0);
|
||||
const bool eveny = ((threadIdx.y & 1) == 0);
|
||||
const int tidx = threadIdx.x;
|
||||
|
||||
if (eveny)
|
||||
{
|
||||
sum = sum + (evenFlag * 0.0625f) * s_srcPatch[1 + (threadIdx.y >> 1)][1 + ((tidx - 2) >> 1)];
|
||||
sum = sum + ( oddFlag * 0.25f ) * s_srcPatch[1 + (threadIdx.y >> 1)][1 + ((tidx - 1) >> 1)];
|
||||
sum = sum + (evenFlag * 0.375f ) * s_srcPatch[1 + (threadIdx.y >> 1)][1 + ((tidx ) >> 1)];
|
||||
sum = sum + ( oddFlag * 0.25f ) * s_srcPatch[1 + (threadIdx.y >> 1)][1 + ((tidx + 1) >> 1)];
|
||||
sum = sum + (evenFlag * 0.0625f) * s_srcPatch[1 + (threadIdx.y >> 1)][1 + ((tidx + 2) >> 1)];
|
||||
}
|
||||
|
||||
s_dstPatch[2 + threadIdx.y][threadIdx.x] = sum;
|
||||
|
||||
if (threadIdx.y < 2)
|
||||
{
|
||||
sum = VecTraits<sum_t>::all(0);
|
||||
|
||||
if (eveny)
|
||||
{
|
||||
sum = sum + (evenFlag * 0.0625f) * s_srcPatch[0][1 + ((tidx - 2) >> 1)];
|
||||
sum = sum + ( oddFlag * 0.25f ) * s_srcPatch[0][1 + ((tidx - 1) >> 1)];
|
||||
sum = sum + (evenFlag * 0.375f ) * s_srcPatch[0][1 + ((tidx ) >> 1)];
|
||||
sum = sum + ( oddFlag * 0.25f ) * s_srcPatch[0][1 + ((tidx + 1) >> 1)];
|
||||
sum = sum + (evenFlag * 0.0625f) * s_srcPatch[0][1 + ((tidx + 2) >> 1)];
|
||||
}
|
||||
|
||||
s_dstPatch[threadIdx.y][threadIdx.x] = sum;
|
||||
}
|
||||
|
||||
if (threadIdx.y > 13)
|
||||
{
|
||||
sum = VecTraits<sum_t>::all(0);
|
||||
|
||||
if (eveny)
|
||||
{
|
||||
sum = sum + (evenFlag * 0.0625f) * s_srcPatch[9][1 + ((tidx - 2) >> 1)];
|
||||
sum = sum + ( oddFlag * 0.25f ) * s_srcPatch[9][1 + ((tidx - 1) >> 1)];
|
||||
sum = sum + (evenFlag * 0.375f ) * s_srcPatch[9][1 + ((tidx ) >> 1)];
|
||||
sum = sum + ( oddFlag * 0.25f ) * s_srcPatch[9][1 + ((tidx + 1) >> 1)];
|
||||
sum = sum + (evenFlag * 0.0625f) * s_srcPatch[9][1 + ((tidx + 2) >> 1)];
|
||||
}
|
||||
|
||||
s_dstPatch[4 + threadIdx.y][threadIdx.x] = sum;
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
sum = VecTraits<sum_t>::all(0);
|
||||
|
||||
const int tidy = threadIdx.y;
|
||||
|
||||
sum = sum + 0.0625f * s_dstPatch[2 + tidy - 2][threadIdx.x];
|
||||
sum = sum + 0.25f * s_dstPatch[2 + tidy - 1][threadIdx.x];
|
||||
sum = sum + 0.375f * s_dstPatch[2 + tidy ][threadIdx.x];
|
||||
sum = sum + 0.25f * s_dstPatch[2 + tidy + 1][threadIdx.x];
|
||||
sum = sum + 0.0625f * s_dstPatch[2 + tidy + 2][threadIdx.x];
|
||||
|
||||
if (x < dst.cols && y < dst.rows)
|
||||
dst(y, x) = saturate_cast<T>(4.0f * sum);
|
||||
}
|
||||
|
||||
template <typename T> void pyrUp_caller(PtrStepSz<T> src, PtrStepSz<T> dst, cudaStream_t stream)
|
||||
{
|
||||
const dim3 block(16, 16);
|
||||
const dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
|
||||
pyrUp<<<grid, block, 0, stream>>>(src, dst);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
template <typename T> void pyrUp_gpu(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream)
|
||||
{
|
||||
pyrUp_caller<T>(static_cast< PtrStepSz<T> >(src), static_cast< PtrStepSz<T> >(dst), stream);
|
||||
}
|
||||
|
||||
template void pyrUp_gpu<uchar>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrUp_gpu<uchar2>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrUp_gpu<uchar3>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrUp_gpu<uchar4>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
|
||||
//template void pyrUp_gpu<schar>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrUp_gpu<char2>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrUp_gpu<char3>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrUp_gpu<char4>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
|
||||
template void pyrUp_gpu<ushort>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrUp_gpu<ushort2>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrUp_gpu<ushort3>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrUp_gpu<ushort4>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
|
||||
template void pyrUp_gpu<short>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrUp_gpu<short2>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrUp_gpu<short3>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrUp_gpu<short4>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
|
||||
//template void pyrUp_gpu<int>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrUp_gpu<int2>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrUp_gpu<int3>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrUp_gpu<int4>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
|
||||
template void pyrUp_gpu<float>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
//template void pyrUp_gpu<float2>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrUp_gpu<float3>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
template void pyrUp_gpu<float4>(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
} // namespace imgproc
|
||||
}}} // namespace cv { namespace cuda { namespace cudev
|
||||
|
||||
#endif /* CUDA_DISABLER */
|
||||
@@ -0,0 +1,301 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#if !defined CUDA_DISABLER
|
||||
|
||||
#include "opencv2/core/cuda/common.hpp"
|
||||
#include "opencv2/core/cuda/border_interpolate.hpp"
|
||||
#include "opencv2/core/cuda/vec_traits.hpp"
|
||||
#include "opencv2/core/cuda/vec_math.hpp"
|
||||
#include "opencv2/core/cuda/saturate_cast.hpp"
|
||||
#include "opencv2/core/cuda/filters.hpp"
|
||||
#include <opencv2/cudev/ptr2d/texture.hpp>
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
template <typename Ptr2D, typename T> __global__ void remap(const Ptr2D src, const PtrStepf mapx, const PtrStepf mapy, PtrStepSz<T> dst)
|
||||
{
|
||||
const int x = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
const int y = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
|
||||
if (x < dst.cols && y < dst.rows)
|
||||
{
|
||||
const float xcoo = mapx.ptr(y)[x];
|
||||
const float ycoo = mapy.ptr(y)[x];
|
||||
|
||||
dst.ptr(y)[x] = saturate_cast<T>(src(ycoo, xcoo));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Ptr2D, typename T> __global__ void remap_relative(const Ptr2D src, const PtrStepf mapx, const PtrStepf mapy, PtrStepSz<T> dst)
|
||||
{
|
||||
const int x = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
const int y = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
|
||||
if (x < dst.cols && y < dst.rows)
|
||||
{
|
||||
const float xcoo = x+mapx.ptr(y)[x];
|
||||
const float ycoo = y+mapy.ptr(y)[x];
|
||||
|
||||
dst.ptr(y)[x] = saturate_cast<T>(src(ycoo, xcoo));
|
||||
}
|
||||
}
|
||||
|
||||
template <template <typename> class Filter, template <typename> class B, typename T> struct RemapDispatcherStream
|
||||
{
|
||||
static void call(PtrStepSz<T> src, PtrStepSzf mapx, PtrStepSzf mapy, PtrStepSz<T> dst, const float* borderValue, cudaStream_t stream, bool, bool isRelative)
|
||||
{
|
||||
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type work_type;
|
||||
|
||||
dim3 block(32, 8);
|
||||
dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
|
||||
B<work_type> brd(src.rows, src.cols, VecTraits<work_type>::make(borderValue));
|
||||
BorderReader<PtrStep<T>, B<work_type>> brdSrc(src, brd);
|
||||
Filter<BorderReader<PtrStep<T>, B<work_type>>> filter_src(brdSrc);
|
||||
|
||||
if (isRelative)
|
||||
remap_relative<<<grid, block, 0, stream>>>(filter_src, mapx, mapy, dst);
|
||||
else
|
||||
remap<<<grid, block, 0, stream>>>(filter_src, mapx, mapy, dst);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
}
|
||||
};
|
||||
|
||||
template <template <typename> class Filter, template <typename> class B, typename T> struct RemapDispatcherNonStream
|
||||
{
|
||||
static void call(PtrStepSz<T> src, PtrStepSz<T> srcWhole, int xoff, int yoff, PtrStepSzf mapx, PtrStepSzf mapy, PtrStepSz<T> dst, const float* borderValue, bool, bool isRelative)
|
||||
{
|
||||
CV_UNUSED(srcWhole);
|
||||
CV_UNUSED(xoff);
|
||||
CV_UNUSED(yoff);
|
||||
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type work_type;
|
||||
|
||||
dim3 block(32, 8);
|
||||
dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
|
||||
B<work_type> brd(src.rows, src.cols, VecTraits<work_type>::make(borderValue));
|
||||
BorderReader<PtrStep<T>, B<work_type>> brdSrc(src, brd);
|
||||
Filter<BorderReader<PtrStep<T>, B<work_type>>> filter_src(brdSrc);
|
||||
|
||||
if (isRelative)
|
||||
remap_relative<<<grid, block>>>(filter_src, mapx, mapy, dst);
|
||||
else
|
||||
remap<<<grid, block>>>(filter_src, mapx, mapy, dst);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
};
|
||||
|
||||
template <template <typename> class Filter, template <typename> class B, typename T> struct RemapDispatcherNonStreamTex
|
||||
{
|
||||
static void call(PtrStepSz< T > src, PtrStepSz< T > srcWhole, int xoff, int yoff, PtrStepSzf mapx, PtrStepSzf mapy,
|
||||
PtrStepSz< T > dst, const float* borderValue, bool cc20, bool isRelative)
|
||||
{
|
||||
typedef typename TypeVec<float, VecTraits< T >::cn>::vec_type work_type;
|
||||
dim3 block(32, cc20 ? 8 : 4);
|
||||
dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
if (srcWhole.cols == src.cols && srcWhole.rows == src.rows)
|
||||
{
|
||||
cudev::Texture<T> texSrcWhole(srcWhole);
|
||||
B<work_type> brd(src.rows, src.cols, VecTraits<work_type>::make(borderValue));
|
||||
BorderReader<cudev::TexturePtr<T>, B<work_type>> brdSrc(texSrcWhole, brd);
|
||||
Filter<BorderReader<cudev::TexturePtr<T>, B<work_type>>> filter_src(brdSrc);
|
||||
if (isRelative)
|
||||
remap_relative<<<grid, block>>>(filter_src, mapx, mapy, dst);
|
||||
else
|
||||
remap<<<grid, block>>>(filter_src, mapx, mapy, dst);
|
||||
|
||||
}
|
||||
else {
|
||||
cudev::TextureOff<T> texSrcWhole(srcWhole, yoff, xoff);
|
||||
B<work_type> brd(src.rows, src.cols, VecTraits<work_type>::make(borderValue));
|
||||
BorderReader<cudev::TextureOffPtr<T>, B<work_type>> brdSrc(texSrcWhole, brd);
|
||||
Filter<BorderReader<cudev::TextureOffPtr<T>, B<work_type>>> filter_src(brdSrc);
|
||||
if (isRelative)
|
||||
remap_relative<<<grid, block>>>(filter_src, mapx, mapy, dst);
|
||||
else
|
||||
remap<<<grid, block >>>(filter_src, mapx, mapy, dst);
|
||||
}
|
||||
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
};
|
||||
|
||||
template <template <typename> class Filter, typename T> struct RemapDispatcherNonStreamTex<Filter, BrdReplicate, T>
|
||||
{
|
||||
static void call(PtrStepSz< T > src, PtrStepSz< T > srcWhole, int xoff, int yoff, PtrStepSzf mapx, PtrStepSzf mapy,
|
||||
PtrStepSz< T > dst, const float*, bool, bool isRelative)
|
||||
{
|
||||
dim3 block(32, 8);
|
||||
dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
if (srcWhole.cols == src.cols && srcWhole.rows == src.rows)
|
||||
{
|
||||
cudev::Texture<T> texSrcWhole(srcWhole);
|
||||
Filter<cudev::TexturePtr<T>> filter_src(texSrcWhole);
|
||||
if (isRelative)
|
||||
remap_relative<<<grid, block>>>(filter_src, mapx, mapy, dst);
|
||||
else
|
||||
remap<<<grid, block>>>(filter_src, mapx, mapy, dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
cudev::TextureOff<T> texSrcWhole(srcWhole, yoff, xoff);
|
||||
BrdReplicate<T> brd(src.rows, src.cols);
|
||||
BorderReader<cudev::TextureOffPtr<T>, BrdReplicate<T>> brdSrc(texSrcWhole, brd);
|
||||
Filter<BorderReader<cudev::TextureOffPtr<T>, BrdReplicate<T>>> filter_src(brdSrc);
|
||||
if (isRelative)
|
||||
remap_relative<<<grid, block>>>(filter_src, mapx, mapy, dst);
|
||||
else
|
||||
remap<<<grid, block>>>(filter_src, mapx, mapy, dst);
|
||||
}
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <template <typename> class Filter, template <typename> class B> struct RemapDispatcherNonStream<Filter, B, uchar> :
|
||||
RemapDispatcherNonStreamTex<Filter, B, uchar> {};
|
||||
template <template <typename> class Filter, template <typename> class B> struct RemapDispatcherNonStream<Filter, B, uchar4> :
|
||||
RemapDispatcherNonStreamTex<Filter, B, uchar4> {};
|
||||
template <template <typename> class Filter, template <typename> class B> struct RemapDispatcherNonStream<Filter, B, ushort> :
|
||||
RemapDispatcherNonStreamTex<Filter, B, ushort> {};
|
||||
template <template <typename> class Filter, template <typename> class B> struct RemapDispatcherNonStream<Filter, B, ushort4> :
|
||||
RemapDispatcherNonStreamTex<Filter, B, ushort4> {};
|
||||
template <template <typename> class Filter, template <typename> class B> struct RemapDispatcherNonStream<Filter, B, short> :
|
||||
RemapDispatcherNonStreamTex<Filter, B, short> {};
|
||||
template <template <typename> class Filter, template <typename> class B> struct RemapDispatcherNonStream<Filter, B, short4> :
|
||||
RemapDispatcherNonStreamTex<Filter, B, short4> {};
|
||||
template <template <typename> class Filter, template <typename> class B> struct RemapDispatcherNonStream<Filter, B, float> :
|
||||
RemapDispatcherNonStreamTex<Filter, B, float> {};
|
||||
template <template <typename> class Filter, template <typename> class B> struct RemapDispatcherNonStream<Filter, B, float4> :
|
||||
RemapDispatcherNonStreamTex<Filter, B, float4> {};
|
||||
|
||||
template <template <typename> class Filter> struct RemapDispatcherNonStream<Filter, BrdReplicate, uchar> :
|
||||
RemapDispatcherNonStreamTex<Filter, BrdReplicate, uchar> {};
|
||||
template <template <typename> class Filter> struct RemapDispatcherNonStream<Filter, BrdReplicate, uchar4> :
|
||||
RemapDispatcherNonStreamTex<Filter, BrdReplicate, uchar4> {};
|
||||
template <template <typename> class Filter> struct RemapDispatcherNonStream<Filter, BrdReplicate, ushort> :
|
||||
RemapDispatcherNonStreamTex<Filter, BrdReplicate, ushort> {};
|
||||
template <template <typename> class Filter> struct RemapDispatcherNonStream<Filter, BrdReplicate, ushort4> :
|
||||
RemapDispatcherNonStreamTex<Filter, BrdReplicate, ushort4> {};
|
||||
template <template <typename> class Filter> struct RemapDispatcherNonStream<Filter, BrdReplicate, short> :
|
||||
RemapDispatcherNonStreamTex<Filter, BrdReplicate, short> {};
|
||||
template <template <typename> class Filter> struct RemapDispatcherNonStream<Filter, BrdReplicate, short4> :
|
||||
RemapDispatcherNonStreamTex<Filter, BrdReplicate, short4> {};
|
||||
template <template <typename> class Filter> struct RemapDispatcherNonStream<Filter, BrdReplicate, float> :
|
||||
RemapDispatcherNonStreamTex<Filter, BrdReplicate, float> {};
|
||||
template <template <typename> class Filter> struct RemapDispatcherNonStream<Filter, BrdReplicate, float4> :
|
||||
RemapDispatcherNonStreamTex<Filter, BrdReplicate, float4> {};
|
||||
|
||||
template <template <typename> class Filter, template <typename> class B, typename T> struct RemapDispatcher
|
||||
{
|
||||
static void call(PtrStepSz<T> src, PtrStepSz<T> srcWhole, int xoff, int yoff, PtrStepSzf mapx, PtrStepSzf mapy,
|
||||
PtrStepSz<T> dst, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative)
|
||||
{
|
||||
if (stream == 0)
|
||||
RemapDispatcherNonStream<Filter, B, T>::call(src, srcWhole, xoff, yoff, mapx, mapy, dst, borderValue, cc20, isRelative);
|
||||
else
|
||||
RemapDispatcherStream<Filter, B, T>::call(src, mapx, mapy, dst, borderValue, stream, cc20, isRelative);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> void remap_gpu(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap,
|
||||
PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative)
|
||||
{
|
||||
typedef void (*caller_t)(PtrStepSz<T> src, PtrStepSz<T> srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap,
|
||||
PtrStepSz<T> dst, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
|
||||
static const caller_t callers[3][5] =
|
||||
{
|
||||
{
|
||||
RemapDispatcher<PointFilter, BrdConstant, T>::call,
|
||||
RemapDispatcher<PointFilter, BrdReplicate, T>::call,
|
||||
RemapDispatcher<PointFilter, BrdReflect, T>::call,
|
||||
RemapDispatcher<PointFilter, BrdWrap, T>::call,
|
||||
RemapDispatcher<PointFilter, BrdReflect101, T>::call
|
||||
},
|
||||
{
|
||||
RemapDispatcher<LinearFilter, BrdConstant, T>::call,
|
||||
RemapDispatcher<LinearFilter, BrdReplicate, T>::call,
|
||||
RemapDispatcher<LinearFilter, BrdReflect, T>::call,
|
||||
RemapDispatcher<LinearFilter, BrdWrap, T>::call,
|
||||
RemapDispatcher<LinearFilter, BrdReflect101, T>::call
|
||||
},
|
||||
{
|
||||
RemapDispatcher<CubicFilter, BrdConstant, T>::call,
|
||||
RemapDispatcher<CubicFilter, BrdReplicate, T>::call,
|
||||
RemapDispatcher<CubicFilter, BrdReflect, T>::call,
|
||||
RemapDispatcher<CubicFilter, BrdWrap, T>::call,
|
||||
RemapDispatcher<CubicFilter, BrdReflect101, T>::call
|
||||
}
|
||||
};
|
||||
|
||||
callers[interpolation][borderMode](static_cast<PtrStepSz<T>>(src), static_cast<PtrStepSz<T>>(srcWhole), xoff, yoff, xmap, ymap,
|
||||
static_cast<PtrStepSz<T>>(dst), borderValue, stream, cc20, isRelative);
|
||||
}
|
||||
|
||||
template void remap_gpu<uchar >(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
template void remap_gpu<uchar3>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
template void remap_gpu<uchar4>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
|
||||
template void remap_gpu<ushort >(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
template void remap_gpu<ushort3>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
template void remap_gpu<ushort4>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
|
||||
template void remap_gpu<short >(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
template void remap_gpu<short3>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
template void remap_gpu<short4>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
|
||||
template void remap_gpu<float >(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
template void remap_gpu<float3>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
template void remap_gpu<float4>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
} // namespace imgproc
|
||||
}}} // namespace cv { namespace cuda { namespace cudev
|
||||
|
||||
|
||||
#endif /* CUDA_DISABLER */
|
||||
@@ -0,0 +1,762 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#if !defined CUDA_DISABLER
|
||||
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
#include "opencv2/core/cuda/common.hpp"
|
||||
#include "opencv2/core/cuda/border_interpolate.hpp"
|
||||
#include "opencv2/core/cuda/vec_traits.hpp"
|
||||
#include "opencv2/core/cuda/vec_math.hpp"
|
||||
#include "opencv2/core/cuda/saturate_cast.hpp"
|
||||
#include "opencv2/core/cuda/filters.hpp"
|
||||
#include <opencv2/cudev/ptr2d/texture.hpp>
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
__device__ __forceinline__ float lanczos_weight(float x_)
|
||||
{
|
||||
float x = fabsf(x_);
|
||||
if (x == 0.0f)
|
||||
return 1.0f;
|
||||
if (x >= 4.0f)
|
||||
return 0.0f;
|
||||
float pi_x = M_PI * x;
|
||||
return sinf(pi_x) * sinf(pi_x / 4.0f) / (pi_x * pi_x / 4.0f);
|
||||
}
|
||||
|
||||
// kernels
|
||||
template <typename T>
|
||||
__global__ void resize_lanczos4(const PtrStepSz<T> src, PtrStepSz<T> dst, const float fy, const float fx)
|
||||
{
|
||||
const int tx = threadIdx.x;
|
||||
const int ty = threadIdx.y;
|
||||
const int bx = blockIdx.x;
|
||||
const int by = blockIdx.y;
|
||||
|
||||
const int x = bx * blockDim.x + tx;
|
||||
const int y = by * blockDim.y + ty;
|
||||
|
||||
const int in_height = src.rows;
|
||||
const int in_width = src.cols;
|
||||
|
||||
constexpr int R = 4;
|
||||
constexpr int BASE_W = 32;
|
||||
constexpr int BASE_H = 8;
|
||||
constexpr int SHARED_WIDTH_MAX = BASE_W + R + R;
|
||||
constexpr int SHARED_HEIGHT_MAX = BASE_H + R + R;
|
||||
|
||||
__shared__ T shared_src[SHARED_HEIGHT_MAX][SHARED_WIDTH_MAX];
|
||||
|
||||
typedef typename VecTraits<T>::elem_type elem_type;
|
||||
constexpr int cn = VecTraits<T>::cn;
|
||||
|
||||
const int out_x0 = bx * blockDim.x;
|
||||
const int out_x1 = ::min(out_x0 + blockDim.x - 1, dst.cols - 1);
|
||||
const int out_y0 = by * blockDim.y;
|
||||
const int out_y1 = ::min(out_y0 + blockDim.y - 1, dst.rows - 1);
|
||||
|
||||
const float src_x0_f = (static_cast<float>(out_x0) + 0.5f) * fx - 0.5f;
|
||||
const float src_x1_f = (static_cast<float>(out_x1) + 0.5f) * fx - 0.5f;
|
||||
const float src_y0_f = (static_cast<float>(out_y0) + 0.5f) * fy - 0.5f;
|
||||
const float src_y1_f = (static_cast<float>(out_y1) + 0.5f) * fy - 0.5f;
|
||||
|
||||
int in_x_min = int(floorf(src_x0_f)) - R;
|
||||
int in_x_max = int(floorf(src_x1_f)) + R;
|
||||
int in_y_min = int(floorf(src_y0_f)) - R;
|
||||
int in_y_max = int(floorf(src_y1_f)) + R;
|
||||
|
||||
if (in_x_min < 0) in_x_min = 0;
|
||||
if (in_y_min < 0) in_y_min = 0;
|
||||
if (in_x_max >= in_width) in_x_max = in_width - 1;
|
||||
if (in_y_max >= in_height) in_y_max = in_height - 1;
|
||||
|
||||
const int W_needed = in_x_max - in_x_min + 1;
|
||||
const int H_needed = in_y_max - in_y_min + 1;
|
||||
|
||||
// for fx <= 1 and fy <= 1
|
||||
const bool use_shared = (W_needed <= SHARED_WIDTH_MAX) && (H_needed <= SHARED_HEIGHT_MAX);
|
||||
|
||||
if (use_shared)
|
||||
{
|
||||
for (int sy = ty; sy < H_needed; sy += blockDim.y)
|
||||
{
|
||||
int iy = in_y_min + sy;
|
||||
for (int sx = tx; sx < W_needed; sx += blockDim.x)
|
||||
{
|
||||
int ix = in_x_min + sx;
|
||||
shared_src[sy][sx] = src(iy, ix);
|
||||
}
|
||||
}
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
if (x >= dst.cols || y >= dst.rows)
|
||||
{
|
||||
if (use_shared) { __syncthreads(); }
|
||||
return;
|
||||
}
|
||||
|
||||
const float src_x = (static_cast<float>(x) + 0.5f) * fx - 0.5f;
|
||||
const float src_y = (static_cast<float>(y) + 0.5f) * fy - 0.5f;
|
||||
|
||||
const int xmin = int(floorf(src_x)) - 3;
|
||||
const int xmax = int(floorf(src_x)) + 4;
|
||||
const int ymin = int(floorf(src_y)) - 3;
|
||||
const int ymax = int(floorf(src_y)) + 4;
|
||||
|
||||
float results[cn];
|
||||
float acc_weights[cn];
|
||||
#pragma unroll
|
||||
for (int c = 0; c < cn; ++c) { results[c] = 0.0f; acc_weights[c] = 0.0f; }
|
||||
|
||||
for (int cy = ymin; cy <= ymax; ++cy)
|
||||
{
|
||||
float wy = lanczos_weight(src_y - static_cast<float>(cy));
|
||||
if (wy == 0.0f) continue;
|
||||
|
||||
for (int cx = xmin; cx <= xmax; ++cx)
|
||||
{
|
||||
float wx = lanczos_weight(src_x - static_cast<float>(cx));
|
||||
if (wx == 0.0f) continue;
|
||||
|
||||
float w = wy * wx;
|
||||
|
||||
if (use_shared)
|
||||
{
|
||||
int sx = cx - in_x_min;
|
||||
int sy = cy - in_y_min;
|
||||
if (sx < 0) sx = 0;
|
||||
else if (sx >= W_needed) sx = W_needed - 1;
|
||||
if (sy < 0) sy = 0;
|
||||
else if (sy >= H_needed) sy = H_needed - 1;
|
||||
|
||||
T val = shared_src[sy][sx];
|
||||
const elem_type* val_ptr = reinterpret_cast<const elem_type*>(&val);
|
||||
#pragma unroll
|
||||
for (int c = 0; c < cn; ++c)
|
||||
{
|
||||
elem_type elem_val = val_ptr[c];
|
||||
float channel_val = static_cast<float>(elem_val);
|
||||
results[c] += channel_val * w;
|
||||
acc_weights[c] += w;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// fallback
|
||||
int iy_r = cy < 0 ? 0 : (cy >= in_height ? (in_height - 1) : cy);
|
||||
int ix_r = cx < 0 ? 0 : (cx >= in_width ? (in_width - 1) : cx);
|
||||
T val = src(iy_r, ix_r);
|
||||
const elem_type* val_ptr = reinterpret_cast<const elem_type*>(&val);
|
||||
#pragma unroll
|
||||
for (int c = 0; c < cn; ++c)
|
||||
{
|
||||
elem_type elem_val = val_ptr[c];
|
||||
float channel_val = static_cast<float>(elem_val);
|
||||
results[c] += channel_val * w;
|
||||
acc_weights[c] += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int c = 0; c < cn; ++c)
|
||||
results[c] = acc_weights[c] > 0.0f ? (results[c] / acc_weights[c]) : 0.0f;
|
||||
|
||||
T result_vec;
|
||||
elem_type* result_ptr = reinterpret_cast<elem_type*>(&result_vec);
|
||||
|
||||
#pragma unroll
|
||||
for (int c = 0; c < cn; ++c)
|
||||
result_ptr[c] = saturate_cast<elem_type>(results[c]);
|
||||
|
||||
dst(y, x) = result_vec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T> __global__ void resize_nearest(const PtrStep<T> src, PtrStepSz<T> dst, const float fy, const float fx)
|
||||
{
|
||||
const int dst_x = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
const int dst_y = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
|
||||
if (dst_x < dst.cols && dst_y < dst.rows)
|
||||
{
|
||||
const float src_x = dst_x * fx;
|
||||
const float src_y = dst_y * fy;
|
||||
|
||||
dst(dst_y, dst_x) = src(__float2int_rz(src_y), __float2int_rz(src_x));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> __global__ void resize_linear(const PtrStepSz<T> src, PtrStepSz<T> dst, const float fy, const float fx)
|
||||
{
|
||||
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type work_type;
|
||||
|
||||
const int dst_x = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
const int dst_y = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
|
||||
if (dst_x < dst.cols && dst_y < dst.rows)
|
||||
{
|
||||
const float src_x = dst_x * fx;
|
||||
const float src_y = dst_y * fy;
|
||||
|
||||
work_type out = VecTraits<work_type>::all(0);
|
||||
|
||||
const int x1 = __float2int_rd(src_x);
|
||||
const int y1 = __float2int_rd(src_y);
|
||||
const int x2 = x1 + 1;
|
||||
const int y2 = y1 + 1;
|
||||
const int x2_read = ::min(x2, src.cols - 1);
|
||||
const int y2_read = ::min(y2, src.rows - 1);
|
||||
|
||||
T src_reg = src(y1, x1);
|
||||
out = out + src_reg * ((x2 - src_x) * (y2 - src_y));
|
||||
|
||||
src_reg = src(y1, x2_read);
|
||||
out = out + src_reg * ((src_x - x1) * (y2 - src_y));
|
||||
|
||||
src_reg = src(y2_read, x1);
|
||||
out = out + src_reg * ((x2 - src_x) * (src_y - y1));
|
||||
|
||||
src_reg = src(y2_read, x2_read);
|
||||
out = out + src_reg * ((src_x - x1) * (src_y - y1));
|
||||
|
||||
dst(dst_y, dst_x) = saturate_cast<T>(out);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Ptr2D, typename T> __global__ void resize(Ptr2D src, PtrStepSz<T> dst, const float fy, const float fx)
|
||||
{
|
||||
const int dst_x = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
const int dst_y = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
|
||||
if (dst_x < dst.cols && dst_y < dst.rows)
|
||||
{
|
||||
const float src_x = dst_x * fx;
|
||||
const float src_y = dst_y * fy;
|
||||
|
||||
dst(dst_y, dst_x) = src(src_y, src_x);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Ptr2D, typename T> __global__ void resize_area(const Ptr2D src, PtrStepSz<T> dst)
|
||||
{
|
||||
const int x = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
const int y = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
|
||||
if (x < dst.cols && y < dst.rows)
|
||||
{
|
||||
dst(y, x) = src(y, x);
|
||||
}
|
||||
}
|
||||
|
||||
// callers for nearest interpolation
|
||||
|
||||
template <typename T>
|
||||
void call_resize_nearest_glob(const PtrStepSz<T>& src, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
const dim3 block(32, 8);
|
||||
const dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
|
||||
resize_nearest<<<grid, block, 0, stream>>>(src, dst, fy, fx);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void call_resize_nearest_tex(const PtrStepSz<T>& srcWhole, int yoff, int xoff, const PtrStepSz<T>& dst, float fy, float fx)
|
||||
{
|
||||
const dim3 block(32, 8);
|
||||
const dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
if (xoff || yoff) {
|
||||
cudev::TextureOff<T> texSrcWhole(srcWhole, yoff, xoff);
|
||||
resize<cudev::TextureOffPtr<T>><<<grid, block>>>(texSrcWhole, dst, fy, fx);
|
||||
}
|
||||
else {
|
||||
cudev::Texture<T> texSrcWhole(srcWhole);
|
||||
resize<cudev::TexturePtr<T>><<<grid, block>>>(texSrcWhole, dst, fy, fx);
|
||||
}
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
// callers for linear interpolation
|
||||
|
||||
template <typename T>
|
||||
void call_resize_linear_glob(const PtrStepSz<T>& src, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
const dim3 block(32, 8);
|
||||
const dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
|
||||
resize_linear<<<grid, block, 0, stream>>>(src, dst, fy, fx);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void call_resize_linear_tex(const PtrStepSz<T>& src, const PtrStepSz<T>& srcWhole, int yoff, int xoff, const PtrStepSz<T>& dst, float fy, float fx)
|
||||
{
|
||||
const dim3 block(32, 8);
|
||||
const dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
if (srcWhole.data == src.data)
|
||||
{
|
||||
cudev::Texture<T> texSrc(src);
|
||||
LinearFilter<cudev::TexturePtr<T>> filteredSrc(texSrc);
|
||||
resize<<<grid, block>>>(filteredSrc, dst, fy, fx);
|
||||
}
|
||||
else
|
||||
{
|
||||
cudev::TextureOff<T> texSrcWhole(srcWhole, yoff, xoff);
|
||||
BrdReplicate<T> brd(src.rows, src.cols);
|
||||
BorderReader<cudev::TextureOffPtr<T>, BrdReplicate<T>> brdSrc(texSrcWhole, brd);
|
||||
LinearFilter<BorderReader<cudev::TextureOffPtr<T>, BrdReplicate<T>>> filteredSrc(brdSrc);
|
||||
resize<<<grid, block>>>(filteredSrc, dst, fy, fx);
|
||||
}
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
// callers for cubic interpolation
|
||||
|
||||
template <typename T>
|
||||
void call_resize_cubic_glob(const PtrStepSz<T>& src, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
const dim3 block(32, 8);
|
||||
const dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
|
||||
BrdReplicate<T> brd(src.rows, src.cols);
|
||||
BorderReader<PtrStep<T>, BrdReplicate<T>> brdSrc(src, brd);
|
||||
CubicFilter<BorderReader< PtrStep<T>, BrdReplicate<T>>> filteredSrc(brdSrc);
|
||||
|
||||
resize<<<grid, block, 0, stream>>>(filteredSrc, dst, fy, fx);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void call_resize_cubic_tex(const PtrStepSz<T>& src, const PtrStepSz<T>& srcWhole, int yoff, int xoff, const PtrStepSz<T>& dst, float fy, float fx)
|
||||
{
|
||||
const dim3 block(32, 8);
|
||||
const dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
if (srcWhole.data == src.data)
|
||||
{
|
||||
cudev::Texture<T> texSrc(src);
|
||||
CubicFilter<cudev::TexturePtr<T>> filteredSrc(texSrc);
|
||||
resize<<<grid, block>>>(filteredSrc, dst, fy, fx);
|
||||
}
|
||||
else
|
||||
{
|
||||
cudev::TextureOff<T> texSrcWhole(srcWhole, yoff, xoff);
|
||||
BrdReplicate<T> brd(src.rows, src.cols);
|
||||
BorderReader<cudev::TextureOffPtr<T>, BrdReplicate<T>> brdSrc(texSrcWhole, brd);
|
||||
CubicFilter<BorderReader<cudev::TextureOffPtr<T>, BrdReplicate<T>>> filteredSrc(brdSrc);
|
||||
resize<<<grid, block>>>(filteredSrc, dst, fy, fx);
|
||||
}
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
// callers for lanczos interpolation
|
||||
|
||||
template <typename T>
|
||||
void call_resize_lanczos4_glob(const PtrStepSz<T>& src, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
const dim3 block(32, 8);
|
||||
const dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
|
||||
resize_lanczos4<<<grid, block, 0, stream>>>(src, dst, fy, fx);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
template <typename Ptr2D, typename T>
|
||||
__global__ void resize_lanczos4_tex(Ptr2D src, PtrStepSz<T> dst, const float fy, const float fx)
|
||||
{
|
||||
const int x = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
const int y = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
|
||||
if (x >= dst.cols || y >= dst.rows)
|
||||
return;
|
||||
|
||||
const float src_x = (static_cast<float>(x) + 0.5f) * fx - 0.5f;
|
||||
const float src_y = (static_cast<float>(y) + 0.5f) * fy - 0.5f;
|
||||
|
||||
typedef typename VecTraits<T>::elem_type elem_type;
|
||||
constexpr int cn = VecTraits<T>::cn;
|
||||
float results[cn] = {0.0f};
|
||||
|
||||
for (int c = 0; c < cn; ++c)
|
||||
{
|
||||
float acc_val = 0.0f;
|
||||
float acc_weight = 0.0f;
|
||||
|
||||
const int xmin = int(floorf(src_x)) - 3;
|
||||
const int xmax = int(floorf(src_x)) + 4;
|
||||
const int ymin = int(floorf(src_y)) - 3;
|
||||
const int ymax = int(floorf(src_y)) + 4;
|
||||
|
||||
for (int cy = ymin; cy <= ymax; ++cy)
|
||||
{
|
||||
float wy = lanczos_weight(src_y - static_cast<float>(cy));
|
||||
if (wy == 0.0f)
|
||||
continue;
|
||||
|
||||
for (int cx = xmin; cx <= xmax; ++cx)
|
||||
{
|
||||
float wx = lanczos_weight(src_x - static_cast<float>(cx));
|
||||
if (wx == 0.0f)
|
||||
continue;
|
||||
|
||||
float w = wy * wx;
|
||||
|
||||
// Use texture memory for sampling (handles boundary automatically)
|
||||
T val = src(static_cast<float>(cy), static_cast<float>(cx));
|
||||
|
||||
const elem_type* val_ptr = reinterpret_cast<const elem_type*>(&val);
|
||||
elem_type elem_val = val_ptr[c];
|
||||
float channel_val = static_cast<float>(elem_val);
|
||||
|
||||
acc_val += channel_val * w;
|
||||
acc_weight += w;
|
||||
}
|
||||
}
|
||||
|
||||
float result = acc_weight > 0.0f ? (acc_val / acc_weight) : 0.0f;
|
||||
results[c] = result;
|
||||
}
|
||||
|
||||
T result_vec;
|
||||
elem_type* result_ptr = reinterpret_cast<elem_type*>(&result_vec);
|
||||
for (int c = 0; c < cn; ++c)
|
||||
{
|
||||
result_ptr[c] = saturate_cast<elem_type>(results[c]);
|
||||
}
|
||||
dst(y, x) = result_vec;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void call_resize_lanczos4_tex(const PtrStepSz<T>& src, const PtrStepSz<T>& srcWhole, int yoff, int xoff, const PtrStepSz<T>& dst, float fy, float fx)
|
||||
{
|
||||
const dim3 block(32, 8);
|
||||
const dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
if (srcWhole.data == src.data)
|
||||
{
|
||||
cudev::Texture<T> texSrc(src);
|
||||
resize_lanczos4_tex<cudev::TexturePtr<T>><<<grid, block>>>(texSrc, dst, fy, fx);
|
||||
}
|
||||
else
|
||||
{
|
||||
cudev::TextureOff<T> texSrcWhole(srcWhole, yoff, xoff);
|
||||
BrdReplicate<T> brd(src.rows, src.cols);
|
||||
BorderReader<cudev::TextureOffPtr<T>, BrdReplicate<T>> brdSrc(texSrcWhole, brd);
|
||||
resize_lanczos4_tex<BorderReader<cudev::TextureOffPtr<T>, BrdReplicate<T>>><<<grid, block>>>(brdSrc, dst, fy, fx);
|
||||
}
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
// ResizeNearestDispatcher
|
||||
|
||||
template <typename T> struct ResizeNearestDispatcher
|
||||
{
|
||||
static void call(const PtrStepSz<T>& src, const PtrStepSz<T>& /*srcWhole*/, int /*yoff*/, int /*xoff*/, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
call_resize_nearest_glob(src, dst, fy, fx, stream);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct SelectImplForNearest
|
||||
{
|
||||
static void call(const PtrStepSz<T>& src, const PtrStepSz<T>& srcWhole, int yoff, int xoff, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
if (stream)
|
||||
call_resize_nearest_glob(src, dst, fy, fx, stream);
|
||||
else
|
||||
{
|
||||
if (fx > 1 || fy > 1)
|
||||
call_resize_nearest_glob(src, dst, fy, fx, 0);
|
||||
else
|
||||
call_resize_nearest_tex(srcWhole, yoff, xoff, dst, fy, fx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct ResizeNearestDispatcher<uchar> : SelectImplForNearest<uchar> {};
|
||||
template <> struct ResizeNearestDispatcher<uchar4> : SelectImplForNearest<uchar4> {};
|
||||
|
||||
template <> struct ResizeNearestDispatcher<ushort> : SelectImplForNearest<ushort> {};
|
||||
template <> struct ResizeNearestDispatcher<ushort4> : SelectImplForNearest<ushort4> {};
|
||||
|
||||
template <> struct ResizeNearestDispatcher<short> : SelectImplForNearest<short> {};
|
||||
template <> struct ResizeNearestDispatcher<short4> : SelectImplForNearest<short4> {};
|
||||
|
||||
template <> struct ResizeNearestDispatcher<float> : SelectImplForNearest<float> {};
|
||||
template <> struct ResizeNearestDispatcher<float4> : SelectImplForNearest<float4> {};
|
||||
|
||||
// ResizeLinearDispatcher
|
||||
|
||||
template <typename T> struct ResizeLinearDispatcher
|
||||
{
|
||||
static void call(const PtrStepSz<T>& src, const PtrStepSz<T>& /*srcWhole*/, int /*yoff*/, int /*xoff*/, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
call_resize_linear_glob(src, dst, fy, fx, stream);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct SelectImplForLinear
|
||||
{
|
||||
static void call(const PtrStepSz<T>& src, const PtrStepSz<T>& srcWhole, int yoff, int xoff, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
if (stream)
|
||||
call_resize_linear_glob(src, dst, fy, fx, stream);
|
||||
else
|
||||
{
|
||||
if (fx > 1 || fy > 1)
|
||||
call_resize_linear_glob(src, dst, fy, fx, 0);
|
||||
else
|
||||
call_resize_linear_tex(src, srcWhole, yoff, xoff, dst, fy, fx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct ResizeLinearDispatcher<uchar> : SelectImplForLinear<uchar> {};
|
||||
template <> struct ResizeLinearDispatcher<uchar4> : SelectImplForLinear<uchar4> {};
|
||||
|
||||
template <> struct ResizeLinearDispatcher<ushort> : SelectImplForLinear<ushort> {};
|
||||
template <> struct ResizeLinearDispatcher<ushort4> : SelectImplForLinear<ushort4> {};
|
||||
|
||||
template <> struct ResizeLinearDispatcher<short> : SelectImplForLinear<short> {};
|
||||
template <> struct ResizeLinearDispatcher<short4> : SelectImplForLinear<short4> {};
|
||||
|
||||
template <> struct ResizeLinearDispatcher<float> : SelectImplForLinear<float> {};
|
||||
template <> struct ResizeLinearDispatcher<float4> : SelectImplForLinear<float4> {};
|
||||
|
||||
// ResizeCubicDispatcher
|
||||
|
||||
template <typename T> struct ResizeCubicDispatcher
|
||||
{
|
||||
static void call(const PtrStepSz<T>& src, const PtrStepSz<T>& /*srcWhole*/, int /*yoff*/, int /*xoff*/, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
call_resize_cubic_glob(src, dst, fy, fx, stream);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct SelectImplForCubic
|
||||
{
|
||||
static void call(const PtrStepSz<T>& src, const PtrStepSz<T>& srcWhole, int yoff, int xoff, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
if (stream)
|
||||
call_resize_cubic_glob(src, dst, fy, fx, stream);
|
||||
else
|
||||
call_resize_cubic_tex(src, srcWhole, yoff, xoff, dst, fy, fx);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct ResizeCubicDispatcher<uchar> : SelectImplForCubic<uchar> {};
|
||||
template <> struct ResizeCubicDispatcher<uchar4> : SelectImplForCubic<uchar4> {};
|
||||
|
||||
template <> struct ResizeCubicDispatcher<ushort> : SelectImplForCubic<ushort> {};
|
||||
template <> struct ResizeCubicDispatcher<ushort4> : SelectImplForCubic<ushort4> {};
|
||||
|
||||
template <> struct ResizeCubicDispatcher<short> : SelectImplForCubic<short> {};
|
||||
template <> struct ResizeCubicDispatcher<short4> : SelectImplForCubic<short4> {};
|
||||
|
||||
template <> struct ResizeCubicDispatcher<float> : SelectImplForCubic<float> {};
|
||||
template <> struct ResizeCubicDispatcher<float4> : SelectImplForCubic<float4> {};
|
||||
|
||||
// ResizeLanczosDispatcher
|
||||
|
||||
template <typename T> struct ResizeLanczosDispatcher
|
||||
{
|
||||
static void call(const PtrStepSz<T>& src, const PtrStepSz<T>& /*srcWhole*/, int /*yoff*/, int /*xoff*/, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
call_resize_lanczos4_glob(src, dst, fy, fx, stream);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct SelectImplForLanczos
|
||||
{
|
||||
static void call(const PtrStepSz<T>& src, const PtrStepSz<T>& srcWhole, int yoff, int xoff, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
if (stream)
|
||||
call_resize_lanczos4_glob(src, dst, fy, fx, stream);
|
||||
else
|
||||
{
|
||||
if (fx > 1 || fy > 1)
|
||||
call_resize_lanczos4_glob(src, dst, fy, fx, 0);
|
||||
else
|
||||
call_resize_lanczos4_tex(src, srcWhole, yoff, xoff, dst, fy, fx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Texture memory doesn't support 3-channel types, so use glob for those
|
||||
template <> struct ResizeLanczosDispatcher<uchar> : SelectImplForLanczos<uchar> {};
|
||||
template <> struct ResizeLanczosDispatcher<uchar3>
|
||||
{
|
||||
static void call(const PtrStepSz<uchar3>& src, const PtrStepSz<uchar3>& /*srcWhole*/, int /*yoff*/, int /*xoff*/, const PtrStepSz<uchar3>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
call_resize_lanczos4_glob(src, dst, fy, fx, stream);
|
||||
}
|
||||
};
|
||||
template <> struct ResizeLanczosDispatcher<uchar4> : SelectImplForLanczos<uchar4> {};
|
||||
|
||||
template <> struct ResizeLanczosDispatcher<ushort> : SelectImplForLanczos<ushort> {};
|
||||
template <> struct ResizeLanczosDispatcher<ushort3>
|
||||
{
|
||||
static void call(const PtrStepSz<ushort3>& src, const PtrStepSz<ushort3>& /*srcWhole*/, int /*yoff*/, int /*xoff*/, const PtrStepSz<ushort3>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
call_resize_lanczos4_glob(src, dst, fy, fx, stream);
|
||||
}
|
||||
};
|
||||
template <> struct ResizeLanczosDispatcher<ushort4> : SelectImplForLanczos<ushort4> {};
|
||||
|
||||
template <> struct ResizeLanczosDispatcher<short> : SelectImplForLanczos<short> {};
|
||||
template <> struct ResizeLanczosDispatcher<short3>
|
||||
{
|
||||
static void call(const PtrStepSz<short3>& src, const PtrStepSz<short3>& /*srcWhole*/, int /*yoff*/, int /*xoff*/, const PtrStepSz<short3>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
call_resize_lanczos4_glob(src, dst, fy, fx, stream);
|
||||
}
|
||||
};
|
||||
template <> struct ResizeLanczosDispatcher<short4> : SelectImplForLanczos<short4> {};
|
||||
|
||||
template <> struct ResizeLanczosDispatcher<float> : SelectImplForLanczos<float> {};
|
||||
template <> struct ResizeLanczosDispatcher<float3>
|
||||
{
|
||||
static void call(const PtrStepSz<float3>& src, const PtrStepSz<float3>& /*srcWhole*/, int /*yoff*/, int /*xoff*/, const PtrStepSz<float3>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
call_resize_lanczos4_glob(src, dst, fy, fx, stream);
|
||||
}
|
||||
};
|
||||
template <> struct ResizeLanczosDispatcher<float4> : SelectImplForLanczos<float4> {};
|
||||
|
||||
// ResizeAreaDispatcher
|
||||
|
||||
template <typename T> struct ResizeAreaDispatcher
|
||||
{
|
||||
static void call(const PtrStepSz<T>& src, const PtrStepSz<T>&, int, int, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream)
|
||||
{
|
||||
const int iscale_x = (int) round(fx);
|
||||
const int iscale_y = (int) round(fy);
|
||||
|
||||
const dim3 block(32, 8);
|
||||
const dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
|
||||
if (std::abs(fx - iscale_x) < FLT_MIN && std::abs(fy - iscale_y) < FLT_MIN)
|
||||
{
|
||||
BrdConstant<T> brd(src.rows, src.cols);
|
||||
BorderReader<PtrStep<T>, BrdConstant<T>> brdSrc(src, brd);
|
||||
IntegerAreaFilter<BorderReader< PtrStep<T>, BrdConstant<T>>> filteredSrc(brdSrc, fx, fy);
|
||||
|
||||
resize_area<<<grid, block, 0, stream>>>(filteredSrc, dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
BrdConstant<T> brd(src.rows, src.cols);
|
||||
BorderReader<PtrStep<T>, BrdConstant<T>> brdSrc(src, brd);
|
||||
AreaFilter<BorderReader< PtrStep<T>, BrdConstant<T>>> filteredSrc(brdSrc, fx, fy);
|
||||
|
||||
resize_area<<<grid, block, 0, stream>>>(filteredSrc, dst);
|
||||
}
|
||||
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
};
|
||||
|
||||
// resize
|
||||
|
||||
template <typename T> void resize(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream)
|
||||
{
|
||||
typedef void (*func_t)(const PtrStepSz<T>& src, const PtrStepSz<T>& srcWhole, int yoff, int xoff, const PtrStepSz<T>& dst, float fy, float fx, cudaStream_t stream);
|
||||
static const func_t funcs[5] =
|
||||
{
|
||||
ResizeNearestDispatcher<T>::call,
|
||||
ResizeLinearDispatcher<T>::call,
|
||||
ResizeCubicDispatcher<T>::call,
|
||||
ResizeAreaDispatcher<T>::call,
|
||||
ResizeLanczosDispatcher<T>::call
|
||||
};
|
||||
|
||||
// change to linear if area interpolation upscaling
|
||||
if (interpolation == 3 && (fx <= 1.f || fy <= 1.f))
|
||||
interpolation = 1;
|
||||
|
||||
// Bounds check for interpolation mode
|
||||
CV_Assert(interpolation >= 0 && interpolation < 5);
|
||||
|
||||
funcs[interpolation](static_cast< PtrStepSz<T> >(src), static_cast< PtrStepSz<T> >(srcWhole), yoff, xoff, static_cast< PtrStepSz<T> >(dst), fy, fx, stream);
|
||||
}
|
||||
|
||||
template void resize<uchar >(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
template void resize<uchar3>(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
template void resize<uchar4>(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
|
||||
template void resize<ushort >(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
template void resize<ushort3>(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
template void resize<ushort4>(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
|
||||
template void resize<short >(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
template void resize<short3>(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
template void resize<short4>(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
|
||||
template void resize<float >(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
template void resize<float3>(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
template void resize<float4>(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
}}}
|
||||
|
||||
#endif /* CUDA_DISABLER */
|
||||
@@ -0,0 +1,336 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#if !defined CUDA_DISABLER
|
||||
|
||||
#include "opencv2/core/cuda/common.hpp"
|
||||
#include "opencv2/core/cuda/border_interpolate.hpp"
|
||||
#include "opencv2/core/cuda/vec_traits.hpp"
|
||||
#include "opencv2/core/cuda/vec_math.hpp"
|
||||
#include "opencv2/core/cuda/saturate_cast.hpp"
|
||||
#include "opencv2/core/cuda/filters.hpp"
|
||||
#include <opencv2/cudev/ptr2d/texture.hpp>
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
struct AffineTransform
|
||||
{
|
||||
static const int rows = 2;
|
||||
static __device__ __forceinline__ float2 calcCoord(const float warpMat[AffineTransform::rows * 3], int x, int y)
|
||||
{
|
||||
const float xcoo = warpMat[0] * x + warpMat[1] * y + warpMat[2];
|
||||
const float ycoo = warpMat[3] * x + warpMat[4] * y + warpMat[5];
|
||||
|
||||
return make_float2(xcoo, ycoo);
|
||||
}
|
||||
|
||||
struct Coefficients
|
||||
{
|
||||
Coefficients(const float* c_)
|
||||
{
|
||||
for(int i = 0; i < AffineTransform::rows * 3; i++)
|
||||
c[i] = c_[i];
|
||||
}
|
||||
float c[AffineTransform::rows * 3];
|
||||
};
|
||||
};
|
||||
|
||||
struct PerspectiveTransform
|
||||
{
|
||||
static const int rows = 3;
|
||||
static __device__ __forceinline__ float2 calcCoord(const float warpMat[PerspectiveTransform::rows * 3], int x, int y)
|
||||
{
|
||||
const float coeff = 1.0f / (warpMat[6] * x + warpMat[7] * y + warpMat[8]);
|
||||
|
||||
const float xcoo = coeff * (warpMat[0] * x + warpMat[1] * y + warpMat[2]);
|
||||
const float ycoo = coeff * (warpMat[3] * x + warpMat[4] * y + warpMat[5]);
|
||||
|
||||
return make_float2(xcoo, ycoo);
|
||||
}
|
||||
struct Coefficients
|
||||
{
|
||||
Coefficients(const float* c_)
|
||||
{
|
||||
for(int i = 0; i < PerspectiveTransform::rows * 3; i++)
|
||||
c[i] = c_[i];
|
||||
}
|
||||
|
||||
float c[PerspectiveTransform::rows * 3];
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Build Maps
|
||||
|
||||
template <class Transform> __global__ void buildWarpMaps(PtrStepSzf xmap, PtrStepf ymap, const typename Transform::Coefficients warpMat)
|
||||
{
|
||||
const int x = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
const int y = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
|
||||
if (x < xmap.cols && y < xmap.rows)
|
||||
{
|
||||
const float2 coord = Transform::calcCoord(warpMat.c, x, y);
|
||||
|
||||
xmap(y, x) = coord.x;
|
||||
ymap(y, x) = coord.y;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Transform> void buildWarpMaps_caller(PtrStepSzf xmap, PtrStepSzf ymap, const float warpMat[Transform::rows * 3], cudaStream_t stream)
|
||||
{
|
||||
dim3 block(32, 8);
|
||||
dim3 grid(divUp(xmap.cols, block.x), divUp(xmap.rows, block.y));
|
||||
|
||||
buildWarpMaps<Transform><<<grid, block, 0, stream>>>(xmap, ymap, warpMat);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
void buildWarpAffineMaps_gpu(float coeffs[2 * 3], PtrStepSzf xmap, PtrStepSzf ymap, cudaStream_t stream)
|
||||
{
|
||||
buildWarpMaps_caller<AffineTransform>(xmap, ymap, coeffs, stream);
|
||||
}
|
||||
|
||||
void buildWarpPerspectiveMaps_gpu(float coeffs[3 * 3], PtrStepSzf xmap, PtrStepSzf ymap, cudaStream_t stream)
|
||||
{
|
||||
buildWarpMaps_caller<PerspectiveTransform>(xmap, ymap, coeffs, stream);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Warp
|
||||
|
||||
template <class Transform, class Ptr2D, typename T> __global__ void warp(const Ptr2D src, PtrStepSz<T> dst, const typename Transform::Coefficients warpMat)
|
||||
{
|
||||
const int x = blockDim.x * blockIdx.x + threadIdx.x;
|
||||
const int y = blockDim.y * blockIdx.y + threadIdx.y;
|
||||
|
||||
if (x < dst.cols && y < dst.rows)
|
||||
{
|
||||
const float2 coord = Transform::calcCoord(warpMat.c, x, y);
|
||||
|
||||
dst.ptr(y)[x] = saturate_cast<T>(src(coord.y, coord.x));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Transform, template <typename> class Filter, template <typename> class B, typename T> struct WarpDispatcherStream
|
||||
{
|
||||
static void call(PtrStepSz<T> src, PtrStepSz<T> dst, const float* borderValue, const float warpMat[Transform::rows*3], cudaStream_t stream, bool)
|
||||
{
|
||||
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type work_type;
|
||||
|
||||
dim3 block(32, 8);
|
||||
dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
|
||||
B<work_type> brd(src.rows, src.cols, VecTraits<work_type>::make(borderValue));
|
||||
BorderReader<PtrStep<T>, B<work_type>> brdSrc(src, brd);
|
||||
Filter<BorderReader<PtrStep<T>, B<work_type>>> filter_src(brdSrc);
|
||||
|
||||
warp<Transform><<<grid, block, 0, stream>>>(filter_src, dst, warpMat);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
}
|
||||
};
|
||||
|
||||
template <class Transform, template <typename> class Filter, template <typename> class B, typename T> struct WarpDispatcherNonStream
|
||||
{
|
||||
static void call(PtrStepSz<T> src, PtrStepSz<T> srcWhole, int xoff, int yoff, PtrStepSz<T> dst, const float* borderValue, const float warpMat[Transform::rows*3], bool)
|
||||
{
|
||||
CV_UNUSED(xoff);
|
||||
CV_UNUSED(yoff);
|
||||
CV_UNUSED(srcWhole);
|
||||
|
||||
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type work_type;
|
||||
|
||||
dim3 block(32, 8);
|
||||
dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
|
||||
B<work_type> brd(src.rows, src.cols, VecTraits<work_type>::make(borderValue));
|
||||
BorderReader<PtrStep<T>, B<work_type>> brdSrc(src, brd);
|
||||
Filter<BorderReader<PtrStep<T>, B<work_type>>> filter_src(brdSrc);
|
||||
|
||||
warp<Transform><<<grid, block>>>(filter_src, dst, warpMat);
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
};
|
||||
|
||||
template <class Transform, template <typename> class Filter, template <typename> class B, typename T> struct WarpDispatcherNonStreamTex
|
||||
{
|
||||
static void call(PtrStepSz<T> src, PtrStepSz<T> srcWhole, int xoff, int yoff, PtrStepSz<T> dst, const float* borderValue, const float warpMat[Transform::rows*3], bool cc20)
|
||||
{
|
||||
typedef typename TypeVec<float, VecTraits<T>::cn>::vec_type work_type;
|
||||
dim3 block(32, cc20 ? 8 : 4);
|
||||
dim3 grid(divUp(dst.cols, block.x), divUp(dst.rows, block.y));
|
||||
if (xoff || yoff) {
|
||||
cudev::TextureOff<T> texSrcWhole(srcWhole, yoff, xoff);
|
||||
B<work_type> brd(src.rows, src.cols, VecTraits<work_type>::make(borderValue));
|
||||
BorderReader<cudev::TextureOffPtr<T>, B<work_type>> brdSrc(texSrcWhole, brd);
|
||||
Filter<BorderReader<cudev::TextureOffPtr<T>, B<work_type>>> filter_src(brdSrc);
|
||||
warp<Transform><<<grid, block>>> (filter_src, dst, warpMat);
|
||||
}
|
||||
else {
|
||||
cudev::Texture<T> texSrcWhole(srcWhole);
|
||||
B<work_type> brd(src.rows, src.cols, VecTraits<work_type>::make(borderValue));
|
||||
BorderReader<cudev::TexturePtr<T>, B<work_type>>brdSrc(texSrcWhole, brd);
|
||||
Filter< BorderReader<cudev::TexturePtr<T>, B<work_type>>> filter_src(brdSrc);
|
||||
warp<Transform><<<grid, block>>> (filter_src, dst, warpMat);
|
||||
}
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
};
|
||||
|
||||
template <class Transform, template <typename> class Filter, template <typename> class B> struct WarpDispatcherNonStream<Transform, Filter, B, uchar> :
|
||||
WarpDispatcherNonStreamTex<Transform, Filter, B, uchar> {};
|
||||
template <class Transform, template <typename> class Filter, template <typename> class B> struct WarpDispatcherNonStream<Transform, Filter, B, uchar4> :
|
||||
WarpDispatcherNonStreamTex<Transform, Filter, B, uchar4> {};
|
||||
template <class Transform, template <typename> class Filter, template <typename> class B> struct WarpDispatcherNonStream<Transform, Filter, B, ushort> :
|
||||
WarpDispatcherNonStreamTex<Transform, Filter, B, ushort> {};
|
||||
template <class Transform, template <typename> class Filter, template <typename> class B> struct WarpDispatcherNonStream<Transform, Filter, B, ushort4> :
|
||||
WarpDispatcherNonStreamTex<Transform, Filter, B, ushort4> {};
|
||||
template <class Transform, template <typename> class Filter, template <typename> class B> struct WarpDispatcherNonStream<Transform, Filter, B, short> :
|
||||
WarpDispatcherNonStreamTex<Transform, Filter, B, short> {};
|
||||
template <class Transform, template <typename> class Filter, template <typename> class B> struct WarpDispatcherNonStream<Transform, Filter, B, short4> :
|
||||
WarpDispatcherNonStreamTex<Transform, Filter, B, short4> {};
|
||||
template <class Transform, template <typename> class Filter, template <typename> class B> struct WarpDispatcherNonStream<Transform, Filter, B, float> :
|
||||
WarpDispatcherNonStreamTex<Transform, Filter, B, float> {};
|
||||
template <class Transform, template <typename> class Filter, template <typename> class B> struct WarpDispatcherNonStream<Transform, Filter, B, float4> :
|
||||
WarpDispatcherNonStreamTex<Transform, Filter, B, float4> {};
|
||||
|
||||
template <class Transform, template <typename> class Filter, template <typename> class B, typename T> struct WarpDispatcher
|
||||
{
|
||||
static void call(PtrStepSz<T> src, PtrStepSz<T> srcWhole, int xoff, int yoff, PtrStepSz<T> dst, const float* borderValue, const float warpMat[Transform::rows*3], cudaStream_t stream, bool cc20)
|
||||
{
|
||||
if (stream == 0)
|
||||
WarpDispatcherNonStream<Transform, Filter, B, T>::call(src, srcWhole, xoff, yoff, dst, borderValue, warpMat, cc20);
|
||||
else
|
||||
WarpDispatcherStream<Transform, Filter, B, T>::call(src, dst, borderValue, warpMat, stream, cc20);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Transform, typename T>
|
||||
void warp_caller(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzb dst, int interpolation,
|
||||
int borderMode, const float* borderValue, const float warpMat[Transform::rows*3], cudaStream_t stream, bool cc20)
|
||||
{
|
||||
typedef void (*func_t)(PtrStepSz<T> src, PtrStepSz<T> srcWhole, int xoff, int yoff, PtrStepSz<T> dst, const float* borderValue, const float warpMat[Transform::rows*3], cudaStream_t stream, bool cc20);
|
||||
|
||||
static const func_t funcs[3][5] =
|
||||
{
|
||||
{
|
||||
WarpDispatcher<Transform, PointFilter, BrdConstant, T>::call,
|
||||
WarpDispatcher<Transform, PointFilter, BrdReplicate, T>::call,
|
||||
WarpDispatcher<Transform, PointFilter, BrdReflect, T>::call,
|
||||
WarpDispatcher<Transform, PointFilter, BrdWrap, T>::call,
|
||||
WarpDispatcher<Transform, PointFilter, BrdReflect101, T>::call
|
||||
},
|
||||
{
|
||||
WarpDispatcher<Transform, LinearFilter, BrdConstant, T>::call,
|
||||
WarpDispatcher<Transform, LinearFilter, BrdReplicate, T>::call,
|
||||
WarpDispatcher<Transform, LinearFilter, BrdReflect, T>::call,
|
||||
WarpDispatcher<Transform, LinearFilter, BrdWrap, T>::call,
|
||||
WarpDispatcher<Transform, LinearFilter, BrdReflect101, T>::call
|
||||
},
|
||||
{
|
||||
WarpDispatcher<Transform, CubicFilter, BrdConstant, T>::call,
|
||||
WarpDispatcher<Transform, CubicFilter, BrdReplicate, T>::call,
|
||||
WarpDispatcher<Transform, CubicFilter, BrdReflect, T>::call,
|
||||
WarpDispatcher<Transform, CubicFilter, BrdWrap, T>::call,
|
||||
WarpDispatcher<Transform, CubicFilter, BrdReflect101, T>::call
|
||||
}
|
||||
};
|
||||
|
||||
funcs[interpolation][borderMode](static_cast<PtrStepSz<T>>(src), static_cast<PtrStepSz<T>>(srcWhole), xoff, yoff,
|
||||
static_cast<PtrStepSz<T>>(dst), borderValue, warpMat, stream, cc20);
|
||||
}
|
||||
|
||||
template <typename T> void warpAffine_gpu(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation,
|
||||
int borderMode, const float* borderValue, cudaStream_t stream, bool cc20)
|
||||
{
|
||||
warp_caller<AffineTransform, T>(src, srcWhole, xoff, yoff, dst, interpolation, borderMode, borderValue, coeffs, stream, cc20);
|
||||
}
|
||||
|
||||
template void warpAffine_gpu<uchar >(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpAffine_gpu<uchar3>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpAffine_gpu<uchar4>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
|
||||
template void warpAffine_gpu<ushort >(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpAffine_gpu<ushort3>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpAffine_gpu<ushort4>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
|
||||
template void warpAffine_gpu<short >(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpAffine_gpu<short3>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpAffine_gpu<short4>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
|
||||
template void warpAffine_gpu<float >(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpAffine_gpu<float3>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpAffine_gpu<float4>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
|
||||
template <typename T> void warpPerspective_gpu(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation,
|
||||
int borderMode, const float* borderValue, cudaStream_t stream, bool cc20)
|
||||
{
|
||||
warp_caller<PerspectiveTransform, T>(src, srcWhole, xoff, yoff, dst, interpolation, borderMode, borderValue, coeffs, stream, cc20);
|
||||
}
|
||||
|
||||
template void warpPerspective_gpu<uchar >(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpPerspective_gpu<uchar3>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpPerspective_gpu<uchar4>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
|
||||
template void warpPerspective_gpu<ushort >(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpPerspective_gpu<ushort3>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpPerspective_gpu<ushort4>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
|
||||
template void warpPerspective_gpu<short >(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpPerspective_gpu<short3>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpPerspective_gpu<short4>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
|
||||
template void warpPerspective_gpu<float >(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpPerspective_gpu<float3>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
template void warpPerspective_gpu<float4>(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
} // namespace imgproc
|
||||
}}} // namespace cv { namespace cuda { namespace cudev
|
||||
|
||||
|
||||
#endif /* CUDA_DISABLER */
|
||||
@@ -0,0 +1,51 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_PRECOMP_H__
|
||||
#define __OPENCV_PRECOMP_H__
|
||||
|
||||
#include "opencv2/geometry.hpp"
|
||||
#include "opencv2/cudawarping.hpp"
|
||||
|
||||
#include "opencv2/core/private.cuda.hpp"
|
||||
|
||||
#endif /* __OPENCV_PRECOMP_H__ */
|
||||
@@ -0,0 +1,134 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::cuda;
|
||||
|
||||
#if !defined HAVE_CUDA || defined(CUDA_DISABLER)
|
||||
|
||||
void cv::cuda::pyrDown(InputArray, OutputArray, Stream&) { throw_no_cuda(); }
|
||||
void cv::cuda::pyrUp(InputArray, OutputArray, Stream&) { throw_no_cuda(); }
|
||||
|
||||
#else // HAVE_CUDA
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// pyrDown
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
template <typename T> void pyrDown_gpu(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
}
|
||||
}}}
|
||||
|
||||
void cv::cuda::pyrDown(InputArray _src, OutputArray _dst, Stream& stream)
|
||||
{
|
||||
using namespace cv::cuda::device::imgproc;
|
||||
|
||||
typedef void (*func_t)(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
static const func_t funcs[6][4] =
|
||||
{
|
||||
{pyrDown_gpu<uchar> , 0 /*pyrDown_gpu<uchar2>*/ , pyrDown_gpu<uchar3> , pyrDown_gpu<uchar4> },
|
||||
{0 /*pyrDown_gpu<schar>*/, 0 /*pyrDown_gpu<schar2>*/ , 0 /*pyrDown_gpu<schar3>*/, 0 /*pyrDown_gpu<schar4>*/},
|
||||
{pyrDown_gpu<ushort> , 0 /*pyrDown_gpu<ushort2>*/, pyrDown_gpu<ushort3> , pyrDown_gpu<ushort4> },
|
||||
{pyrDown_gpu<short> , 0 /*pyrDown_gpu<short2>*/ , pyrDown_gpu<short3> , pyrDown_gpu<short4> },
|
||||
{pyrDown_gpu<int> , 0 /*pyrDown_gpu<int2>*/ , pyrDown_gpu<int3> , pyrDown_gpu<int4> },
|
||||
{pyrDown_gpu<float> , 0 /*pyrDown_gpu<float2>*/ , pyrDown_gpu<float3> , pyrDown_gpu<float4> }
|
||||
};
|
||||
|
||||
GpuMat src = _src.getGpuMat();
|
||||
|
||||
CV_Assert( src.depth() <= CV_32F && src.channels() <= 4 );
|
||||
|
||||
const func_t func = funcs[src.depth()][src.channels() - 1];
|
||||
CV_Assert( func != 0 );
|
||||
|
||||
_dst.create((src.rows + 1) / 2, (src.cols + 1) / 2, src.type());
|
||||
GpuMat dst = _dst.getGpuMat();
|
||||
|
||||
func(src, dst, StreamAccessor::getStream(stream));
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// pyrUp
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
template <typename T> void pyrUp_gpu(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
}
|
||||
}}}
|
||||
|
||||
void cv::cuda::pyrUp(InputArray _src, OutputArray _dst, Stream& stream)
|
||||
{
|
||||
using namespace cv::cuda::device::imgproc;
|
||||
|
||||
typedef void (*func_t)(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream);
|
||||
static const func_t funcs[6][4] =
|
||||
{
|
||||
{pyrUp_gpu<uchar> , 0 /*pyrUp_gpu<uchar2>*/ , pyrUp_gpu<uchar3> , pyrUp_gpu<uchar4> },
|
||||
{0 /*pyrUp_gpu<schar>*/, 0 /*pyrUp_gpu<schar2>*/ , 0 /*pyrUp_gpu<schar3>*/, 0 /*pyrUp_gpu<schar4>*/},
|
||||
{pyrUp_gpu<ushort> , 0 /*pyrUp_gpu<ushort2>*/, pyrUp_gpu<ushort3> , pyrUp_gpu<ushort4> },
|
||||
{pyrUp_gpu<short> , 0 /*pyrUp_gpu<short2>*/ , pyrUp_gpu<short3> , pyrUp_gpu<short4> },
|
||||
{0 /*pyrUp_gpu<int>*/ , 0 /*pyrUp_gpu<int2>*/ , 0 /*pyrUp_gpu<int3>*/ , 0 /*pyrUp_gpu<int4>*/ },
|
||||
{pyrUp_gpu<float> , 0 /*pyrUp_gpu<float2>*/ , pyrUp_gpu<float3> , pyrUp_gpu<float4> }
|
||||
};
|
||||
|
||||
GpuMat src = _src.getGpuMat();
|
||||
|
||||
CV_Assert( src.depth() <= CV_32F && src.channels() <= 4 );
|
||||
|
||||
const func_t func = funcs[src.depth()][src.channels() - 1];
|
||||
CV_Assert( func != 0 );
|
||||
|
||||
_dst.create(src.rows * 2, src.cols * 2, src.type());
|
||||
GpuMat dst = _dst.getGpuMat();
|
||||
|
||||
func(src, dst, StreamAccessor::getStream(stream));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,107 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#if !defined HAVE_CUDA || defined(CUDA_DISABLER)
|
||||
|
||||
void cv::cuda::remap(InputArray, OutputArray, InputArray, InputArray, int, int, Scalar, Stream&){ throw_no_cuda(); }
|
||||
|
||||
#else // HAVE_CUDA
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
template <typename T>
|
||||
void remap_gpu(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst,
|
||||
int interpolation, int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
}
|
||||
}}}
|
||||
|
||||
void cv::cuda::remap(InputArray _src, OutputArray _dst, InputArray _xmap, InputArray _ymap, int interpolation, int borderMode, Scalar borderValue, Stream& stream)
|
||||
{
|
||||
using namespace cv::cuda::device::imgproc;
|
||||
|
||||
const bool hasRelativeFlag = ((interpolation & WARP_RELATIVE_MAP) != 0);
|
||||
interpolation &= ~WARP_RELATIVE_MAP;
|
||||
|
||||
typedef void (*func_t)(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, PtrStepSzf xmap, PtrStepSzf ymap, PtrStepSzb dst, int interpolation,
|
||||
int borderMode, const float* borderValue, cudaStream_t stream, bool cc20, bool isRelative);
|
||||
static const func_t funcs[6][4] =
|
||||
{
|
||||
{remap_gpu<uchar> , 0 /*remap_gpu<uchar2>*/ , remap_gpu<uchar3> , remap_gpu<uchar4> },
|
||||
{0 /*remap_gpu<schar>*/, 0 /*remap_gpu<char2>*/ , 0 /*remap_gpu<char3>*/, 0 /*remap_gpu<char4>*/},
|
||||
{remap_gpu<ushort> , 0 /*remap_gpu<ushort2>*/, remap_gpu<ushort3> , remap_gpu<ushort4> },
|
||||
{remap_gpu<short> , 0 /*remap_gpu<short2>*/ , remap_gpu<short3> , remap_gpu<short4> },
|
||||
{0 /*remap_gpu<int>*/ , 0 /*remap_gpu<int2>*/ , 0 /*remap_gpu<int3>*/ , 0 /*remap_gpu<int4>*/ },
|
||||
{remap_gpu<float> , 0 /*remap_gpu<float2>*/ , remap_gpu<float3> , remap_gpu<float4> }
|
||||
};
|
||||
|
||||
GpuMat src = _src.getGpuMat();
|
||||
GpuMat xmap = _xmap.getGpuMat();
|
||||
GpuMat ymap = _ymap.getGpuMat();
|
||||
|
||||
CV_Assert( src.depth() <= CV_32F && src.channels() <= 4 );
|
||||
CV_Assert( xmap.type() == CV_32F && ymap.type() == CV_32F && xmap.size() == ymap.size() );
|
||||
CV_Assert( interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC );
|
||||
CV_Assert( borderMode == BORDER_REFLECT101 || borderMode == BORDER_REPLICATE || borderMode == BORDER_CONSTANT || borderMode == BORDER_REFLECT || borderMode == BORDER_WRAP );
|
||||
|
||||
const func_t func = funcs[src.depth()][src.channels() - 1];
|
||||
if (!func)
|
||||
CV_Error(Error::StsUnsupportedFormat, "Unsupported input type");
|
||||
|
||||
_dst.create(xmap.size(), src.type());
|
||||
GpuMat dst = _dst.getGpuMat();
|
||||
|
||||
Scalar_<float> borderValueFloat;
|
||||
borderValueFloat = borderValue;
|
||||
|
||||
Size wholeSize;
|
||||
Point ofs;
|
||||
src.locateROI(wholeSize, ofs);
|
||||
|
||||
func(src, PtrStepSzb(wholeSize.height, wholeSize.width, src.datastart, src.step), ofs.x, ofs.y, xmap, ymap,
|
||||
dst, interpolation, borderMode, borderValueFloat.val, StreamAccessor::getStream(stream), deviceSupports(FEATURE_SET_COMPUTE_20), hasRelativeFlag);
|
||||
}
|
||||
|
||||
#endif // HAVE_CUDA
|
||||
@@ -0,0 +1,108 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#if !defined HAVE_CUDA || defined(CUDA_DISABLER)
|
||||
|
||||
void cv::cuda::resize(InputArray, OutputArray, Size, double, double, int, Stream&) { throw_no_cuda(); }
|
||||
|
||||
#else // HAVE_CUDA
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
template <typename T>
|
||||
void resize(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
}}}
|
||||
|
||||
void cv::cuda::resize(InputArray _src, OutputArray _dst, Size dsize, double fx, double fy, int interpolation, Stream& stream)
|
||||
{
|
||||
GpuMat src = _src.getGpuMat();
|
||||
|
||||
typedef void (*func_t)(const PtrStepSzb& src, const PtrStepSzb& srcWhole, int yoff, int xoff, const PtrStepSzb& dst, float fy, float fx, int interpolation, cudaStream_t stream);
|
||||
static const func_t funcs[6][4] =
|
||||
{
|
||||
{device::resize<uchar> , 0 /*device::resize<uchar2>*/ , device::resize<uchar3> , device::resize<uchar4> },
|
||||
{0 /*device::resize<schar>*/, 0 /*device::resize<char2>*/ , 0 /*device::resize<char3>*/, 0 /*device::resize<char4>*/},
|
||||
{device::resize<ushort> , 0 /*device::resize<ushort2>*/, device::resize<ushort3> , device::resize<ushort4> },
|
||||
{device::resize<short> , 0 /*device::resize<short2>*/ , device::resize<short3> , device::resize<short4> },
|
||||
{0 /*device::resize<int>*/ , 0 /*device::resize<int2>*/ , 0 /*device::resize<int3>*/ , 0 /*device::resize<int4>*/ },
|
||||
{device::resize<float> , 0 /*device::resize<float2>*/ , device::resize<float3> , device::resize<float4> }
|
||||
};
|
||||
|
||||
CV_Assert( src.depth() <= CV_32F && src.channels() <= 4 );
|
||||
CV_Assert( interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC || interpolation == INTER_AREA || interpolation == INTER_LANCZOS4 );
|
||||
CV_Assert( !(dsize == Size()) || (fx > 0 && fy > 0) );
|
||||
|
||||
if (dsize == Size())
|
||||
{
|
||||
dsize = Size(saturate_cast<int>(src.cols * fx), saturate_cast<int>(src.rows * fy));
|
||||
}
|
||||
else
|
||||
{
|
||||
fx = static_cast<double>(dsize.width) / src.cols;
|
||||
fy = static_cast<double>(dsize.height) / src.rows;
|
||||
}
|
||||
|
||||
_dst.create(dsize, src.type());
|
||||
GpuMat dst = _dst.getGpuMat();
|
||||
|
||||
if (dsize == src.size())
|
||||
{
|
||||
src.copyTo(dst, stream);
|
||||
return;
|
||||
}
|
||||
|
||||
const func_t func = funcs[src.depth()][src.channels() - 1];
|
||||
|
||||
if (!func)
|
||||
CV_Error(Error::StsUnsupportedFormat, "Unsupported combination of source and destination types");
|
||||
|
||||
Size wholeSize;
|
||||
Point ofs;
|
||||
src.locateROI(wholeSize, ofs);
|
||||
PtrStepSzb wholeSrc(wholeSize.height, wholeSize.width, src.datastart, src.step);
|
||||
|
||||
func(src, wholeSrc, ofs.y, ofs.x, dst, static_cast<float>(1.0 / fy), static_cast<float>(1.0 / fx), interpolation, StreamAccessor::getStream(stream));
|
||||
}
|
||||
|
||||
#endif // HAVE_CUDA
|
||||
@@ -0,0 +1,606 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::cuda;
|
||||
|
||||
#if !defined HAVE_CUDA || defined(CUDA_DISABLER)
|
||||
|
||||
void cv::cuda::warpAffine(InputArray, OutputArray, InputArray, Size, int, int, Scalar, Stream&) { throw_no_cuda(); }
|
||||
void cv::cuda::buildWarpAffineMaps(InputArray, bool, Size, OutputArray, OutputArray, Stream&) { throw_no_cuda(); }
|
||||
|
||||
void cv::cuda::warpPerspective(InputArray, OutputArray, InputArray, Size, int, int, Scalar, Stream&) { throw_no_cuda(); }
|
||||
void cv::cuda::buildWarpPerspectiveMaps(InputArray, bool, Size, OutputArray, OutputArray, Stream&) { throw_no_cuda(); }
|
||||
|
||||
void cv::cuda::rotate(InputArray, OutputArray, Size, double, double, double, int, Stream&) { throw_no_cuda(); }
|
||||
|
||||
#else // HAVE_CUDA
|
||||
|
||||
namespace cv { namespace cuda { namespace device
|
||||
{
|
||||
namespace imgproc
|
||||
{
|
||||
void buildWarpAffineMaps_gpu(float coeffs[2 * 3], PtrStepSzf xmap, PtrStepSzf ymap, cudaStream_t stream);
|
||||
|
||||
template <typename T>
|
||||
void warpAffine_gpu(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation,
|
||||
int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
|
||||
void buildWarpPerspectiveMaps_gpu(float coeffs[3 * 3], PtrStepSzf xmap, PtrStepSzf ymap, cudaStream_t stream);
|
||||
|
||||
template <typename T>
|
||||
void warpPerspective_gpu(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[3 * 3], PtrStepSzb dst, int interpolation,
|
||||
int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
}
|
||||
}}}
|
||||
|
||||
void cv::cuda::buildWarpAffineMaps(InputArray _M, bool inverse, Size dsize, OutputArray _xmap, OutputArray _ymap, Stream& stream)
|
||||
{
|
||||
using namespace cv::cuda::device::imgproc;
|
||||
|
||||
Mat M = _M.getMat();
|
||||
|
||||
CV_Assert( M.rows == 2 && M.cols == 3 );
|
||||
|
||||
_xmap.create(dsize, CV_32FC1);
|
||||
_ymap.create(dsize, CV_32FC1);
|
||||
|
||||
GpuMat xmap = _xmap.getGpuMat();
|
||||
GpuMat ymap = _ymap.getGpuMat();
|
||||
|
||||
float coeffs[2 * 3];
|
||||
Mat coeffsMat(2, 3, CV_32F, (void*)coeffs);
|
||||
|
||||
if (inverse)
|
||||
M.convertTo(coeffsMat, coeffsMat.type());
|
||||
else
|
||||
{
|
||||
cv::Mat iM;
|
||||
invertAffineTransform(M, iM);
|
||||
iM.convertTo(coeffsMat, coeffsMat.type());
|
||||
}
|
||||
|
||||
buildWarpAffineMaps_gpu(coeffs, xmap, ymap, StreamAccessor::getStream(stream));
|
||||
}
|
||||
|
||||
void cv::cuda::buildWarpPerspectiveMaps(InputArray _M, bool inverse, Size dsize, OutputArray _xmap, OutputArray _ymap, Stream& stream)
|
||||
{
|
||||
using namespace cv::cuda::device::imgproc;
|
||||
|
||||
Mat M = _M.getMat();
|
||||
|
||||
CV_Assert( M.rows == 3 && M.cols == 3 );
|
||||
|
||||
_xmap.create(dsize, CV_32FC1);
|
||||
_ymap.create(dsize, CV_32FC1);
|
||||
|
||||
GpuMat xmap = _xmap.getGpuMat();
|
||||
GpuMat ymap = _ymap.getGpuMat();
|
||||
|
||||
float coeffs[3 * 3];
|
||||
Mat coeffsMat(3, 3, CV_32F, (void*)coeffs);
|
||||
|
||||
if (inverse)
|
||||
M.convertTo(coeffsMat, coeffsMat.type());
|
||||
else
|
||||
{
|
||||
cv::Mat iM;
|
||||
invert(M, iM);
|
||||
iM.convertTo(coeffsMat, coeffsMat.type());
|
||||
}
|
||||
|
||||
buildWarpPerspectiveMaps_gpu(coeffs, xmap, ymap, StreamAccessor::getStream(stream));
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
template <int DEPTH> struct NppWarpFunc
|
||||
{
|
||||
typedef typename NPPTypeTraits<DEPTH>::npp_type npp_type;
|
||||
|
||||
#if USE_NPP_STREAM_CTX
|
||||
typedef NppStatus(*func_t)(const npp_type* pSrc, NppiSize srcSize, int srcStep, NppiRect srcRoi, npp_type* pDst,
|
||||
int dstStep, NppiRect dstRoi, const double coeffs[][3],
|
||||
int interpolation, NppStreamContext ctx);
|
||||
#else
|
||||
typedef NppStatus (*func_t)(const npp_type* pSrc, NppiSize srcSize, int srcStep, NppiRect srcRoi, npp_type* pDst,
|
||||
int dstStep, NppiRect dstRoi, const double coeffs[][3],
|
||||
int interpolation);
|
||||
#endif
|
||||
};
|
||||
|
||||
template <int DEPTH, typename NppWarpFunc<DEPTH>::func_t func> struct NppWarp
|
||||
{
|
||||
typedef typename NppWarpFunc<DEPTH>::npp_type npp_type;
|
||||
|
||||
static void call(const cv::cuda::GpuMat& src, cv::cuda::GpuMat& dst, double coeffs[][3], int interpolation, cudaStream_t stream)
|
||||
{
|
||||
static const int npp_inter[] = {NPPI_INTER_NN, NPPI_INTER_LINEAR, NPPI_INTER_CUBIC};
|
||||
|
||||
NppiSize srcsz;
|
||||
srcsz.height = src.rows;
|
||||
srcsz.width = src.cols;
|
||||
|
||||
NppiRect srcroi;
|
||||
srcroi.x = 0;
|
||||
srcroi.y = 0;
|
||||
srcroi.height = src.rows;
|
||||
srcroi.width = src.cols;
|
||||
|
||||
NppiRect dstroi;
|
||||
dstroi.x = 0;
|
||||
dstroi.y = 0;
|
||||
dstroi.height = dst.rows;
|
||||
dstroi.width = dst.cols;
|
||||
|
||||
cv::cuda::NppStreamHandler h(stream);
|
||||
|
||||
#if USE_NPP_STREAM_CTX
|
||||
nppSafeCall(func(src.ptr<npp_type>(), srcsz, static_cast<int>(src.step), srcroi,
|
||||
dst.ptr<npp_type>(), static_cast<int>(dst.step), dstroi,
|
||||
coeffs, npp_inter[interpolation], h));
|
||||
#else
|
||||
nppSafeCall( func(src.ptr<npp_type>(), srcsz, static_cast<int>(src.step), srcroi,
|
||||
dst.ptr<npp_type>(), static_cast<int>(dst.step), dstroi,
|
||||
coeffs, npp_inter[interpolation]) );
|
||||
#endif
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void cv::cuda::warpAffine(InputArray _src, OutputArray _dst, InputArray _M, Size dsize, int flags, int borderMode, Scalar borderValue, Stream& stream)
|
||||
{
|
||||
GpuMat src = _src.getGpuMat();
|
||||
Mat M = _M.getMat();
|
||||
|
||||
CV_Assert( M.rows == 2 && M.cols == 3 );
|
||||
|
||||
const int interpolation = flags & INTER_MAX;
|
||||
|
||||
CV_Assert( src.depth() <= CV_32F && src.channels() <= 4 );
|
||||
CV_Assert( interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC );
|
||||
CV_Assert( borderMode == BORDER_REFLECT101 || borderMode == BORDER_REPLICATE || borderMode == BORDER_CONSTANT || borderMode == BORDER_REFLECT || borderMode == BORDER_WRAP );
|
||||
|
||||
_dst.create(dsize, src.type());
|
||||
GpuMat dst = _dst.getGpuMat();
|
||||
|
||||
CV_Assert( src.data != dst.data && "In-place operation not supported for cv::cuda::warpAffine" );
|
||||
|
||||
Size wholeSize;
|
||||
Point ofs;
|
||||
src.locateROI(wholeSize, ofs);
|
||||
|
||||
static const bool useNppTab[6][4][3] =
|
||||
{
|
||||
{
|
||||
{false, false, true},
|
||||
{false, false, false},
|
||||
{false, true, true},
|
||||
{false, false, false}
|
||||
},
|
||||
{
|
||||
{false, false, false},
|
||||
{false, false, false},
|
||||
{false, false, false},
|
||||
{false, false, false}
|
||||
},
|
||||
{
|
||||
{false, true, true},
|
||||
{false, false, false},
|
||||
{false, true, true},
|
||||
{false, false, false}
|
||||
},
|
||||
{
|
||||
{false, false, false},
|
||||
{false, false, false},
|
||||
{false, false, false},
|
||||
{false, false, false}
|
||||
},
|
||||
{
|
||||
{false, true, true},
|
||||
{false, false, false},
|
||||
{false, true, true},
|
||||
{false, false, true}
|
||||
},
|
||||
{
|
||||
{false, true, true},
|
||||
{false, false, false},
|
||||
{false, true, true},
|
||||
{false, false, true}
|
||||
}
|
||||
};
|
||||
|
||||
bool useNpp = borderMode == BORDER_CONSTANT && ofs.x == 0 && ofs.y == 0 && useNppTab[src.depth()][src.channels() - 1][interpolation];
|
||||
// NPP bug on float data
|
||||
useNpp = useNpp && src.depth() != CV_32F;
|
||||
|
||||
if (useNpp)
|
||||
{
|
||||
typedef void (*func_t)(const cv::cuda::GpuMat& src, cv::cuda::GpuMat& dst, double coeffs[][3], int flags, cudaStream_t stream);
|
||||
|
||||
static const func_t funcs[2][6][4] =
|
||||
{
|
||||
#if USE_NPP_STREAM_CTX
|
||||
{
|
||||
{NppWarp<CV_8U, nppiWarpAffine_8u_C1R_Ctx>::call, 0, NppWarp<CV_8U, nppiWarpAffine_8u_C3R_Ctx>::call, NppWarp<CV_8U, nppiWarpAffine_8u_C4R_Ctx>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_16U, nppiWarpAffine_16u_C1R_Ctx>::call, 0, NppWarp<CV_16U, nppiWarpAffine_16u_C3R_Ctx>::call, NppWarp<CV_16U, nppiWarpAffine_16u_C4R_Ctx>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_32S, nppiWarpAffine_32s_C1R_Ctx>::call, 0, NppWarp<CV_32S, nppiWarpAffine_32s_C3R_Ctx>::call, NppWarp<CV_32S, nppiWarpAffine_32s_C4R_Ctx>::call},
|
||||
{NppWarp<CV_32F, nppiWarpAffine_32f_C1R_Ctx>::call, 0, NppWarp<CV_32F, nppiWarpAffine_32f_C3R_Ctx>::call, NppWarp<CV_32F, nppiWarpAffine_32f_C4R_Ctx>::call}
|
||||
},
|
||||
{
|
||||
{NppWarp<CV_8U, nppiWarpAffineBack_8u_C1R_Ctx>::call, 0, NppWarp<CV_8U, nppiWarpAffineBack_8u_C3R_Ctx>::call, NppWarp<CV_8U, nppiWarpAffineBack_8u_C4R_Ctx>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_16U, nppiWarpAffineBack_16u_C1R_Ctx>::call, 0, NppWarp<CV_16U, nppiWarpAffineBack_16u_C3R_Ctx>::call, NppWarp<CV_16U, nppiWarpAffineBack_16u_C4R_Ctx>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_32S, nppiWarpAffineBack_32s_C1R_Ctx>::call, 0, NppWarp<CV_32S, nppiWarpAffineBack_32s_C3R_Ctx>::call, NppWarp<CV_32S, nppiWarpAffineBack_32s_C4R_Ctx>::call},
|
||||
{NppWarp<CV_32F, nppiWarpAffineBack_32f_C1R_Ctx>::call, 0, NppWarp<CV_32F, nppiWarpAffineBack_32f_C3R_Ctx>::call, NppWarp<CV_32F, nppiWarpAffineBack_32f_C4R_Ctx>::call}
|
||||
}
|
||||
#else
|
||||
{
|
||||
{NppWarp<CV_8U, nppiWarpAffine_8u_C1R>::call, 0, NppWarp<CV_8U, nppiWarpAffine_8u_C3R>::call, NppWarp<CV_8U, nppiWarpAffine_8u_C4R>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_16U, nppiWarpAffine_16u_C1R>::call, 0, NppWarp<CV_16U, nppiWarpAffine_16u_C3R>::call, NppWarp<CV_16U, nppiWarpAffine_16u_C4R>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_32S, nppiWarpAffine_32s_C1R>::call, 0, NppWarp<CV_32S, nppiWarpAffine_32s_C3R>::call, NppWarp<CV_32S, nppiWarpAffine_32s_C4R>::call},
|
||||
{NppWarp<CV_32F, nppiWarpAffine_32f_C1R>::call, 0, NppWarp<CV_32F, nppiWarpAffine_32f_C3R>::call, NppWarp<CV_32F, nppiWarpAffine_32f_C4R>::call}
|
||||
},
|
||||
{
|
||||
{NppWarp<CV_8U, nppiWarpAffineBack_8u_C1R>::call, 0, NppWarp<CV_8U, nppiWarpAffineBack_8u_C3R>::call, NppWarp<CV_8U, nppiWarpAffineBack_8u_C4R>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_16U, nppiWarpAffineBack_16u_C1R>::call, 0, NppWarp<CV_16U, nppiWarpAffineBack_16u_C3R>::call, NppWarp<CV_16U, nppiWarpAffineBack_16u_C4R>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_32S, nppiWarpAffineBack_32s_C1R>::call, 0, NppWarp<CV_32S, nppiWarpAffineBack_32s_C3R>::call, NppWarp<CV_32S, nppiWarpAffineBack_32s_C4R>::call},
|
||||
{NppWarp<CV_32F, nppiWarpAffineBack_32f_C1R>::call, 0, NppWarp<CV_32F, nppiWarpAffineBack_32f_C3R>::call, NppWarp<CV_32F, nppiWarpAffineBack_32f_C4R>::call}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
dst.setTo(borderValue, stream);
|
||||
|
||||
double coeffs[2][3];
|
||||
Mat coeffsMat(2, 3, CV_64F, (void*)coeffs);
|
||||
M.convertTo(coeffsMat, coeffsMat.type());
|
||||
|
||||
const func_t func = funcs[(flags & WARP_INVERSE_MAP) != 0][src.depth()][src.channels() - 1];
|
||||
CV_Assert(func != 0);
|
||||
|
||||
func(src, dst, coeffs, interpolation, StreamAccessor::getStream(stream));
|
||||
}
|
||||
else
|
||||
{
|
||||
using namespace cv::cuda::device::imgproc;
|
||||
|
||||
typedef void (*func_t)(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation,
|
||||
int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
|
||||
static const func_t funcs[6][4] =
|
||||
{
|
||||
{warpAffine_gpu<uchar> , 0 /*warpAffine_gpu<uchar2>*/ , warpAffine_gpu<uchar3> , warpAffine_gpu<uchar4> },
|
||||
{0 /*warpAffine_gpu<schar>*/, 0 /*warpAffine_gpu<char2>*/ , 0 /*warpAffine_gpu<char3>*/, 0 /*warpAffine_gpu<char4>*/},
|
||||
{warpAffine_gpu<ushort> , 0 /*warpAffine_gpu<ushort2>*/, warpAffine_gpu<ushort3> , warpAffine_gpu<ushort4> },
|
||||
{warpAffine_gpu<short> , 0 /*warpAffine_gpu<short2>*/ , warpAffine_gpu<short3> , warpAffine_gpu<short4> },
|
||||
{0 /*warpAffine_gpu<int>*/ , 0 /*warpAffine_gpu<int2>*/ , 0 /*warpAffine_gpu<int3>*/ , 0 /*warpAffine_gpu<int4>*/ },
|
||||
{warpAffine_gpu<float> , 0 /*warpAffine_gpu<float2>*/ , warpAffine_gpu<float3> , warpAffine_gpu<float4> }
|
||||
};
|
||||
|
||||
const func_t func = funcs[src.depth()][src.channels() - 1];
|
||||
CV_Assert(func != 0);
|
||||
|
||||
float coeffs[2 * 3];
|
||||
Mat coeffsMat(2, 3, CV_32F, (void*)coeffs);
|
||||
|
||||
if (flags & WARP_INVERSE_MAP)
|
||||
M.convertTo(coeffsMat, coeffsMat.type());
|
||||
else
|
||||
{
|
||||
cv::Mat iM;
|
||||
invertAffineTransform(M, iM);
|
||||
iM.convertTo(coeffsMat, coeffsMat.type());
|
||||
}
|
||||
|
||||
Scalar_<float> borderValueFloat;
|
||||
borderValueFloat = borderValue;
|
||||
|
||||
func(src, PtrStepSzb(wholeSize.height, wholeSize.width, src.datastart, src.step), ofs.x, ofs.y, coeffs,
|
||||
dst, interpolation, borderMode, borderValueFloat.val, StreamAccessor::getStream(stream), deviceSupports(FEATURE_SET_COMPUTE_20));
|
||||
}
|
||||
}
|
||||
|
||||
void cv::cuda::warpPerspective(InputArray _src, OutputArray _dst, InputArray _M, Size dsize, int flags, int borderMode, Scalar borderValue, Stream& stream)
|
||||
{
|
||||
GpuMat src = _src.getGpuMat();
|
||||
Mat M = _M.getMat();
|
||||
|
||||
CV_Assert( M.rows == 3 && M.cols == 3 );
|
||||
|
||||
const int interpolation = flags & INTER_MAX;
|
||||
|
||||
CV_Assert( src.depth() <= CV_32F && src.channels() <= 4 );
|
||||
CV_Assert( interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC );
|
||||
CV_Assert( borderMode == BORDER_REFLECT101 || borderMode == BORDER_REPLICATE || borderMode == BORDER_CONSTANT || borderMode == BORDER_REFLECT || borderMode == BORDER_WRAP) ;
|
||||
|
||||
_dst.create(dsize, src.type());
|
||||
GpuMat dst = _dst.getGpuMat();
|
||||
|
||||
Size wholeSize;
|
||||
Point ofs;
|
||||
src.locateROI(wholeSize, ofs);
|
||||
|
||||
static const bool useNppTab[6][4][3] =
|
||||
{
|
||||
{
|
||||
{false, false, true},
|
||||
{false, false, false},
|
||||
{false, true, true},
|
||||
{false, false, false}
|
||||
},
|
||||
{
|
||||
{false, false, false},
|
||||
{false, false, false},
|
||||
{false, false, false},
|
||||
{false, false, false}
|
||||
},
|
||||
{
|
||||
{false, true, true},
|
||||
{false, false, false},
|
||||
{false, true, true},
|
||||
{false, false, false}
|
||||
},
|
||||
{
|
||||
{false, false, false},
|
||||
{false, false, false},
|
||||
{false, false, false},
|
||||
{false, false, false}
|
||||
},
|
||||
{
|
||||
{false, true, true},
|
||||
{false, false, false},
|
||||
{false, true, true},
|
||||
{false, false, true}
|
||||
},
|
||||
{
|
||||
{false, true, true},
|
||||
{false, false, false},
|
||||
{false, true, true},
|
||||
{false, false, true}
|
||||
}
|
||||
};
|
||||
|
||||
bool useNpp = borderMode == BORDER_CONSTANT && ofs.x == 0 && ofs.y == 0 && useNppTab[src.depth()][src.channels() - 1][interpolation];
|
||||
// NPP bug on float data
|
||||
useNpp = useNpp && src.depth() != CV_32F;
|
||||
|
||||
if (useNpp)
|
||||
{
|
||||
typedef void (*func_t)(const cv::cuda::GpuMat& src, cv::cuda::GpuMat& dst, double coeffs[][3], int flags, cudaStream_t stream);
|
||||
|
||||
static const func_t funcs[2][6][4] =
|
||||
{
|
||||
#if USE_NPP_STREAM_CTX
|
||||
{
|
||||
{NppWarp<CV_8U, nppiWarpPerspective_8u_C1R_Ctx>::call, 0, NppWarp<CV_8U, nppiWarpPerspective_8u_C3R_Ctx>::call, NppWarp<CV_8U, nppiWarpPerspective_8u_C4R_Ctx>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_16U, nppiWarpPerspective_16u_C1R_Ctx>::call, 0, NppWarp<CV_16U, nppiWarpPerspective_16u_C3R_Ctx>::call, NppWarp<CV_16U, nppiWarpPerspective_16u_C4R_Ctx>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_32S, nppiWarpPerspective_32s_C1R_Ctx>::call, 0, NppWarp<CV_32S, nppiWarpPerspective_32s_C3R_Ctx>::call, NppWarp<CV_32S, nppiWarpPerspective_32s_C4R_Ctx>::call},
|
||||
{NppWarp<CV_32F, nppiWarpPerspective_32f_C1R_Ctx>::call, 0, NppWarp<CV_32F, nppiWarpPerspective_32f_C3R_Ctx>::call, NppWarp<CV_32F, nppiWarpPerspective_32f_C4R_Ctx>::call}
|
||||
},
|
||||
{
|
||||
{NppWarp<CV_8U, nppiWarpPerspectiveBack_8u_C1R_Ctx>::call, 0, NppWarp<CV_8U, nppiWarpPerspectiveBack_8u_C3R_Ctx>::call, NppWarp<CV_8U, nppiWarpPerspectiveBack_8u_C4R_Ctx>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_16U, nppiWarpPerspectiveBack_16u_C1R_Ctx>::call, 0, NppWarp<CV_16U, nppiWarpPerspectiveBack_16u_C3R_Ctx>::call, NppWarp<CV_16U, nppiWarpPerspectiveBack_16u_C4R_Ctx>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_32S, nppiWarpPerspectiveBack_32s_C1R_Ctx>::call, 0, NppWarp<CV_32S, nppiWarpPerspectiveBack_32s_C3R_Ctx>::call, NppWarp<CV_32S, nppiWarpPerspectiveBack_32s_C4R_Ctx>::call},
|
||||
{NppWarp<CV_32F, nppiWarpPerspectiveBack_32f_C1R_Ctx>::call, 0, NppWarp<CV_32F, nppiWarpPerspectiveBack_32f_C3R_Ctx>::call, NppWarp<CV_32F, nppiWarpPerspectiveBack_32f_C4R_Ctx>::call}
|
||||
}
|
||||
#else
|
||||
{
|
||||
{NppWarp<CV_8U, nppiWarpPerspective_8u_C1R>::call, 0, NppWarp<CV_8U, nppiWarpPerspective_8u_C3R>::call, NppWarp<CV_8U, nppiWarpPerspective_8u_C4R>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_16U, nppiWarpPerspective_16u_C1R>::call, 0, NppWarp<CV_16U, nppiWarpPerspective_16u_C3R>::call, NppWarp<CV_16U, nppiWarpPerspective_16u_C4R>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_32S, nppiWarpPerspective_32s_C1R>::call, 0, NppWarp<CV_32S, nppiWarpPerspective_32s_C3R>::call, NppWarp<CV_32S, nppiWarpPerspective_32s_C4R>::call},
|
||||
{NppWarp<CV_32F, nppiWarpPerspective_32f_C1R>::call, 0, NppWarp<CV_32F, nppiWarpPerspective_32f_C3R>::call, NppWarp<CV_32F, nppiWarpPerspective_32f_C4R>::call}
|
||||
},
|
||||
{
|
||||
{NppWarp<CV_8U, nppiWarpPerspectiveBack_8u_C1R>::call, 0, NppWarp<CV_8U, nppiWarpPerspectiveBack_8u_C3R>::call, NppWarp<CV_8U, nppiWarpPerspectiveBack_8u_C4R>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_16U, nppiWarpPerspectiveBack_16u_C1R>::call, 0, NppWarp<CV_16U, nppiWarpPerspectiveBack_16u_C3R>::call, NppWarp<CV_16U, nppiWarpPerspectiveBack_16u_C4R>::call},
|
||||
{0, 0, 0, 0},
|
||||
{NppWarp<CV_32S, nppiWarpPerspectiveBack_32s_C1R>::call, 0, NppWarp<CV_32S, nppiWarpPerspectiveBack_32s_C3R>::call, NppWarp<CV_32S, nppiWarpPerspectiveBack_32s_C4R>::call},
|
||||
{NppWarp<CV_32F, nppiWarpPerspectiveBack_32f_C1R>::call, 0, NppWarp<CV_32F, nppiWarpPerspectiveBack_32f_C3R>::call, NppWarp<CV_32F, nppiWarpPerspectiveBack_32f_C4R>::call}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
dst.setTo(borderValue, stream);
|
||||
|
||||
double coeffs[3][3];
|
||||
Mat coeffsMat(3, 3, CV_64F, (void*)coeffs);
|
||||
M.convertTo(coeffsMat, coeffsMat.type());
|
||||
|
||||
const func_t func = funcs[(flags & WARP_INVERSE_MAP) != 0][src.depth()][src.channels() - 1];
|
||||
CV_Assert(func != 0);
|
||||
|
||||
func(src, dst, coeffs, interpolation, StreamAccessor::getStream(stream));
|
||||
}
|
||||
else
|
||||
{
|
||||
using namespace cv::cuda::device::imgproc;
|
||||
|
||||
typedef void (*func_t)(PtrStepSzb src, PtrStepSzb srcWhole, int xoff, int yoff, float coeffs[2 * 3], PtrStepSzb dst, int interpolation,
|
||||
int borderMode, const float* borderValue, cudaStream_t stream, bool cc20);
|
||||
|
||||
static const func_t funcs[6][4] =
|
||||
{
|
||||
{warpPerspective_gpu<uchar> , 0 /*warpPerspective_gpu<uchar2>*/ , warpPerspective_gpu<uchar3> , warpPerspective_gpu<uchar4> },
|
||||
{0 /*warpPerspective_gpu<schar>*/, 0 /*warpPerspective_gpu<char2>*/ , 0 /*warpPerspective_gpu<char3>*/, 0 /*warpPerspective_gpu<char4>*/},
|
||||
{warpPerspective_gpu<ushort> , 0 /*warpPerspective_gpu<ushort2>*/, warpPerspective_gpu<ushort3> , warpPerspective_gpu<ushort4> },
|
||||
{warpPerspective_gpu<short> , 0 /*warpPerspective_gpu<short2>*/ , warpPerspective_gpu<short3> , warpPerspective_gpu<short4> },
|
||||
{0 /*warpPerspective_gpu<int>*/ , 0 /*warpPerspective_gpu<int2>*/ , 0 /*warpPerspective_gpu<int3>*/ , 0 /*warpPerspective_gpu<int4>*/ },
|
||||
{warpPerspective_gpu<float> , 0 /*warpPerspective_gpu<float2>*/ , warpPerspective_gpu<float3> , warpPerspective_gpu<float4> }
|
||||
};
|
||||
|
||||
const func_t func = funcs[src.depth()][src.channels() - 1];
|
||||
CV_Assert(func != 0);
|
||||
|
||||
float coeffs[3 * 3];
|
||||
Mat coeffsMat(3, 3, CV_32F, (void*)coeffs);
|
||||
|
||||
if (flags & WARP_INVERSE_MAP)
|
||||
M.convertTo(coeffsMat, coeffsMat.type());
|
||||
else
|
||||
{
|
||||
cv::Mat iM;
|
||||
invert(M, iM);
|
||||
iM.convertTo(coeffsMat, coeffsMat.type());
|
||||
}
|
||||
|
||||
Scalar_<float> borderValueFloat;
|
||||
borderValueFloat = borderValue;
|
||||
|
||||
func(src, PtrStepSzb(wholeSize.height, wholeSize.width, src.datastart, src.step), ofs.x, ofs.y, coeffs,
|
||||
dst, interpolation, borderMode, borderValueFloat.val, StreamAccessor::getStream(stream), deviceSupports(FEATURE_SET_COMPUTE_20));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// rotate
|
||||
|
||||
namespace
|
||||
{
|
||||
template <int DEPTH> struct NppRotateFunc
|
||||
{
|
||||
typedef typename NPPTypeTraits<DEPTH>::npp_type npp_type;
|
||||
|
||||
#if USE_NPP_STREAM_CTX
|
||||
typedef NppStatus(*func_t)(const npp_type* pSrc, NppiSize oSrcSize, int nSrcStep, NppiRect oSrcROI,
|
||||
npp_type* pDst, int nDstStep, NppiRect oDstROI,
|
||||
double nAngle, double nShiftX, double nShiftY, int eInterpolation, NppStreamContext ctx);
|
||||
#else
|
||||
typedef NppStatus (*func_t)(const npp_type* pSrc, NppiSize oSrcSize, int nSrcStep, NppiRect oSrcROI,
|
||||
npp_type* pDst, int nDstStep, NppiRect oDstROI,
|
||||
double nAngle, double nShiftX, double nShiftY, int eInterpolation);
|
||||
#endif
|
||||
};
|
||||
|
||||
template <int DEPTH, typename NppRotateFunc<DEPTH>::func_t func> struct NppRotate
|
||||
{
|
||||
typedef typename NppRotateFunc<DEPTH>::npp_type npp_type;
|
||||
|
||||
static void call(const GpuMat& src, GpuMat& dst, Size dsize, double angle, double xShift, double yShift, int interpolation, cudaStream_t stream)
|
||||
{
|
||||
CV_UNUSED(dsize);
|
||||
static const int npp_inter[] = {NPPI_INTER_NN, NPPI_INTER_LINEAR, NPPI_INTER_CUBIC};
|
||||
|
||||
NppStreamHandler h(stream);
|
||||
|
||||
NppiSize srcsz;
|
||||
srcsz.height = src.rows;
|
||||
srcsz.width = src.cols;
|
||||
NppiRect srcroi;
|
||||
srcroi.x = srcroi.y = 0;
|
||||
srcroi.height = src.rows;
|
||||
srcroi.width = src.cols;
|
||||
NppiRect dstroi;
|
||||
dstroi.x = dstroi.y = 0;
|
||||
dstroi.height = dst.rows;
|
||||
dstroi.width = dst.cols;
|
||||
|
||||
#if USE_NPP_STREAM_CTX
|
||||
nppSafeCall(func(src.ptr<npp_type>(), srcsz, static_cast<int>(src.step), srcroi,
|
||||
dst.ptr<npp_type>(), static_cast<int>(dst.step), dstroi, angle, xShift, yShift, npp_inter[interpolation], h));
|
||||
#else
|
||||
nppSafeCall( func(src.ptr<npp_type>(), srcsz, static_cast<int>(src.step), srcroi,
|
||||
dst.ptr<npp_type>(), static_cast<int>(dst.step), dstroi, angle, xShift, yShift, npp_inter[interpolation]) );
|
||||
#endif
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void cv::cuda::rotate(InputArray _src, OutputArray _dst, Size dsize, double angle, double xShift, double yShift, int interpolation, Stream& stream)
|
||||
{
|
||||
typedef void (*func_t)(const GpuMat& src, GpuMat& dst, Size dsize, double angle, double xShift, double yShift, int interpolation, cudaStream_t stream);
|
||||
static const func_t funcs[6][4] =
|
||||
{
|
||||
#if USE_NPP_STREAM_CTX
|
||||
{NppRotate<CV_8U, nppiRotate_8u_C1R_Ctx>::call, 0, NppRotate<CV_8U, nppiRotate_8u_C3R_Ctx>::call, NppRotate<CV_8U, nppiRotate_8u_C4R_Ctx>::call},
|
||||
{0,0,0,0},
|
||||
{NppRotate<CV_16U, nppiRotate_16u_C1R_Ctx>::call, 0, NppRotate<CV_16U, nppiRotate_16u_C3R_Ctx>::call, NppRotate<CV_16U, nppiRotate_16u_C4R_Ctx>::call},
|
||||
{0,0,0,0},
|
||||
{0,0,0,0},
|
||||
{NppRotate<CV_32F, nppiRotate_32f_C1R_Ctx>::call, 0, NppRotate<CV_32F, nppiRotate_32f_C3R_Ctx>::call, NppRotate<CV_32F, nppiRotate_32f_C4R_Ctx>::call}
|
||||
#else
|
||||
{NppRotate<CV_8U, nppiRotate_8u_C1R>::call, 0, NppRotate<CV_8U, nppiRotate_8u_C3R>::call, NppRotate<CV_8U, nppiRotate_8u_C4R>::call},
|
||||
{0,0,0,0},
|
||||
{NppRotate<CV_16U, nppiRotate_16u_C1R>::call, 0, NppRotate<CV_16U, nppiRotate_16u_C3R>::call, NppRotate<CV_16U, nppiRotate_16u_C4R>::call},
|
||||
{0,0,0,0},
|
||||
{0,0,0,0},
|
||||
{NppRotate<CV_32F, nppiRotate_32f_C1R>::call, 0, NppRotate<CV_32F, nppiRotate_32f_C3R>::call, NppRotate<CV_32F, nppiRotate_32f_C4R>::call}
|
||||
#endif
|
||||
};
|
||||
|
||||
GpuMat src = _src.getGpuMat();
|
||||
|
||||
CV_Assert( src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32F );
|
||||
CV_Assert( src.channels() == 1 || src.channels() == 3 || src.channels() == 4 );
|
||||
CV_Assert( interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC );
|
||||
|
||||
_dst.create(dsize, src.type());
|
||||
GpuMat dst = _dst.getGpuMat();
|
||||
|
||||
dst.setTo(Scalar::all(0), stream);
|
||||
|
||||
funcs[src.depth()][src.channels() - 1](src, dst, dsize, angle, xShift, yShift, interpolation, StreamAccessor::getStream(stream));
|
||||
}
|
||||
|
||||
#endif // HAVE_CUDA
|
||||
@@ -0,0 +1,182 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_TEST_INTERPOLATION_HPP__
|
||||
#define __OPENCV_TEST_INTERPOLATION_HPP__
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
template <typename T> T readVal(const cv::Mat& src, int y, int x, int c, int border_type, cv::Scalar borderVal = cv::Scalar())
|
||||
{
|
||||
if (border_type == cv::BORDER_CONSTANT)
|
||||
return (y >= 0 && y < src.rows && x >= 0 && x < src.cols) ? src.at<T>(y, x * src.channels() + c) : cv::saturate_cast<T>(borderVal.val[c]);
|
||||
|
||||
return src.at<T>(cv::borderInterpolate(y, src.rows, border_type), cv::borderInterpolate(x, src.cols, border_type) * src.channels() + c);
|
||||
}
|
||||
|
||||
template <typename T> struct NearestInterpolator
|
||||
{
|
||||
static T getValue(const cv::Mat& src, float y, float x, int c, int border_type, cv::Scalar borderVal = cv::Scalar())
|
||||
{
|
||||
return readVal<T>(src, int(y), int(x), c, border_type, borderVal);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct LinearInterpolator
|
||||
{
|
||||
static T getValue(const cv::Mat& src, float y, float x, int c, int border_type, cv::Scalar borderVal = cv::Scalar())
|
||||
{
|
||||
int x1 = cvFloor(x);
|
||||
int y1 = cvFloor(y);
|
||||
int x2 = x1 + 1;
|
||||
int y2 = y1 + 1;
|
||||
|
||||
float res = 0;
|
||||
|
||||
res += readVal<T>(src, y1, x1, c, border_type, borderVal) * ((x2 - x) * (y2 - y));
|
||||
res += readVal<T>(src, y1, x2, c, border_type, borderVal) * ((x - x1) * (y2 - y));
|
||||
res += readVal<T>(src, y2, x1, c, border_type, borderVal) * ((x2 - x) * (y - y1));
|
||||
res += readVal<T>(src, y2, x2, c, border_type, borderVal) * ((x - x1) * (y - y1));
|
||||
|
||||
return cv::saturate_cast<T>(res);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct CubicInterpolator
|
||||
{
|
||||
static float bicubicCoeff(float x_)
|
||||
{
|
||||
float x = fabsf(x_);
|
||||
if (x <= 1.0f)
|
||||
{
|
||||
return x * x * (1.5f * x - 2.5f) + 1.0f;
|
||||
}
|
||||
else if (x < 2.0f)
|
||||
{
|
||||
return x * (x * (-0.5f * x + 2.5f) - 4.0f) + 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
static T getValue(const cv::Mat& src, float y, float x, int c, int border_type, cv::Scalar borderVal = cv::Scalar())
|
||||
{
|
||||
const float xmin = ceilf(x - 2.0f);
|
||||
const float xmax = floorf(x + 2.0f);
|
||||
|
||||
const float ymin = ceilf(y - 2.0f);
|
||||
const float ymax = floorf(y + 2.0f);
|
||||
|
||||
float sum = 0.0f;
|
||||
float wsum = 0.0f;
|
||||
|
||||
for (float cy = ymin; cy <= ymax; cy += 1.0f)
|
||||
{
|
||||
for (float cx = xmin; cx <= xmax; cx += 1.0f)
|
||||
{
|
||||
const float w = bicubicCoeff(x - cx) * bicubicCoeff(y - cy);
|
||||
sum += w * readVal<T>(src, (int) floorf(cy), (int) floorf(cx), c, border_type, borderVal);
|
||||
wsum += w;
|
||||
}
|
||||
}
|
||||
|
||||
float res = (!wsum)? 0 : sum / wsum;
|
||||
|
||||
return cv::saturate_cast<T>(res);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct LanczosInterpolator
|
||||
{
|
||||
static constexpr int A = 4;
|
||||
|
||||
static float lanczosCoeff(float x_)
|
||||
{
|
||||
float x = fabsf(x_);
|
||||
if (x == 0.0f)
|
||||
return 1.0f;
|
||||
if (x >= A)
|
||||
return 0.0f;
|
||||
|
||||
float pi_x = CV_PI * x;
|
||||
return sinf(pi_x) * sinf(pi_x / A) / (pi_x * pi_x / A);
|
||||
}
|
||||
|
||||
static T getValue(const cv::Mat& src, float y, float x, int c, int border_type, cv::Scalar borderVal = cv::Scalar())
|
||||
{
|
||||
const int xmin = (int) floorf(x) - A + 1;
|
||||
const int xmax = (int) floorf(x) + A;
|
||||
|
||||
const int ymin = (int) floorf(y) - A + 1;
|
||||
const int ymax = (int) floorf(y) + A;
|
||||
|
||||
float sum = 0.0f;
|
||||
float wsum = 0.0f;
|
||||
|
||||
for (int cy = ymin; cy <= ymax; ++cy)
|
||||
{
|
||||
float wy = lanczosCoeff(y - cy);
|
||||
if (wy == 0.0f)
|
||||
continue;
|
||||
|
||||
for (int cx = xmin; cx <= xmax; ++cx)
|
||||
{
|
||||
float wx = lanczosCoeff(x - cx);
|
||||
if (wx == 0.0f)
|
||||
continue;
|
||||
|
||||
const float w = wy * wx;
|
||||
sum += w * readVal<T>(src, cy, cx, c, border_type, borderVal);
|
||||
wsum += w;
|
||||
}
|
||||
}
|
||||
|
||||
float res = (!wsum)? 0 : sum / wsum;
|
||||
|
||||
return cv::saturate_cast<T>(res);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __OPENCV_TEST_INTERPOLATION_HPP__
|
||||
@@ -0,0 +1,155 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
#ifdef HAVE_CUDA
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Gold implementation
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T>
|
||||
void resizeLanczosImpl(const cv::Mat& src, cv::Mat& dst, double fx, double fy)
|
||||
{
|
||||
const int cn = src.channels();
|
||||
|
||||
cv::Size dsize(cv::saturate_cast<int>(src.cols * fx), cv::saturate_cast<int>(src.rows * fy));
|
||||
|
||||
dst.create(dsize, src.type());
|
||||
|
||||
float ifx = static_cast<float>(1.0 / fx);
|
||||
float ify = static_cast<float>(1.0 / fy);
|
||||
|
||||
// OpenCV CPU resize uses center-aligned coordinate mapping: (x + 0.5) * fx - 0.5
|
||||
// Since fx and fy here are scale factors, and ifx = 1.0 / fx, ify = 1.0 / fy,
|
||||
// the center-aligned mapping becomes: (x + 0.5) / fx - 0.5 = (x + 0.5) * ifx - 0.5
|
||||
for (int y = 0; y < dsize.height; ++y)
|
||||
{
|
||||
for (int x = 0; x < dsize.width; ++x)
|
||||
{
|
||||
for (int c = 0; c < cn; ++c)
|
||||
{
|
||||
float src_x = (static_cast<float>(x) + 0.5f) * ifx - 0.5f;
|
||||
float src_y = (static_cast<float>(y) + 0.5f) * ify - 0.5f;
|
||||
dst.at<T>(y, x * cn + c) = LanczosInterpolator<T>::getValue(src, src_y, src_x, c, cv::BORDER_REPLICATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void resizeLanczosGold(const cv::Mat& src, cv::Mat& dst, double fx, double fy)
|
||||
{
|
||||
typedef void (*func_t)(const cv::Mat& src, cv::Mat& dst, double fx, double fy);
|
||||
|
||||
static const func_t lanczos_funcs[] =
|
||||
{
|
||||
resizeLanczosImpl<unsigned char>,
|
||||
resizeLanczosImpl<signed char>,
|
||||
resizeLanczosImpl<unsigned short>,
|
||||
resizeLanczosImpl<short>,
|
||||
resizeLanczosImpl<int>,
|
||||
resizeLanczosImpl<float>
|
||||
};
|
||||
|
||||
lanczos_funcs[src.depth()](src, dst, fx, fy);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
PARAM_TEST_CASE(ResizeLanczos, cv::cuda::DeviceInfo, cv::Size, MatType, double, UseRoi)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
cv::Size size;
|
||||
double coeff;
|
||||
int type;
|
||||
bool useRoi;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
size = GET_PARAM(1);
|
||||
type = GET_PARAM(2);
|
||||
coeff = GET_PARAM(3);
|
||||
useRoi = GET_PARAM(4);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
|
||||
virtual void TearDown()
|
||||
{
|
||||
// GpuMat destructors will automatically clean up GPU memory
|
||||
}
|
||||
};
|
||||
|
||||
CUDA_TEST_P(ResizeLanczos, Accuracy)
|
||||
{
|
||||
cv::Mat src = randomMat(size, type);
|
||||
|
||||
cv::cuda::GpuMat dst = createMat(cv::Size(cv::saturate_cast<int>(src.cols * coeff), cv::saturate_cast<int>(src.rows * coeff)), type, useRoi);
|
||||
cv::cuda::resize(loadMat(src, useRoi), dst, cv::Size(), coeff, coeff, cv::INTER_LANCZOS4);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
resizeLanczosGold(src, dst_gold, coeff, coeff);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-2 : 1.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, ResizeLanczos, testing::Combine(
|
||||
testing::Values(cv::cuda::DeviceInfo()),
|
||||
DIFFERENT_SIZES,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_16UC1), MatType(CV_16UC3), MatType(CV_16UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
testing::Values(0.3, 0.5, 1.5, 2.0),
|
||||
WHOLE_SUBMAT));
|
||||
|
||||
/////////////////
|
||||
|
||||
PARAM_TEST_CASE(ResizeLanczosSameAsHost, cv::cuda::DeviceInfo, cv::Size, MatType, double, UseRoi)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
cv::Size size;
|
||||
double coeff;
|
||||
int type;
|
||||
bool useRoi;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
size = GET_PARAM(1);
|
||||
type = GET_PARAM(2);
|
||||
coeff = GET_PARAM(3);
|
||||
useRoi = GET_PARAM(4);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
|
||||
virtual void TearDown()
|
||||
{
|
||||
// GpuMat destructors will automatically clean up GPU memory
|
||||
}
|
||||
};
|
||||
|
||||
CUDA_TEST_P(ResizeLanczosSameAsHost, Accuracy)
|
||||
{
|
||||
cv::Mat src = randomMat(size, type);
|
||||
|
||||
cv::cuda::GpuMat dst = createMat(cv::Size(cv::saturate_cast<int>(src.cols * coeff), cv::saturate_cast<int>(src.rows * coeff)), type, useRoi);
|
||||
cv::cuda::resize(loadMat(src, useRoi), dst, cv::Size(), coeff, coeff, cv::INTER_LANCZOS4);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
cv::resize(src, dst_gold, cv::Size(), coeff, coeff, cv::INTER_LANCZOS4);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-2 : 1.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, ResizeLanczosSameAsHost, testing::Combine(
|
||||
testing::Values(cv::cuda::DeviceInfo()),
|
||||
DIFFERENT_SIZES,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_16UC1), MatType(CV_16UC3), MatType(CV_16UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
testing::Values(0.3, 0.5, 1.5, 2.0),
|
||||
WHOLE_SUBMAT));
|
||||
|
||||
}} // namespace
|
||||
#endif // HAVE_CUDA
|
||||
@@ -0,0 +1,45 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
CV_CUDA_TEST_MAIN("gpu")
|
||||
@@ -0,0 +1,57 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "opencv2/ts.hpp"
|
||||
#include "opencv2/ts/cuda_test.hpp"
|
||||
|
||||
#include "opencv2/cudawarping.hpp"
|
||||
#include "opencv2/geometry.hpp"
|
||||
|
||||
#include "cvconfig.h"
|
||||
|
||||
#include "interpolation.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,131 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
#ifdef HAVE_CUDA
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// pyrDown
|
||||
|
||||
PARAM_TEST_CASE(PyrDown, cv::cuda::DeviceInfo, cv::Size, MatType, UseRoi)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
cv::Size size;
|
||||
int type;
|
||||
bool useRoi;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
size = GET_PARAM(1);
|
||||
type = GET_PARAM(2);
|
||||
useRoi = GET_PARAM(3);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
CUDA_TEST_P(PyrDown, Accuracy)
|
||||
{
|
||||
cv::Mat src = randomMat(size, type);
|
||||
|
||||
cv::cuda::GpuMat dst = createMat(cv::Size((size.width + 1) / 2, (size.height + 1) / 2), type, useRoi);
|
||||
cv::cuda::pyrDown(loadMat(src, useRoi), dst);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
cv::pyrDown(src, dst_gold);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-4 : 1.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, PyrDown, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
DIFFERENT_SIZES,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_16UC1), MatType(CV_16UC3), MatType(CV_16UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
WHOLE_SUBMAT));
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// pyrUp
|
||||
|
||||
PARAM_TEST_CASE(PyrUp, cv::cuda::DeviceInfo, cv::Size, MatType, UseRoi)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
cv::Size size;
|
||||
int type;
|
||||
bool useRoi;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
size = GET_PARAM(1);
|
||||
type = GET_PARAM(2);
|
||||
useRoi = GET_PARAM(3);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
CUDA_TEST_P(PyrUp, Accuracy)
|
||||
{
|
||||
cv::Mat src = randomMat(size, type);
|
||||
|
||||
cv::cuda::GpuMat dst = createMat(cv::Size(size.width * 2, size.height * 2), type, useRoi);
|
||||
cv::cuda::pyrUp(loadMat(src, useRoi), dst);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
cv::pyrUp(src, dst_gold);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-4 : 1.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, PyrUp, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
DIFFERENT_SIZES,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_16UC1), MatType(CV_16UC3), MatType(CV_16UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
WHOLE_SUBMAT));
|
||||
|
||||
|
||||
}} // namespace
|
||||
#endif // HAVE_CUDA
|
||||
@@ -0,0 +1,285 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
#include "opencv2/core/matx.hpp"
|
||||
#include "nppdefs.h"
|
||||
|
||||
#ifdef HAVE_CUDA
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Gold implementation
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T, template <typename> class Interpolator> void remapImpl(const cv::Mat& src, const cv::Mat& xmap, const cv::Mat& ymap, cv::Mat& dst, int borderType, cv::Scalar borderVal)
|
||||
{
|
||||
const int cn = src.channels();
|
||||
|
||||
cv::Size dsize = xmap.size();
|
||||
|
||||
dst.create(dsize, src.type());
|
||||
|
||||
for (int y = 0; y < dsize.height; ++y)
|
||||
{
|
||||
for (int x = 0; x < dsize.width; ++x)
|
||||
{
|
||||
for (int c = 0; c < cn; ++c)
|
||||
dst.at<T>(y, x * cn + c) = Interpolator<T>::getValue(src, ymap.at<float>(y, x), xmap.at<float>(y, x), c, borderType, borderVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void remapGold(const cv::Mat& src, const cv::Mat& xmap, const cv::Mat& ymap, cv::Mat& dst, int interpolation, int borderType, cv::Scalar borderVal)
|
||||
{
|
||||
typedef void (*func_t)(const cv::Mat& src, const cv::Mat& xmap, const cv::Mat& ymap, cv::Mat& dst, int borderType, cv::Scalar borderVal);
|
||||
|
||||
static const func_t nearest_funcs[] =
|
||||
{
|
||||
remapImpl<unsigned char, NearestInterpolator>,
|
||||
remapImpl<signed char, NearestInterpolator>,
|
||||
remapImpl<unsigned short, NearestInterpolator>,
|
||||
remapImpl<short, NearestInterpolator>,
|
||||
remapImpl<int, NearestInterpolator>,
|
||||
remapImpl<float, NearestInterpolator>
|
||||
};
|
||||
|
||||
static const func_t linear_funcs[] =
|
||||
{
|
||||
remapImpl<unsigned char, LinearInterpolator>,
|
||||
remapImpl<signed char, LinearInterpolator>,
|
||||
remapImpl<unsigned short, LinearInterpolator>,
|
||||
remapImpl<short, LinearInterpolator>,
|
||||
remapImpl<int, LinearInterpolator>,
|
||||
remapImpl<float, LinearInterpolator>
|
||||
};
|
||||
|
||||
static const func_t cubic_funcs[] =
|
||||
{
|
||||
remapImpl<unsigned char, CubicInterpolator>,
|
||||
remapImpl<signed char, CubicInterpolator>,
|
||||
remapImpl<unsigned short, CubicInterpolator>,
|
||||
remapImpl<short, CubicInterpolator>,
|
||||
remapImpl<int, CubicInterpolator>,
|
||||
remapImpl<float, CubicInterpolator>
|
||||
};
|
||||
|
||||
static const func_t* funcs[] = {nearest_funcs, linear_funcs, cubic_funcs};
|
||||
|
||||
funcs[interpolation][src.depth()](src, xmap, ymap, dst, borderType, borderVal);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
PARAM_TEST_CASE(Remap, cv::cuda::DeviceInfo, cv::Size, MatType, Interpolation, BorderType, UseRoi)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
cv::Size size;
|
||||
int type;
|
||||
int interpolation;
|
||||
int borderType;
|
||||
bool useRoi;
|
||||
|
||||
cv::Mat xmap;
|
||||
cv::Mat ymap;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
size = GET_PARAM(1);
|
||||
type = GET_PARAM(2);
|
||||
interpolation = GET_PARAM(3);
|
||||
borderType = GET_PARAM(4);
|
||||
useRoi = GET_PARAM(5);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
|
||||
// rotation matrix
|
||||
|
||||
const double aplha = CV_PI / 4;
|
||||
static double M[2][3] = { {std::cos(aplha), -std::sin(aplha), size.width / 2.0},
|
||||
{std::sin(aplha), std::cos(aplha), 0.0}};
|
||||
|
||||
xmap.create(size, CV_32FC1);
|
||||
ymap.create(size, CV_32FC1);
|
||||
|
||||
for (int y = 0; y < size.height; ++y)
|
||||
{
|
||||
for (int x = 0; x < size.width; ++x)
|
||||
{
|
||||
xmap.at<float>(y, x) = static_cast<float>(M[0][0] * x + M[0][1] * y + M[0][2]);
|
||||
ymap.at<float>(y, x) = static_cast<float>(M[1][0] * x + M[1][1] * y + M[1][2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CUDA_TEST_P(Remap, Accuracy)
|
||||
{
|
||||
cv::Mat src = randomMat(size, type);
|
||||
cv::Scalar val = randomScalar(0.0, 255.0);
|
||||
|
||||
cv::cuda::GpuMat dst = createMat(xmap.size(), type, useRoi);
|
||||
cv::cuda::remap(loadMat(src, useRoi), dst, loadMat(xmap, useRoi), loadMat(ymap, useRoi), interpolation, borderType, val);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
remapGold(src, xmap, ymap, dst_gold, interpolation, borderType, val);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-3 : 1.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, Remap, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
DIFFERENT_SIZES_EXTRA,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
|
||||
testing::Values(BorderType(cv::BORDER_REFLECT101), BorderType(cv::BORDER_REPLICATE), BorderType(cv::BORDER_CONSTANT), BorderType(cv::BORDER_REFLECT), BorderType(cv::BORDER_WRAP)),
|
||||
WHOLE_SUBMAT));
|
||||
|
||||
|
||||
class RemapOutOfScope : public Remap {};
|
||||
CUDA_TEST_P(RemapOutOfScope, Regression_18224)
|
||||
{
|
||||
cv::Mat src = randomMat(size, type);
|
||||
cv::cuda::GpuMat dst = createMat(xmap.size(), type, useRoi);
|
||||
randu(xmap, NPP_MAX_32S, NPP_MAXABS_32F);
|
||||
randu(ymap, NPP_MAX_32S, NPP_MAXABS_32F);
|
||||
|
||||
cv::cuda::remap(loadMat(src, useRoi), dst, loadMat(xmap, useRoi), loadMat(ymap, useRoi), interpolation, borderType, 0.);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
remapGold(src, xmap, ymap, dst_gold, interpolation, borderType, 0.);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-3 : 1.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, RemapOutOfScope, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
DIFFERENT_SIZES_EXTRA,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR)),
|
||||
testing::Values(BorderType(cv::BORDER_CONSTANT)),
|
||||
WHOLE_SUBMAT));
|
||||
|
||||
PARAM_TEST_CASE(RemapRelative, cv::cuda::DeviceInfo, MatType, Interpolation, BorderType)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
int type;
|
||||
int interpolation;
|
||||
int borderType;
|
||||
|
||||
cv::cuda::GpuMat gSrc;
|
||||
cv::cuda::GpuMat gMapRelativeX32F;
|
||||
cv::cuda::GpuMat gMapRelativeY32F;
|
||||
cv::cuda::GpuMat gMapAbsoluteX32F;
|
||||
cv::cuda::GpuMat gMapAbsoluteY32F;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
type = GET_PARAM(1);
|
||||
interpolation = GET_PARAM(2);
|
||||
borderType = GET_PARAM(3);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
|
||||
const int nChannels = CV_MAT_CN(type);
|
||||
const cv::Size size(127, 61);
|
||||
cv::Mat data64FC1(1, size.area()*nChannels, CV_64FC1);
|
||||
data64FC1.forEach<double>([&](double& pixel, const int* position) {pixel = static_cast<double>(position[1]);});
|
||||
|
||||
cv::Mat src;
|
||||
data64FC1.reshape(nChannels, size.height).convertTo(src, type);
|
||||
|
||||
cv::Mat mapRelativeX32F(size, CV_32FC1);
|
||||
mapRelativeX32F.setTo(cv::Scalar::all(-0.33));
|
||||
|
||||
cv::Mat mapRelativeY32F(size, CV_32FC1);
|
||||
mapRelativeY32F.setTo(cv::Scalar::all(-0.33));
|
||||
|
||||
cv::Mat mapAbsoluteX32F = mapRelativeX32F.clone();
|
||||
mapAbsoluteX32F.forEach<float>([&](float& pixel, const int* position) {
|
||||
pixel += static_cast<float>(position[1]);
|
||||
});
|
||||
|
||||
cv::Mat mapAbsoluteY32F = mapRelativeY32F.clone();
|
||||
mapAbsoluteY32F.forEach<float>([&](float& pixel, const int* position) {
|
||||
pixel += static_cast<float>(position[0]);
|
||||
});
|
||||
|
||||
gSrc.upload(src);
|
||||
gMapRelativeX32F.upload(mapRelativeX32F);
|
||||
gMapRelativeY32F.upload(mapRelativeY32F);
|
||||
gMapAbsoluteX32F.upload(mapAbsoluteX32F);
|
||||
gMapAbsoluteY32F.upload(mapAbsoluteY32F);
|
||||
}
|
||||
};
|
||||
CUDA_TEST_P(RemapRelative, RemapRelative_Validity)
|
||||
{
|
||||
cv::cuda::GpuMat gDstAbsolute;
|
||||
cv::cuda::remap(gSrc, gDstAbsolute, gMapAbsoluteX32F, gMapAbsoluteY32F, interpolation, borderType);
|
||||
cv::cuda::GpuMat gDstRelative;
|
||||
cv::cuda::remap(gSrc, gDstRelative, gMapRelativeX32F, gMapRelativeY32F, interpolation | WARP_RELATIVE_MAP, borderType);
|
||||
|
||||
cv::Mat dstAbsolute;
|
||||
gDstAbsolute.download(dstAbsolute);
|
||||
cv::Mat dstRelative;
|
||||
gDstRelative.download(dstRelative);
|
||||
|
||||
EXPECT_MAT_NEAR(dstAbsolute, dstRelative, (dstAbsolute.depth() == CV_32F) ? 1e-3 : 1.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_RemapRelative, RemapRelative, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4),
|
||||
MatType(CV_16UC1), MatType(CV_16UC3), MatType(CV_16UC4),
|
||||
MatType(CV_16SC1), MatType(CV_16SC3), MatType(CV_16SC4),
|
||||
MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
|
||||
testing::Values(BorderType(cv::BORDER_REFLECT101), BorderType(cv::BORDER_REPLICATE), BorderType(cv::BORDER_CONSTANT))));
|
||||
|
||||
}} // namespace
|
||||
#endif // HAVE_CUDA
|
||||
@@ -0,0 +1,265 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
#ifdef HAVE_CUDA
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Gold implementation
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T, template <typename> class Interpolator>
|
||||
void resizeImpl(const cv::Mat& src, cv::Mat& dst, double fx, double fy)
|
||||
{
|
||||
const int cn = src.channels();
|
||||
|
||||
cv::Size dsize(cv::saturate_cast<int>(src.cols * fx), cv::saturate_cast<int>(src.rows * fy));
|
||||
|
||||
dst.create(dsize, src.type());
|
||||
|
||||
float ifx = static_cast<float>(1.0 / fx);
|
||||
float ify = static_cast<float>(1.0 / fy);
|
||||
|
||||
for (int y = 0; y < dsize.height; ++y)
|
||||
{
|
||||
for (int x = 0; x < dsize.width; ++x)
|
||||
{
|
||||
for (int c = 0; c < cn; ++c)
|
||||
dst.at<T>(y, x * cn + c) = Interpolator<T>::getValue(src, y * ify, x * ifx, c, cv::BORDER_REPLICATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void resizeGold(const cv::Mat& src, cv::Mat& dst, double fx, double fy, int interpolation)
|
||||
{
|
||||
typedef void (*func_t)(const cv::Mat& src, cv::Mat& dst, double fx, double fy);
|
||||
|
||||
static const func_t nearest_funcs[] =
|
||||
{
|
||||
resizeImpl<unsigned char, NearestInterpolator>,
|
||||
resizeImpl<signed char, NearestInterpolator>,
|
||||
resizeImpl<unsigned short, NearestInterpolator>,
|
||||
resizeImpl<short, NearestInterpolator>,
|
||||
resizeImpl<int, NearestInterpolator>,
|
||||
resizeImpl<float, NearestInterpolator>
|
||||
};
|
||||
|
||||
|
||||
static const func_t linear_funcs[] =
|
||||
{
|
||||
resizeImpl<unsigned char, LinearInterpolator>,
|
||||
resizeImpl<signed char, LinearInterpolator>,
|
||||
resizeImpl<unsigned short, LinearInterpolator>,
|
||||
resizeImpl<short, LinearInterpolator>,
|
||||
resizeImpl<int, LinearInterpolator>,
|
||||
resizeImpl<float, LinearInterpolator>
|
||||
};
|
||||
|
||||
static const func_t cubic_funcs[] =
|
||||
{
|
||||
resizeImpl<unsigned char, CubicInterpolator>,
|
||||
resizeImpl<signed char, CubicInterpolator>,
|
||||
resizeImpl<unsigned short, CubicInterpolator>,
|
||||
resizeImpl<short, CubicInterpolator>,
|
||||
resizeImpl<int, CubicInterpolator>,
|
||||
resizeImpl<float, CubicInterpolator>
|
||||
};
|
||||
|
||||
static const func_t* funcs[] = {nearest_funcs, linear_funcs, cubic_funcs};
|
||||
|
||||
funcs[interpolation][src.depth()](src, dst, fx, fy);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
PARAM_TEST_CASE(Resize, cv::cuda::DeviceInfo, cv::Size, MatType, double, Interpolation, UseRoi)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
cv::Size size;
|
||||
double coeff;
|
||||
int interpolation;
|
||||
int type;
|
||||
bool useRoi;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
size = GET_PARAM(1);
|
||||
type = GET_PARAM(2);
|
||||
coeff = GET_PARAM(3);
|
||||
interpolation = GET_PARAM(4);
|
||||
useRoi = GET_PARAM(5);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
CUDA_TEST_P(Resize, Accuracy)
|
||||
{
|
||||
cv::Mat src = randomMat(size, type);
|
||||
|
||||
cv::cuda::GpuMat dst = createMat(cv::Size(cv::saturate_cast<int>(src.cols * coeff), cv::saturate_cast<int>(src.rows * coeff)), type, useRoi);
|
||||
cv::cuda::resize(loadMat(src, useRoi), dst, cv::Size(), coeff, coeff, interpolation);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
resizeGold(src, dst_gold, coeff, coeff, interpolation);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-2 : 1.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, Resize, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
DIFFERENT_SIZES,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_16UC1), MatType(CV_16UC3), MatType(CV_16UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
testing::Values(0.3, 0.5, 1.5, 2.0),
|
||||
testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
|
||||
WHOLE_SUBMAT));
|
||||
|
||||
/////////////////
|
||||
|
||||
PARAM_TEST_CASE(ResizeSameAsHost, cv::cuda::DeviceInfo, cv::Size, MatType, double, Interpolation, UseRoi)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
cv::Size size;
|
||||
double coeff;
|
||||
int interpolation;
|
||||
int type;
|
||||
bool useRoi;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
size = GET_PARAM(1);
|
||||
type = GET_PARAM(2);
|
||||
coeff = GET_PARAM(3);
|
||||
interpolation = GET_PARAM(4);
|
||||
useRoi = GET_PARAM(5);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
// downscaling only: used for classifiers
|
||||
CUDA_TEST_P(ResizeSameAsHost, Accuracy)
|
||||
{
|
||||
cv::Mat src = randomMat(size, type);
|
||||
|
||||
cv::cuda::GpuMat dst = createMat(cv::Size(cv::saturate_cast<int>(src.cols * coeff), cv::saturate_cast<int>(src.rows * coeff)), type, useRoi);
|
||||
cv::cuda::resize(loadMat(src, useRoi), dst, cv::Size(), coeff, coeff, interpolation);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
cv::resize(src, dst_gold, cv::Size(), coeff, coeff, interpolation);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-2 : 1.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, ResizeSameAsHost, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
DIFFERENT_SIZES,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_16UC1), MatType(CV_16UC3), MatType(CV_16UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
testing::Values(0.3, 0.5),
|
||||
testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_AREA)),
|
||||
WHOLE_SUBMAT));
|
||||
|
||||
PARAM_TEST_CASE(ResizeTextures, cv::cuda::DeviceInfo, Interpolation)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
Interpolation interpolation;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
interpolation = GET_PARAM(1);
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
void ResizeThread(const Interpolation interp, const GpuMat& imgIn, const std::vector<GpuMat>& imgsOut, Stream& stream) {
|
||||
for (auto& imgOut : imgsOut)
|
||||
cv::cuda::resize(imgIn, imgOut, imgOut.size(), 0, 0, interp, stream);
|
||||
}
|
||||
|
||||
CUDA_TEST_P(ResizeTextures, Accuracy)
|
||||
{
|
||||
constexpr int nThreads = 5;
|
||||
constexpr int nIters = 5;
|
||||
const Size szIn(100, 100);
|
||||
const Size szOut(200, 200);
|
||||
vector<Stream> streams(nThreads, cv::cuda::Stream::Null());
|
||||
vector<GpuMat> imgsIn;
|
||||
vector<vector<GpuMat>> imgsOut;
|
||||
for (int i = 0; i < nThreads; i++) {
|
||||
imgsIn.push_back(GpuMat(szIn, CV_8UC1, i));
|
||||
vector<GpuMat> imgsOutPerThread;
|
||||
for (int j = 0; j < nIters; j++)
|
||||
imgsOutPerThread.push_back(GpuMat(szOut, CV_8UC1));
|
||||
imgsOut.push_back(imgsOutPerThread);
|
||||
}
|
||||
|
||||
vector<std::thread> thread(nThreads);
|
||||
for (int i = 0; i < nThreads; i++) thread.at(i) = std::thread(ResizeThread, interpolation, std::ref(imgsIn.at(i)), std::ref(imgsOut.at(i)), std::ref(streams.at(i)));
|
||||
for (int i = 0; i < nThreads; i++) thread.at(i).join();
|
||||
|
||||
for (int i = 0; i < nThreads; i++) {
|
||||
GpuMat imgOutGs;
|
||||
cv::cuda::resize(imgsIn.at(i), imgOutGs, szOut, 0, 0, interpolation, streams.at(i));
|
||||
Mat imgOutGsHost; imgOutGs.download(imgOutGsHost);
|
||||
for (const auto& imgOut : imgsOut.at(i)) {
|
||||
Mat imgOutHost; imgOut.download(imgOutHost);
|
||||
ASSERT_TRUE(cv::norm(imgOutHost, imgOutGsHost, NORM_INF) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, ResizeTextures, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC))));
|
||||
|
||||
|
||||
}} // namespace
|
||||
#endif // HAVE_CUDA
|
||||
@@ -0,0 +1,312 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
#ifdef HAVE_CUDA
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
namespace
|
||||
{
|
||||
cv::Mat createTransformMatrix(cv::Size srcSize, double angle)
|
||||
{
|
||||
cv::Mat M(2, 3, CV_64FC1);
|
||||
|
||||
M.at<double>(0, 0) = std::cos(angle); M.at<double>(0, 1) = -std::sin(angle); M.at<double>(0, 2) = srcSize.width / 2;
|
||||
M.at<double>(1, 0) = std::sin(angle); M.at<double>(1, 1) = std::cos(angle); M.at<double>(1, 2) = 0.0;
|
||||
|
||||
return M;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Test buildWarpAffineMaps
|
||||
|
||||
PARAM_TEST_CASE(BuildWarpAffineMaps, cv::cuda::DeviceInfo, cv::Size, Inverse)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
cv::Size size;
|
||||
bool inverse;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
size = GET_PARAM(1);
|
||||
inverse = GET_PARAM(2);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
CUDA_TEST_P(BuildWarpAffineMaps, Accuracy)
|
||||
{
|
||||
cv::Mat M = createTransformMatrix(size, CV_PI / 4);
|
||||
cv::Mat src = randomMat(randomSize(200, 400), CV_8UC1);
|
||||
|
||||
cv::cuda::GpuMat xmap, ymap;
|
||||
cv::cuda::buildWarpAffineMaps(M, inverse, size, xmap, ymap);
|
||||
|
||||
int interpolation = cv::INTER_NEAREST;
|
||||
int borderMode = cv::BORDER_CONSTANT;
|
||||
int flags = interpolation;
|
||||
if (inverse)
|
||||
flags |= cv::WARP_INVERSE_MAP;
|
||||
|
||||
cv::Mat dst;
|
||||
cv::remap(src, dst, cv::Mat(xmap), cv::Mat(ymap), interpolation, borderMode);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
cv::warpAffine(src, dst_gold, M, size, flags, borderMode);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, 0.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, BuildWarpAffineMaps, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
DIFFERENT_SIZES,
|
||||
DIRECT_INVERSE));
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Gold implementation
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T, template <typename> class Interpolator> void warpAffineImpl(const cv::Mat& src, const cv::Mat& M, cv::Size dsize, cv::Mat& dst, int borderType, cv::Scalar borderVal)
|
||||
{
|
||||
const int cn = src.channels();
|
||||
|
||||
dst.create(dsize, src.type());
|
||||
|
||||
for (int y = 0; y < dsize.height; ++y)
|
||||
{
|
||||
for (int x = 0; x < dsize.width; ++x)
|
||||
{
|
||||
float xcoo = static_cast<float>(M.at<double>(0, 0) * x + M.at<double>(0, 1) * y + M.at<double>(0, 2));
|
||||
float ycoo = static_cast<float>(M.at<double>(1, 0) * x + M.at<double>(1, 1) * y + M.at<double>(1, 2));
|
||||
|
||||
for (int c = 0; c < cn; ++c)
|
||||
dst.at<T>(y, x * cn + c) = Interpolator<T>::getValue(src, ycoo, xcoo, c, borderType, borderVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void warpAffineGold(const cv::Mat& src, const cv::Mat& M, bool inverse, cv::Size dsize, cv::Mat& dst, int interpolation, int borderType, cv::Scalar borderVal)
|
||||
{
|
||||
typedef void (*func_t)(const cv::Mat& src, const cv::Mat& M, cv::Size dsize, cv::Mat& dst, int borderType, cv::Scalar borderVal);
|
||||
|
||||
static const func_t nearest_funcs[] =
|
||||
{
|
||||
warpAffineImpl<unsigned char, NearestInterpolator>,
|
||||
warpAffineImpl<signed char, NearestInterpolator>,
|
||||
warpAffineImpl<unsigned short, NearestInterpolator>,
|
||||
warpAffineImpl<short, NearestInterpolator>,
|
||||
warpAffineImpl<int, NearestInterpolator>,
|
||||
warpAffineImpl<float, NearestInterpolator>
|
||||
};
|
||||
|
||||
static const func_t linear_funcs[] =
|
||||
{
|
||||
warpAffineImpl<unsigned char, LinearInterpolator>,
|
||||
warpAffineImpl<signed char, LinearInterpolator>,
|
||||
warpAffineImpl<unsigned short, LinearInterpolator>,
|
||||
warpAffineImpl<short, LinearInterpolator>,
|
||||
warpAffineImpl<int, LinearInterpolator>,
|
||||
warpAffineImpl<float, LinearInterpolator>
|
||||
};
|
||||
|
||||
static const func_t cubic_funcs[] =
|
||||
{
|
||||
warpAffineImpl<unsigned char, CubicInterpolator>,
|
||||
warpAffineImpl<signed char, CubicInterpolator>,
|
||||
warpAffineImpl<unsigned short, CubicInterpolator>,
|
||||
warpAffineImpl<short, CubicInterpolator>,
|
||||
warpAffineImpl<int, CubicInterpolator>,
|
||||
warpAffineImpl<float, CubicInterpolator>
|
||||
};
|
||||
|
||||
static const func_t* funcs[] = {nearest_funcs, linear_funcs, cubic_funcs};
|
||||
|
||||
if (inverse)
|
||||
funcs[interpolation][src.depth()](src, M, dsize, dst, borderType, borderVal);
|
||||
else
|
||||
{
|
||||
cv::Mat iM;
|
||||
cv::invertAffineTransform(M, iM);
|
||||
funcs[interpolation][src.depth()](src, iM, dsize, dst, borderType, borderVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
PARAM_TEST_CASE(WarpAffine, cv::cuda::DeviceInfo, cv::Size, MatType, Inverse, Interpolation, BorderType, UseRoi)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
cv::Size size;
|
||||
int type;
|
||||
bool inverse;
|
||||
int interpolation;
|
||||
int borderType;
|
||||
bool useRoi;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
size = GET_PARAM(1);
|
||||
type = GET_PARAM(2);
|
||||
inverse = GET_PARAM(3);
|
||||
interpolation = GET_PARAM(4);
|
||||
borderType = GET_PARAM(5);
|
||||
useRoi = GET_PARAM(6);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
CUDA_TEST_P(WarpAffine, Accuracy)
|
||||
{
|
||||
cv::Mat src = randomMat(size, type);
|
||||
cv::Mat M = createTransformMatrix(size, CV_PI / 3);
|
||||
int flags = interpolation;
|
||||
if (inverse)
|
||||
flags |= cv::WARP_INVERSE_MAP;
|
||||
cv::Scalar val = randomScalar(0.0, 255.0);
|
||||
|
||||
cv::cuda::GpuMat dst = createMat(size, type, useRoi);
|
||||
cv::cuda::warpAffine(loadMat(src, useRoi), dst, M, size, flags, borderType, val);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
warpAffineGold(src, M, inverse, size, dst_gold, interpolation, borderType, val);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-1 : 1.0);
|
||||
}
|
||||
|
||||
CUDA_TEST_P(WarpAffine, OverlapDetection)
|
||||
{
|
||||
cv::Mat src = randomMat(size, type);
|
||||
ASSERT_FALSE(src.empty());
|
||||
cv::cuda::GpuMat gpuSrc;
|
||||
gpuSrc.upload(src);
|
||||
|
||||
cv::Mat M = cv::Mat::eye(2, 3, CV_64FC1);
|
||||
int flags = interpolation;
|
||||
if (inverse)
|
||||
flags |= cv::WARP_INVERSE_MAP;
|
||||
|
||||
{
|
||||
cv::cuda::GpuMat gpuDst(gpuSrc, cv::Rect(0, 0, size.width, size.height));
|
||||
|
||||
EXPECT_THROW(
|
||||
cv::cuda::warpAffine(gpuSrc, gpuDst, M, size, flags, borderType, cv::Scalar::all(0)),
|
||||
cv::Exception);
|
||||
}
|
||||
|
||||
{
|
||||
cv::cuda::GpuMat gpuDst(size, gpuSrc.type());
|
||||
ASSERT_NE(gpuSrc.data, gpuDst.data); // Confirm they are distinct
|
||||
|
||||
EXPECT_NO_THROW({
|
||||
cv::cuda::warpAffine(gpuSrc, gpuDst, M, size, flags, borderType, cv::Scalar::all(0));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, WarpAffine, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
DIFFERENT_SIZES,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_16UC1), MatType(CV_16UC3), MatType(CV_16UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
DIRECT_INVERSE,
|
||||
testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
|
||||
testing::Values(BorderType(cv::BORDER_REFLECT101), BorderType(cv::BORDER_REPLICATE), BorderType(cv::BORDER_REFLECT), BorderType(cv::BORDER_WRAP)),
|
||||
WHOLE_SUBMAT));
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Test NPP
|
||||
|
||||
PARAM_TEST_CASE(WarpAffineNPP, cv::cuda::DeviceInfo, MatType, Inverse, Interpolation)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
int type;
|
||||
bool inverse;
|
||||
int interpolation;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
type = GET_PARAM(1);
|
||||
inverse = GET_PARAM(2);
|
||||
interpolation = GET_PARAM(3);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
CUDA_TEST_P(WarpAffineNPP, Accuracy)
|
||||
{
|
||||
cv::Mat src = readImageType("stereobp/aloe-L.png", type);
|
||||
ASSERT_FALSE(src.empty());
|
||||
|
||||
cv::Mat M = createTransformMatrix(src.size(), CV_PI / 4);
|
||||
int flags = interpolation;
|
||||
if (inverse)
|
||||
flags |= cv::WARP_INVERSE_MAP;
|
||||
|
||||
cv::cuda::GpuMat dst;
|
||||
cv::cuda::warpAffine(loadMat(src), dst, M, src.size(), flags);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
warpAffineGold(src, M, inverse, src.size(), dst_gold, interpolation, cv::BORDER_CONSTANT, cv::Scalar::all(0));
|
||||
|
||||
EXPECT_MAT_SIMILAR(dst_gold, dst, 2e-2);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, WarpAffineNPP, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
DIRECT_INVERSE,
|
||||
testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC))));
|
||||
|
||||
|
||||
}} // namespace
|
||||
#endif // HAVE_CUDA
|
||||
@@ -0,0 +1,285 @@
|
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
#ifdef HAVE_CUDA
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
namespace
|
||||
{
|
||||
cv::Mat createTransformMatrix(cv::Size srcSize, double angle)
|
||||
{
|
||||
cv::Mat M(3, 3, CV_64FC1);
|
||||
|
||||
M.at<double>(0, 0) = std::cos(angle); M.at<double>(0, 1) = -std::sin(angle); M.at<double>(0, 2) = srcSize.width / 2;
|
||||
M.at<double>(1, 0) = std::sin(angle); M.at<double>(1, 1) = std::cos(angle); M.at<double>(1, 2) = 0.0;
|
||||
M.at<double>(2, 0) = 0.0 ; M.at<double>(2, 1) = 0.0 ; M.at<double>(2, 2) = 1.0;
|
||||
|
||||
return M;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Test buildWarpPerspectiveMaps
|
||||
|
||||
PARAM_TEST_CASE(BuildWarpPerspectiveMaps, cv::cuda::DeviceInfo, cv::Size, Inverse)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
cv::Size size;
|
||||
bool inverse;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
size = GET_PARAM(1);
|
||||
inverse = GET_PARAM(2);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
CUDA_TEST_P(BuildWarpPerspectiveMaps, Accuracy)
|
||||
{
|
||||
cv::Mat M = createTransformMatrix(size, CV_PI / 4);
|
||||
|
||||
cv::cuda::GpuMat xmap, ymap;
|
||||
cv::cuda::buildWarpPerspectiveMaps(M, inverse, size, xmap, ymap);
|
||||
|
||||
cv::Mat src = randomMat(randomSize(200, 400), CV_8UC1);
|
||||
int interpolation = cv::INTER_NEAREST;
|
||||
int borderMode = cv::BORDER_CONSTANT;
|
||||
int flags = interpolation;
|
||||
if (inverse)
|
||||
flags |= cv::WARP_INVERSE_MAP;
|
||||
|
||||
cv::Mat dst;
|
||||
cv::remap(src, dst, cv::Mat(xmap), cv::Mat(ymap), interpolation, borderMode);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
cv::warpPerspective(src, dst_gold, M, size, flags, borderMode);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, 0.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, BuildWarpPerspectiveMaps, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
DIFFERENT_SIZES,
|
||||
DIRECT_INVERSE));
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Gold implementation
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename T, template <typename> class Interpolator> void warpPerspectiveImpl(const cv::Mat& src, const cv::Mat& M, cv::Size dsize, cv::Mat& dst, int borderType, cv::Scalar borderVal)
|
||||
{
|
||||
const int cn = src.channels();
|
||||
|
||||
dst.create(dsize, src.type());
|
||||
|
||||
for (int y = 0; y < dsize.height; ++y)
|
||||
{
|
||||
for (int x = 0; x < dsize.width; ++x)
|
||||
{
|
||||
float coeff = static_cast<float>(M.at<double>(2, 0) * x + M.at<double>(2, 1) * y + M.at<double>(2, 2));
|
||||
|
||||
float xcoo = static_cast<float>((M.at<double>(0, 0) * x + M.at<double>(0, 1) * y + M.at<double>(0, 2)) / coeff);
|
||||
float ycoo = static_cast<float>((M.at<double>(1, 0) * x + M.at<double>(1, 1) * y + M.at<double>(1, 2)) / coeff);
|
||||
|
||||
for (int c = 0; c < cn; ++c)
|
||||
dst.at<T>(y, x * cn + c) = Interpolator<T>::getValue(src, ycoo, xcoo, c, borderType, borderVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void warpPerspectiveGold(const cv::Mat& src, const cv::Mat& M, bool inverse, cv::Size dsize, cv::Mat& dst, int interpolation, int borderType, cv::Scalar borderVal)
|
||||
{
|
||||
typedef void (*func_t)(const cv::Mat& src, const cv::Mat& M, cv::Size dsize, cv::Mat& dst, int borderType, cv::Scalar borderVal);
|
||||
|
||||
static const func_t nearest_funcs[] =
|
||||
{
|
||||
warpPerspectiveImpl<unsigned char, NearestInterpolator>,
|
||||
warpPerspectiveImpl<signed char, NearestInterpolator>,
|
||||
warpPerspectiveImpl<unsigned short, NearestInterpolator>,
|
||||
warpPerspectiveImpl<short, NearestInterpolator>,
|
||||
warpPerspectiveImpl<int, NearestInterpolator>,
|
||||
warpPerspectiveImpl<float, NearestInterpolator>
|
||||
};
|
||||
|
||||
static const func_t linear_funcs[] =
|
||||
{
|
||||
warpPerspectiveImpl<unsigned char, LinearInterpolator>,
|
||||
warpPerspectiveImpl<signed char, LinearInterpolator>,
|
||||
warpPerspectiveImpl<unsigned short, LinearInterpolator>,
|
||||
warpPerspectiveImpl<short, LinearInterpolator>,
|
||||
warpPerspectiveImpl<int, LinearInterpolator>,
|
||||
warpPerspectiveImpl<float, LinearInterpolator>
|
||||
};
|
||||
|
||||
static const func_t cubic_funcs[] =
|
||||
{
|
||||
warpPerspectiveImpl<unsigned char, CubicInterpolator>,
|
||||
warpPerspectiveImpl<signed char, CubicInterpolator>,
|
||||
warpPerspectiveImpl<unsigned short, CubicInterpolator>,
|
||||
warpPerspectiveImpl<short, CubicInterpolator>,
|
||||
warpPerspectiveImpl<int, CubicInterpolator>,
|
||||
warpPerspectiveImpl<float, CubicInterpolator>
|
||||
};
|
||||
|
||||
static const func_t* funcs[] = {nearest_funcs, linear_funcs, cubic_funcs};
|
||||
|
||||
if (inverse)
|
||||
funcs[interpolation][src.depth()](src, M, dsize, dst, borderType, borderVal);
|
||||
else
|
||||
{
|
||||
cv::Mat iM;
|
||||
cv::invert(M, iM);
|
||||
funcs[interpolation][src.depth()](src, iM, dsize, dst, borderType, borderVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
PARAM_TEST_CASE(WarpPerspective, cv::cuda::DeviceInfo, cv::Size, MatType, Inverse, Interpolation, BorderType, UseRoi)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
cv::Size size;
|
||||
int type;
|
||||
bool inverse;
|
||||
int interpolation;
|
||||
int borderType;
|
||||
bool useRoi;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
size = GET_PARAM(1);
|
||||
type = GET_PARAM(2);
|
||||
inverse = GET_PARAM(3);
|
||||
interpolation = GET_PARAM(4);
|
||||
borderType = GET_PARAM(5);
|
||||
useRoi = GET_PARAM(6);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
CUDA_TEST_P(WarpPerspective, Accuracy)
|
||||
{
|
||||
cv::Mat src = randomMat(size, type);
|
||||
cv::Mat M = createTransformMatrix(size, CV_PI / 3);
|
||||
int flags = interpolation;
|
||||
if (inverse)
|
||||
flags |= cv::WARP_INVERSE_MAP;
|
||||
cv::Scalar val = randomScalar(0.0, 255.0);
|
||||
|
||||
cv::cuda::GpuMat dst = createMat(size, type, useRoi);
|
||||
cv::cuda::warpPerspective(loadMat(src, useRoi), dst, M, size, flags, borderType, val);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
warpPerspectiveGold(src, M, inverse, size, dst_gold, interpolation, borderType, val);
|
||||
|
||||
EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-1 : 1.0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, WarpPerspective, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
DIFFERENT_SIZES,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_16UC1), MatType(CV_16UC3), MatType(CV_16UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
DIRECT_INVERSE,
|
||||
testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
|
||||
testing::Values(BorderType(cv::BORDER_REFLECT101), BorderType(cv::BORDER_REPLICATE), BorderType(cv::BORDER_REFLECT), BorderType(cv::BORDER_WRAP)),
|
||||
WHOLE_SUBMAT));
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// Test NPP
|
||||
|
||||
PARAM_TEST_CASE(WarpPerspectiveNPP, cv::cuda::DeviceInfo, MatType, Inverse, Interpolation)
|
||||
{
|
||||
cv::cuda::DeviceInfo devInfo;
|
||||
int type;
|
||||
bool inverse;
|
||||
int interpolation;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
devInfo = GET_PARAM(0);
|
||||
type = GET_PARAM(1);
|
||||
inverse = GET_PARAM(2);
|
||||
interpolation = GET_PARAM(3);
|
||||
|
||||
cv::cuda::setDevice(devInfo.deviceID());
|
||||
}
|
||||
};
|
||||
|
||||
CUDA_TEST_P(WarpPerspectiveNPP, Accuracy)
|
||||
{
|
||||
cv::Mat src = readImageType("stereobp/aloe-L.png", type);
|
||||
ASSERT_FALSE(src.empty());
|
||||
|
||||
cv::Mat M = createTransformMatrix(src.size(), CV_PI / 4);
|
||||
int flags = interpolation;
|
||||
if (inverse)
|
||||
flags |= cv::WARP_INVERSE_MAP;
|
||||
|
||||
cv::cuda::GpuMat dst;
|
||||
cv::cuda::warpPerspective(loadMat(src), dst, M, src.size(), flags);
|
||||
|
||||
cv::Mat dst_gold;
|
||||
warpPerspectiveGold(src, M, inverse, src.size(), dst_gold, interpolation, cv::BORDER_CONSTANT, cv::Scalar::all(0));
|
||||
|
||||
EXPECT_MAT_SIMILAR(dst_gold, dst, 2e-2);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(CUDA_Warping, WarpPerspectiveNPP, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
|
||||
DIRECT_INVERSE,
|
||||
testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC))));
|
||||
|
||||
|
||||
}} // namespace
|
||||
#endif // HAVE_CUDA
|
||||
Reference in New Issue
Block a user