Merge branch 'master' of https://github.com/Itseez/opencv
Conflicts: modules/imgproc/src/sumpixels.cpp
This commit is contained in:
commit
1c15776cf5
2
3rdparty/include/opencl/1.2/CL/cl_platform.h
vendored
2
3rdparty/include/opencl/1.2/CL/cl_platform.h
vendored
@ -454,7 +454,7 @@ typedef unsigned int cl_GLenum;
|
||||
/* Define alignment keys */
|
||||
#if defined( __GNUC__ )
|
||||
#define CL_ALIGNED(_x) __attribute__ ((aligned(_x)))
|
||||
#elif defined( _WIN32) && (_MSC_VER)
|
||||
#elif defined( _WIN32) && defined(_MSC_VER)
|
||||
/* Alignment keys neutered on windows because MSVC can't swallow function arguments with alignment requirements */
|
||||
/* http://msdn.microsoft.com/en-us/library/373ak2y1%28VS.71%29.aspx */
|
||||
/* #include <crtdefs.h> */
|
||||
|
@ -116,6 +116,7 @@ endif()
|
||||
OCV_OPTION(WITH_1394 "Include IEEE1394 support" ON IF (NOT ANDROID AND NOT IOS) )
|
||||
OCV_OPTION(WITH_AVFOUNDATION "Use AVFoundation for Video I/O" ON IF IOS)
|
||||
OCV_OPTION(WITH_CARBON "Use Carbon for UI instead of Cocoa" OFF IF APPLE )
|
||||
OCV_OPTION(WITH_VTK "Include VTK library support (and build opencv_viz module eiher)" OFF IF (NOT ANDROID AND NOT IOS) )
|
||||
OCV_OPTION(WITH_CUDA "Include NVidia Cuda Runtime support" ON IF (NOT IOS) )
|
||||
OCV_OPTION(WITH_CUFFT "Include NVidia Cuda Fast Fourier Transform (FFT) library support" ON IF (NOT IOS) )
|
||||
OCV_OPTION(WITH_CUBLAS "Include NVidia Cuda Basic Linear Algebra Subprograms (BLAS) library support" OFF IF (NOT IOS) )
|
||||
@ -124,7 +125,7 @@ OCV_OPTION(WITH_EIGEN "Include Eigen2/Eigen3 support" ON)
|
||||
OCV_OPTION(WITH_VFW "Include Video for Windows support" ON IF WIN32 )
|
||||
OCV_OPTION(WITH_FFMPEG "Include FFMPEG support" ON IF (NOT ANDROID AND NOT IOS))
|
||||
OCV_OPTION(WITH_GSTREAMER "Include Gstreamer support" ON IF (UNIX AND NOT APPLE AND NOT ANDROID) )
|
||||
OCV_OPTION(WITH_GSTREAMER_1_X "Include Gstreamer 1.x support" OFF)
|
||||
OCV_OPTION(WITH_GSTREAMER_0_10 "Enable Gstreamer 0.10 support (instead of 1.x)" OFF )
|
||||
OCV_OPTION(WITH_GTK "Include GTK support" ON IF (UNIX AND NOT APPLE AND NOT ANDROID) )
|
||||
OCV_OPTION(WITH_IPP "Include Intel IPP support" OFF IF (MSVC OR X86 OR X86_64) )
|
||||
OCV_OPTION(WITH_JASPER "Include JPEG2K support" ON IF (NOT IOS) )
|
||||
@ -430,6 +431,8 @@ endif()
|
||||
# --- Matlab/Octave ---
|
||||
include(cmake/OpenCVFindMatlab.cmake)
|
||||
|
||||
include(cmake/OpenCVDetectVTK.cmake)
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Add CUDA libraries (needed for apps/tools, samples)
|
||||
# ----------------------------------------------------------------------------
|
||||
@ -659,6 +662,7 @@ else()
|
||||
endif()
|
||||
|
||||
status(" OpenGL support:" HAVE_OPENGL THEN "YES (${OPENGL_LIBRARIES})" ELSE NO)
|
||||
status(" VTK support:" HAVE_VTK THEN "YES (ver ${VTK_VERSION})" ELSE NO)
|
||||
|
||||
# ========================== MEDIA IO ==========================
|
||||
status("")
|
||||
|
@ -70,7 +70,7 @@ bool CvCascadeImageReader::NegReader::nextImg()
|
||||
_offset.x = std::min( (int)round % winSize.width, src.cols - winSize.width );
|
||||
_offset.y = std::min( (int)round / winSize.width, src.rows - winSize.height );
|
||||
if( !src.empty() && src.type() == CV_8UC1
|
||||
&& offset.x >= 0 && offset.y >= 0 )
|
||||
&& _offset.x >= 0 && _offset.y >= 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
|
21
cmake/OpenCVDetectVTK.cmake
Normal file
21
cmake/OpenCVDetectVTK.cmake
Normal file
@ -0,0 +1,21 @@
|
||||
if(NOT WITH_VTK OR ANDROID OR IOS)
|
||||
return()
|
||||
endif()
|
||||
|
||||
find_package(VTK 6.0 QUIET COMPONENTS vtkRenderingCore vtkInteractionWidgets vtkInteractionStyle vtkIOLegacy vtkIOPLY vtkRenderingFreeType vtkRenderingLOD vtkFiltersTexture NO_MODULE)
|
||||
|
||||
if(NOT DEFINED VTK_FOUND OR NOT VTK_FOUND)
|
||||
find_package(VTK 5.10 QUIET COMPONENTS vtkCommon vtkFiltering vtkRendering vtkWidgets vtkImaging NO_MODULE)
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED VTK_FOUND OR NOT VTK_FOUND)
|
||||
find_package(VTK 5.8 QUIET COMPONENTS vtkCommon vtkFiltering vtkRendering vtkWidgets vtkImaging NO_MODULE)
|
||||
endif()
|
||||
|
||||
if(VTK_FOUND)
|
||||
set(HAVE_VTK ON)
|
||||
message(STATUS "Found VTK ver. ${VTK_VERSION} (usefile: ${VTK_USE_FILE})")
|
||||
else()
|
||||
set(HAVE_VTK OFF)
|
||||
message(STATUS "VTK is not found. Please set -DVTK_DIR in CMake to VTK build directory, or set $VTK_DIR enviroment variable to VTK install subdirectory with VTKConfig.cmake file (for windows)")
|
||||
endif()
|
@ -12,28 +12,8 @@ endif(WITH_VFW)
|
||||
|
||||
# --- GStreamer ---
|
||||
ocv_clear_vars(HAVE_GSTREAMER)
|
||||
# try to find gstreamer 0.10 first
|
||||
if(WITH_GSTREAMER AND NOT WITH_GSTREAMER_1_X)
|
||||
CHECK_MODULE(gstreamer-base-0.10 HAVE_GSTREAMER_BASE)
|
||||
CHECK_MODULE(gstreamer-video-0.10 HAVE_GSTREAMER_VIDEO)
|
||||
CHECK_MODULE(gstreamer-app-0.10 HAVE_GSTREAMER_APP)
|
||||
CHECK_MODULE(gstreamer-riff-0.10 HAVE_GSTREAMER_RIFF)
|
||||
CHECK_MODULE(gstreamer-pbutils-0.10 HAVE_GSTREAMER_PBUTILS)
|
||||
|
||||
if(HAVE_GSTREAMER_BASE AND HAVE_GSTREAMER_VIDEO AND HAVE_GSTREAMER_APP AND HAVE_GSTREAMER_RIFF AND HAVE_GSTREAMER_PBUTILS)
|
||||
set(HAVE_GSTREAMER TRUE)
|
||||
set(GSTREAMER_BASE_VERSION ${ALIASOF_gstreamer-base-0.10_VERSION})
|
||||
set(GSTREAMER_VIDEO_VERSION ${ALIASOF_gstreamer-video-0.10_VERSION})
|
||||
set(GSTREAMER_APP_VERSION ${ALIASOF_gstreamer-app-0.10_VERSION})
|
||||
set(GSTREAMER_RIFF_VERSION ${ALIASOF_gstreamer-riff-0.10_VERSION})
|
||||
set(GSTREAMER_PBUTILS_VERSION ${ALIASOF_gstreamer-pbutils-0.10_VERSION})
|
||||
endif()
|
||||
|
||||
endif(WITH_GSTREAMER AND NOT WITH_GSTREAMER_1_X)
|
||||
|
||||
# if gstreamer 0.10 was not found, or we specified we wanted 1.x, try to find it
|
||||
if(WITH_GSTREAMER_1_X OR NOT HAVE_GSTREAMER)
|
||||
#check for 1.x
|
||||
# try to find gstreamer 1.x first
|
||||
if(WITH_GSTREAMER AND NOT WITH_GSTREAMER_0_10)
|
||||
CHECK_MODULE(gstreamer-base-1.0 HAVE_GSTREAMER_BASE)
|
||||
CHECK_MODULE(gstreamer-video-1.0 HAVE_GSTREAMER_VIDEO)
|
||||
CHECK_MODULE(gstreamer-app-1.0 HAVE_GSTREAMER_APP)
|
||||
@ -49,7 +29,25 @@ if(WITH_GSTREAMER_1_X OR NOT HAVE_GSTREAMER)
|
||||
set(GSTREAMER_PBUTILS_VERSION ${ALIASOF_gstreamer-pbutils-1.0_VERSION})
|
||||
endif()
|
||||
|
||||
endif(WITH_GSTREAMER_1_X OR NOT HAVE_GSTREAMER)
|
||||
endif(WITH_GSTREAMER AND NOT WITH_GSTREAMER_0_10)
|
||||
|
||||
# if gstreamer 1.x was not found, or we specified we wanted 0.10, try to find it
|
||||
if(WITH_GSTREAMER_0_10 OR NOT HAVE_GSTREAMER)
|
||||
CHECK_MODULE(gstreamer-base-0.10 HAVE_GSTREAMER_BASE)
|
||||
CHECK_MODULE(gstreamer-video-0.10 HAVE_GSTREAMER_VIDEO)
|
||||
CHECK_MODULE(gstreamer-app-0.10 HAVE_GSTREAMER_APP)
|
||||
CHECK_MODULE(gstreamer-riff-0.10 HAVE_GSTREAMER_RIFF)
|
||||
CHECK_MODULE(gstreamer-pbutils-0.10 HAVE_GSTREAMER_PBUTILS)
|
||||
|
||||
if(HAVE_GSTREAMER_BASE AND HAVE_GSTREAMER_VIDEO AND HAVE_GSTREAMER_APP AND HAVE_GSTREAMER_RIFF AND HAVE_GSTREAMER_PBUTILS)
|
||||
set(HAVE_GSTREAMER TRUE)
|
||||
set(GSTREAMER_BASE_VERSION ${ALIASOF_gstreamer-base-0.10_VERSION})
|
||||
set(GSTREAMER_VIDEO_VERSION ${ALIASOF_gstreamer-video-0.10_VERSION})
|
||||
set(GSTREAMER_APP_VERSION ${ALIASOF_gstreamer-app-0.10_VERSION})
|
||||
set(GSTREAMER_RIFF_VERSION ${ALIASOF_gstreamer-riff-0.10_VERSION})
|
||||
set(GSTREAMER_PBUTILS_VERSION ${ALIASOF_gstreamer-pbutils-0.10_VERSION})
|
||||
endif()
|
||||
endif(WITH_GSTREAMER_0_10 OR NOT HAVE_GSTREAMER)
|
||||
|
||||
# --- unicap ---
|
||||
ocv_clear_vars(HAVE_UNICAP)
|
||||
|
@ -485,6 +485,9 @@ macro(ocv_glob_module_sources)
|
||||
file(GLOB lib_hdrs "include/opencv2/*.hpp" "include/opencv2/${name}/*.hpp" "include/opencv2/${name}/*.h")
|
||||
file(GLOB lib_hdrs_detail "include/opencv2/${name}/detail/*.hpp" "include/opencv2/${name}/detail/*.h")
|
||||
|
||||
ocv_source_group("Src" DIRBASE "${CMAKE_CURRENT_SOURCE_DIR}/src" FILES ${lib_srcs} ${lib_int_hdrs})
|
||||
ocv_source_group("Include" DIRBASE "${CMAKE_CURRENT_SOURCE_DIR}/include" FILES ${lib_hdrs} ${lib_hdrs_detail})
|
||||
|
||||
file(GLOB lib_cuda_srcs "src/cuda/*.cu")
|
||||
set(cuda_objs "")
|
||||
set(lib_cuda_hdrs "")
|
||||
@ -493,11 +496,9 @@ macro(ocv_glob_module_sources)
|
||||
file(GLOB lib_cuda_hdrs "src/cuda/*.hpp")
|
||||
|
||||
ocv_cuda_compile(cuda_objs ${lib_cuda_srcs} ${lib_cuda_hdrs})
|
||||
source_group("Src\\Cuda" FILES ${lib_cuda_srcs} ${lib_cuda_hdrs})
|
||||
source_group("Src\\Cuda" FILES ${lib_cuda_srcs} ${lib_cuda_hdrs})
|
||||
endif()
|
||||
|
||||
source_group("Src" FILES ${lib_srcs} ${lib_int_hdrs})
|
||||
|
||||
file(GLOB cl_kernels "src/opencl/*.cl")
|
||||
if(cl_kernels)
|
||||
ocv_include_directories(${OPENCL_INCLUDE_DIRS})
|
||||
@ -506,15 +507,13 @@ macro(ocv_glob_module_sources)
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.hpp"
|
||||
COMMAND ${CMAKE_COMMAND} -DMODULE_NAME="${the_module_barename}" -DCL_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src/opencl" -DOUTPUT="${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" -P "${OpenCV_SOURCE_DIR}/cmake/cl2cpp.cmake"
|
||||
DEPENDS ${cl_kernels} "${OpenCV_SOURCE_DIR}/cmake/cl2cpp.cmake")
|
||||
source_group("OpenCL" FILES ${cl_kernels} "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.hpp")
|
||||
ocv_source_group("Src\\opencl\\kernels" FILES ${cl_kernels})
|
||||
ocv_source_group("Src\\opencl\\kernels\\autogenerated" FILES "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.hpp")
|
||||
list(APPEND lib_srcs ${cl_kernels} "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.cpp" "${CMAKE_CURRENT_BINARY_DIR}/opencl_kernels.hpp")
|
||||
endif()
|
||||
|
||||
ocv_set_module_sources(${ARGN} HEADERS ${lib_hdrs} ${lib_hdrs_detail}
|
||||
SOURCES ${lib_srcs} ${lib_int_hdrs} ${cuda_objs} ${lib_cuda_srcs} ${lib_cuda_hdrs})
|
||||
|
||||
source_group("Include" FILES ${lib_hdrs})
|
||||
source_group("Include\\detail" FILES ${lib_hdrs_detail})
|
||||
endmacro()
|
||||
|
||||
# creates OpenCV module in current folder
|
||||
@ -692,8 +691,8 @@ function(ocv_add_perf_tests)
|
||||
if(NOT OPENCV_PERF_${the_module}_SOURCES)
|
||||
file(GLOB_RECURSE perf_srcs "${perf_path}/*.cpp")
|
||||
file(GLOB_RECURSE perf_hdrs "${perf_path}/*.hpp" "${perf_path}/*.h")
|
||||
source_group("Src" FILES ${perf_srcs})
|
||||
source_group("Include" FILES ${perf_hdrs})
|
||||
ocv_source_group("Src" DIRBASE "${perf_path}" FILES ${perf_srcs})
|
||||
ocv_source_group("Include" DIRBASE "${perf_path}" FILES ${perf_hdrs})
|
||||
set(OPENCV_PERF_${the_module}_SOURCES ${perf_srcs} ${perf_hdrs})
|
||||
endif()
|
||||
|
||||
@ -742,8 +741,8 @@ function(ocv_add_accuracy_tests)
|
||||
if(NOT OPENCV_TEST_${the_module}_SOURCES)
|
||||
file(GLOB_RECURSE test_srcs "${test_path}/*.cpp")
|
||||
file(GLOB_RECURSE test_hdrs "${test_path}/*.hpp" "${test_path}/*.h")
|
||||
source_group("Src" FILES ${test_srcs})
|
||||
source_group("Include" FILES ${test_hdrs})
|
||||
ocv_source_group("Src" DIRBASE "${test_path}" FILES ${test_srcs})
|
||||
ocv_source_group("Include" DIRBASE "${test_path}" FILES ${test_hdrs})
|
||||
set(OPENCV_TEST_${the_module}_SOURCES ${test_srcs} ${test_hdrs})
|
||||
endif()
|
||||
|
||||
|
@ -1,3 +1,22 @@
|
||||
# Debugging function
|
||||
function(ocv_cmake_dump_vars)
|
||||
cmake_parse_arguments(DUMP "" "TOFILE" "" ${ARGN})
|
||||
set(regex "${DUMP_UNPARSED_ARGUMENTS}")
|
||||
get_cmake_property(_variableNames VARIABLES)
|
||||
set(VARS "")
|
||||
foreach(_variableName ${_variableNames})
|
||||
if(_variableName MATCHES "${regex}")
|
||||
set(VARS "${VARS}${_variableName}=${${_variableName}}\n")
|
||||
endif()
|
||||
endforeach()
|
||||
if(DUMP_TOFILE)
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/${DUMP_TOFILE} "${VARS}")
|
||||
else()
|
||||
message(AUTHOR_WARNING "${VARS}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
# Search packages for host system instead of packages for target system
|
||||
# in case of cross compilation thess macro should be defined by toolchain file
|
||||
if(NOT COMMAND find_host_package)
|
||||
@ -601,7 +620,35 @@ endmacro()
|
||||
################################################################################################
|
||||
# short command to setup source group
|
||||
function(ocv_source_group group)
|
||||
cmake_parse_arguments(OCV_SOURCE_GROUP "" "" "GLOB" ${ARGN})
|
||||
file(GLOB srcs ${OCV_SOURCE_GROUP_GLOB})
|
||||
source_group(${group} FILES ${srcs})
|
||||
cmake_parse_arguments(SG "" "DIRBASE" "GLOB;GLOB_RECURSE;FILES" ${ARGN})
|
||||
set(files "")
|
||||
if(SG_FILES)
|
||||
list(APPEND files ${SG_FILES})
|
||||
endif()
|
||||
if(SG_GLOB)
|
||||
file(GLOB srcs ${SG_GLOB})
|
||||
list(APPEND files ${srcs})
|
||||
endif()
|
||||
if(SG_GLOB_RECURSE)
|
||||
file(GLOB_RECURSE srcs ${SG_GLOB_RECURSE})
|
||||
list(APPEND files ${srcs})
|
||||
endif()
|
||||
if(SG_DIRBASE)
|
||||
foreach(f ${files})
|
||||
file(RELATIVE_PATH fpart "${SG_DIRBASE}" "${f}")
|
||||
if(fpart MATCHES "^\\.\\.")
|
||||
message(AUTHOR_WARNING "Can't detect subpath for source_group command: Group=${group} FILE=${f} DIRBASE=${SG_DIRBASE}")
|
||||
set(fpart "")
|
||||
else()
|
||||
get_filename_component(fpart "${fpart}" PATH)
|
||||
if(fpart)
|
||||
set(fpart "/${fpart}") # add '/'
|
||||
string(REPLACE "/" "\\" fpart "${fpart}")
|
||||
endif()
|
||||
endif()
|
||||
source_group("${group}${fpart}" FILES ${f})
|
||||
endforeach()
|
||||
else()
|
||||
source_group(${group} FILES ${files})
|
||||
endif()
|
||||
endfunction()
|
||||
|
@ -105,7 +105,7 @@ Building OpenCV
|
||||
Enable hardware optimizations
|
||||
-----------------------------
|
||||
|
||||
Depending on target platfrom architecture different instruction sets can be used. By default
|
||||
Depending on target platform architecture different instruction sets can be used. By default
|
||||
compiler generates code for armv5l without VFPv3 and NEON extensions. Add ``-DUSE_VFPV3=ON``
|
||||
to cmake command line to enable code generation for VFPv3 and ``-DUSE_NEON=ON`` for using
|
||||
NEON SIMD extensions.
|
||||
|
@ -79,3 +79,30 @@ TEST(Calib3d_Affine3f, accuracy)
|
||||
|
||||
ASSERT_LT(cv::norm(diff, cv::NORM_INF), 1e-15);
|
||||
}
|
||||
|
||||
TEST(Calib3d_Affine3f, accuracy_rvec)
|
||||
{
|
||||
cv::RNG rng;
|
||||
typedef float T;
|
||||
|
||||
cv::Affine3<T>::Vec3 w;
|
||||
cv::Affine3<T>::Mat3 u, vt, R;
|
||||
|
||||
for(int i = 0; i < 100; ++i)
|
||||
{
|
||||
rng.fill(R, cv::RNG::UNIFORM, -10, 10, true);
|
||||
cv::SVD::compute(R, w, u, vt, cv::SVD::FULL_UV + cv::SVD::MODIFY_A);
|
||||
R = u * vt;
|
||||
|
||||
//double s = (double)cv::getTickCount();
|
||||
cv::Affine3<T>::Vec3 va = cv::Affine3<T>(R).rvec();
|
||||
//std::cout << "M:" <<(cv::getTickCount() - s)*1000/cv::getTickFrequency() << std::endl;
|
||||
|
||||
cv::Affine3<T>::Vec3 vo;
|
||||
//s = (double)cv::getTickCount();
|
||||
cv::Rodrigues(R, vo);
|
||||
//std::cout << "O:" <<(cv::getTickCount() - s)*1000/cv::getTickFrequency() << std::endl;
|
||||
|
||||
ASSERT_LT(cv::norm(va - vo), 1e-9);
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@
|
||||
namespace cv
|
||||
{
|
||||
template<typename T>
|
||||
class CV_EXPORTS Affine3
|
||||
class Affine3
|
||||
{
|
||||
public:
|
||||
typedef T float_type;
|
||||
@ -97,6 +97,9 @@ namespace cv
|
||||
Mat3 linear() const;
|
||||
Vec3 translation() const;
|
||||
|
||||
//Rodrigues vector
|
||||
Vec3 rvec() const;
|
||||
|
||||
Affine3 inv(int method = cv::DECOMP_SVD) const;
|
||||
|
||||
// a.rotate(R) is equivalent to Affine(R, 0) * a;
|
||||
@ -158,9 +161,9 @@ cv::Affine3<T>::Affine3(const Mat3& R, const Vec3& t)
|
||||
}
|
||||
|
||||
template<typename T> inline
|
||||
cv::Affine3<T>::Affine3(const Vec3& rvec, const Vec3& t)
|
||||
cv::Affine3<T>::Affine3(const Vec3& _rvec, const Vec3& t)
|
||||
{
|
||||
rotation(rvec);
|
||||
rotation(_rvec);
|
||||
translation(t);
|
||||
matrix.val[12] = matrix.val[13] = matrix.val[14] = 0;
|
||||
matrix.val[15] = 1;
|
||||
@ -205,9 +208,9 @@ void cv::Affine3<T>::rotation(const Mat3& R)
|
||||
}
|
||||
|
||||
template<typename T> inline
|
||||
void cv::Affine3<T>::rotation(const Vec3& rvec)
|
||||
void cv::Affine3<T>::rotation(const Vec3& _rvec)
|
||||
{
|
||||
double rx = rvec[0], ry = rvec[1], rz = rvec[2];
|
||||
double rx = _rvec[0], ry = _rvec[1], rz = _rvec[2];
|
||||
double theta = std::sqrt(rx*rx + ry*ry + rz*rz);
|
||||
|
||||
if (theta < DBL_EPSILON)
|
||||
@ -250,9 +253,9 @@ void cv::Affine3<T>::rotation(const cv::Mat& data)
|
||||
}
|
||||
else if ((data.cols == 3 && data.rows == 1) || (data.cols == 1 && data.rows == 3))
|
||||
{
|
||||
Vec3 rvec;
|
||||
data.reshape(1, 3).copyTo(rvec);
|
||||
rotation(rvec);
|
||||
Vec3 _rvec;
|
||||
data.reshape(1, 3).copyTo(_rvec);
|
||||
rotation(_rvec);
|
||||
}
|
||||
else
|
||||
CV_Assert(!"Input marix can be 3x3, 1x3 or 3x1");
|
||||
@ -300,6 +303,55 @@ typename cv::Affine3<T>::Vec3 cv::Affine3<T>::translation() const
|
||||
return Vec3(matrix.val[3], matrix.val[7], matrix.val[11]);
|
||||
}
|
||||
|
||||
template<typename T> inline
|
||||
typename cv::Affine3<T>::Vec3 cv::Affine3<T>::rvec() const
|
||||
{
|
||||
cv::Vec3d w;
|
||||
cv::Matx33d u, vt, R = rotation();
|
||||
cv::SVD::compute(R, w, u, vt, cv::SVD::FULL_UV + cv::SVD::MODIFY_A);
|
||||
R = u * vt;
|
||||
|
||||
double rx = R.val[7] - R.val[5];
|
||||
double ry = R.val[2] - R.val[6];
|
||||
double rz = R.val[3] - R.val[1];
|
||||
|
||||
double s = std::sqrt((rx*rx + ry*ry + rz*rz)*0.25);
|
||||
double c = (R.val[0] + R.val[4] + R.val[8] - 1) * 0.5;
|
||||
c = c > 1.0 ? 1.0 : c < -1.0 ? -1.0 : c;
|
||||
double theta = acos(c);
|
||||
|
||||
if( s < 1e-5 )
|
||||
{
|
||||
if( c > 0 )
|
||||
rx = ry = rz = 0;
|
||||
else
|
||||
{
|
||||
double t;
|
||||
t = (R.val[0] + 1) * 0.5;
|
||||
rx = std::sqrt(std::max(t, 0.0));
|
||||
t = (R.val[4] + 1) * 0.5;
|
||||
ry = std::sqrt(std::max(t, 0.0)) * (R.val[1] < 0 ? -1.0 : 1.0);
|
||||
t = (R.val[8] + 1) * 0.5;
|
||||
rz = std::sqrt(std::max(t, 0.0)) * (R.val[2] < 0 ? -1.0 : 1.0);
|
||||
|
||||
if( fabs(rx) < fabs(ry) && fabs(rx) < fabs(rz) && (R.val[5] > 0) != (ry*rz > 0) )
|
||||
rz = -rz;
|
||||
theta /= std::sqrt(rx*rx + ry*ry + rz*rz);
|
||||
rx *= theta;
|
||||
ry *= theta;
|
||||
rz *= theta;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double vth = 1/(2*s);
|
||||
vth *= theta;
|
||||
rx *= vth; ry *= vth; rz *= vth;
|
||||
}
|
||||
|
||||
return cv::Vec3d(rx, ry, rz);
|
||||
}
|
||||
|
||||
template<typename T> inline
|
||||
cv::Affine3<T> cv::Affine3<T>::inv(int method) const
|
||||
{
|
||||
|
@ -129,6 +129,8 @@ public:
|
||||
virtual bool isContinuous(int i=-1) const;
|
||||
virtual bool empty() const;
|
||||
virtual void copyTo(const _OutputArray& arr) const;
|
||||
virtual size_t offset(int i=-1) const;
|
||||
virtual size_t step(int i=-1) const;
|
||||
bool isMat() const;
|
||||
bool isUMat() const;
|
||||
bool isMatVectot() const;
|
||||
|
@ -153,8 +153,8 @@ public:
|
||||
//! transpose the matrix
|
||||
Matx<_Tp, n, m> t() const;
|
||||
|
||||
//! invert matrix the matrix
|
||||
Matx<_Tp, n, m> inv(int method=DECOMP_LU) const;
|
||||
//! invert the matrix
|
||||
Matx<_Tp, n, m> inv(int method=DECOMP_LU, bool *p_is_ok = NULL) const;
|
||||
|
||||
//! solve linear system
|
||||
template<int l> Matx<_Tp, n, l> solve(const Matx<_Tp, m, l>& rhs, int flags=DECOMP_LU) const;
|
||||
|
@ -186,7 +186,7 @@ Matx<_Tp,m,n> Matx<_Tp,m,n>::randn(_Tp a, _Tp b)
|
||||
}
|
||||
|
||||
template<typename _Tp, int m, int n> inline
|
||||
Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method) const
|
||||
Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method, bool *p_is_ok /*= NULL*/) const
|
||||
{
|
||||
Matx<_Tp, n, m> b;
|
||||
bool ok;
|
||||
@ -197,6 +197,7 @@ Matx<_Tp, n, m> Matx<_Tp, m, n>::inv(int method) const
|
||||
Mat A(*this, false), B(b, false);
|
||||
ok = (invert(A, B, method) != 0);
|
||||
}
|
||||
if( NULL != p_is_ok ) { *p_is_ok = ok; }
|
||||
return ok ? b : Matx<_Tp, n, m>::zeros();
|
||||
}
|
||||
|
||||
@ -435,7 +436,7 @@ int print(const std::vector<Point3_<_Tp> >& vec, FILE* stream = stdout)
|
||||
template<typename _Tp, int m, int n> static inline
|
||||
int print(const Matx<_Tp, m, n>& matx, FILE* stream = stdout)
|
||||
{
|
||||
return print(Formatter::get()->format(matx), stream);
|
||||
return print(Formatter::get()->format(cv::Mat(matx)), stream);
|
||||
}
|
||||
|
||||
|
||||
|
@ -264,8 +264,50 @@ void cv::split(const Mat& src, Mat* mv)
|
||||
}
|
||||
}
|
||||
|
||||
namespace cv {
|
||||
|
||||
static bool ocl_split( InputArray _m, OutputArrayOfArrays _mv )
|
||||
{
|
||||
int type = _m.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
|
||||
String dstargs, dstdecl, processelem;
|
||||
for (int i = 0; i < cn; ++i)
|
||||
{
|
||||
dstargs += format("DECLARE_DST_PARAM(%d)", i);
|
||||
dstdecl += format("DECLARE_DATA(%d)", i);
|
||||
processelem += format("PROCESS_ELEM(%d)", i);
|
||||
}
|
||||
|
||||
ocl::Kernel k("split", ocl::core::split_merge_oclsrc,
|
||||
format("-D T=%s -D OP_SPLIT -D cn=%d -D DECLARE_DST_PARAMS=%s "
|
||||
"-D DECLARE_DATA_N=%s -D PROCESS_ELEMS_N=%s",
|
||||
ocl::memopTypeToStr(depth), cn, dstargs.c_str(),
|
||||
dstdecl.c_str(), processelem.c_str()));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
Size size = _m.size();
|
||||
std::vector<UMat> & dst = *(std::vector<UMat> *)_mv.getObj();
|
||||
dst.resize(cn);
|
||||
for (int i = 0; i < cn; ++i)
|
||||
dst[i].create(size, depth);
|
||||
|
||||
int argidx = k.set(0, ocl::KernelArg::ReadOnly(_m.getUMat()));
|
||||
for (int i = 0; i < cn; ++i)
|
||||
argidx = k.set(argidx, ocl::KernelArg::WriteOnlyNoSize(dst[i]));
|
||||
|
||||
size_t globalsize[2] = { size.width, size.height };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cv::split(InputArray _m, OutputArrayOfArrays _mv)
|
||||
{
|
||||
if (ocl::useOpenCL() && _m.dims() <= 2 && _mv.isUMatVector() &&
|
||||
ocl_split(_m, _mv))
|
||||
return;
|
||||
|
||||
Mat m = _m.getMat();
|
||||
if( m.empty() )
|
||||
{
|
||||
@ -353,8 +395,58 @@ void cv::merge(const Mat* mv, size_t n, OutputArray _dst)
|
||||
}
|
||||
}
|
||||
|
||||
namespace cv {
|
||||
|
||||
static bool ocl_merge( InputArrayOfArrays _mv, OutputArray _dst )
|
||||
{
|
||||
const std::vector<UMat> & src = *(const std::vector<UMat> *)(_mv.getObj());
|
||||
CV_Assert(!src.empty());
|
||||
|
||||
int type = src[0].type(), depth = CV_MAT_DEPTH(type);
|
||||
Size size = src[0].size();
|
||||
|
||||
size_t srcsize = src.size();
|
||||
for (size_t i = 0; i < srcsize; ++i)
|
||||
{
|
||||
int itype = src[i].type(), icn = CV_MAT_CN(itype), idepth = CV_MAT_DEPTH(itype);
|
||||
if (src[i].dims > 2 || icn != 1)
|
||||
return false;
|
||||
CV_Assert(size == src[i].size() && depth == idepth);
|
||||
}
|
||||
|
||||
String srcargs, srcdecl, processelem;
|
||||
for (size_t i = 0; i < srcsize; ++i)
|
||||
{
|
||||
srcargs += format("DECLARE_SRC_PARAM(%d)", i);
|
||||
srcdecl += format("DECLARE_DATA(%d)", i);
|
||||
processelem += format("PROCESS_ELEM(%d)", i);
|
||||
}
|
||||
|
||||
ocl::Kernel k("merge", ocl::core::split_merge_oclsrc,
|
||||
format("-D OP_MERGE -D cn=%d -D T=%s -D DECLARE_SRC_PARAMS_N=%s -D DECLARE_DATA_N=%s -D PROCESS_ELEMS_N=%s",
|
||||
(int)srcsize, ocl::memopTypeToStr(depth), srcargs.c_str(), srcdecl.c_str(), processelem.c_str()));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
_dst.create(size, CV_MAKE_TYPE(depth, (int)srcsize));
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
int argidx = 0;
|
||||
for (size_t i = 0; i < srcsize; ++i)
|
||||
argidx = k.set(argidx, ocl::KernelArg::ReadOnlyNoSize(src[i]));
|
||||
k.set(argidx, ocl::KernelArg::WriteOnly(dst));
|
||||
|
||||
size_t globalsize[2] = { dst.cols, dst.rows };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cv::merge(InputArrayOfArrays _mv, OutputArray _dst)
|
||||
{
|
||||
if (ocl::useOpenCL() && _mv.isUMatVector() && _dst.isUMat() && ocl_merge(_mv, _dst))
|
||||
return;
|
||||
|
||||
std::vector<Mat> mv;
|
||||
_mv.getMatVector(mv);
|
||||
merge(!mv.empty() ? &mv[0] : 0, mv.size(), _dst);
|
||||
@ -1214,9 +1306,10 @@ namespace cv {
|
||||
|
||||
static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst)
|
||||
{
|
||||
int dcn = _dst.channels(), lcn = _lut.channels(), dtype = _dst.type();
|
||||
int dtype = _dst.type(), lcn = _lut.channels(), dcn = CV_MAT_CN(dtype), ddepth = CV_MAT_DEPTH(dtype);
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
|
||||
if (_src.dims() > 2)
|
||||
if (_src.dims() > 2 || (!doubleSupport && ddepth == CV_64F))
|
||||
return false;
|
||||
|
||||
UMat src = _src.getUMat(), lut = _lut.getUMat();
|
||||
@ -1224,8 +1317,9 @@ static bool ocl_LUT(InputArray _src, InputArray _lut, OutputArray _dst)
|
||||
UMat dst = _dst.getUMat();
|
||||
|
||||
ocl::Kernel k("LUT", ocl::core::lut_oclsrc,
|
||||
format("-D dcn=%d -D lcn=%d -D srcT=%s -D dstT=%s", dcn, lcn,
|
||||
ocl::typeToStr(src.depth()), ocl::typeToStr(dst.depth())));
|
||||
format("-D dcn=%d -D lcn=%d -D srcT=%s -D dstT=%s%s", dcn, lcn,
|
||||
ocl::typeToStr(src.depth()), ocl::typeToStr(ddepth),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::ReadOnlyNoSize(lut),
|
||||
ocl::KernelArg::WriteOnly(dst));
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
// 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
|
||||
//
|
||||
@ -478,11 +477,59 @@ flipVert( const uchar* src0, size_t sstep, uchar* dst0, size_t dstep, Size size,
|
||||
}
|
||||
}
|
||||
|
||||
enum { FLIP_COLS = 1 << 0, FLIP_ROWS = 1 << 1, FLIP_BOTH = FLIP_ROWS | FLIP_COLS };
|
||||
|
||||
static bool ocl_flip(InputArray _src, OutputArray _dst, int flipCode )
|
||||
{
|
||||
int type = _src.type(), cn = CV_MAT_CN(type);
|
||||
|
||||
if (cn > 4 || cn == 3)
|
||||
return false;
|
||||
|
||||
const char * kernelName;
|
||||
int flipType;
|
||||
|
||||
if (flipCode == 0)
|
||||
kernelName = "arithm_flip_rows", flipType = FLIP_ROWS;
|
||||
else if (flipCode > 0)
|
||||
kernelName = "arithm_flip_cols", flipType = FLIP_COLS;
|
||||
else
|
||||
kernelName = "arithm_flip_rows_cols", flipType = FLIP_BOTH;
|
||||
|
||||
Size size = _src.size();
|
||||
int cols = size.width, rows = size.height;
|
||||
if ((cols == 1 && flipType == FLIP_COLS) ||
|
||||
(rows == 1 && flipType == FLIP_ROWS) ||
|
||||
(rows == 1 && cols == 1 && flipType == FLIP_BOTH))
|
||||
{
|
||||
_src.copyTo(_dst);
|
||||
return true;
|
||||
}
|
||||
|
||||
ocl::Kernel k(kernelName, ocl::core::flip_oclsrc,
|
||||
format( "-D type=%s", ocl::memopTypeToStr(type)));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
_dst.create(size, type);
|
||||
UMat src = _src.getUMat(), dst = _dst.getUMat();
|
||||
|
||||
cols = flipType == FLIP_COLS ? ((cols+1)/2) : cols;
|
||||
rows = flipType & FLIP_ROWS ? ((rows+1)/2) : rows;
|
||||
|
||||
size_t globalsize[2] = { cols, rows };
|
||||
return k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst), rows, cols).run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
void flip( InputArray _src, OutputArray _dst, int flip_mode )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
CV_Assert( _src.dims() <= 2 );
|
||||
|
||||
CV_Assert( src.dims <= 2 );
|
||||
bool use_opencl = ocl::useOpenCL() && _dst.isUMat();
|
||||
if ( use_opencl && ocl_flip(_src,_dst, flip_mode))
|
||||
return;
|
||||
|
||||
Mat src = _src.getMat();
|
||||
_dst.create( src.size(), src.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
size_t esz = src.elemSize();
|
||||
|
@ -1792,6 +1792,99 @@ bool _InputArray::isContinuous(int i) const
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t _InputArray::offset(int i) const
|
||||
{
|
||||
int k = kind();
|
||||
|
||||
if( k == MAT )
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
const Mat * const m = ((const Mat*)obj);
|
||||
return (size_t)(m->data - m->datastart);
|
||||
}
|
||||
|
||||
if( k == UMAT )
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
return ((const UMat*)obj)->offset;
|
||||
}
|
||||
|
||||
if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR)
|
||||
return 0;
|
||||
|
||||
if( k == STD_VECTOR_MAT )
|
||||
{
|
||||
const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
|
||||
if( i < 0 )
|
||||
return 1;
|
||||
CV_Assert( i < (int)vv.size() );
|
||||
|
||||
return (size_t)(vv[i].data - vv[i].datastart);
|
||||
}
|
||||
|
||||
if( k == STD_VECTOR_UMAT )
|
||||
{
|
||||
const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
|
||||
CV_Assert((size_t)i < vv.size());
|
||||
return vv[i].offset;
|
||||
}
|
||||
|
||||
if( k == GPU_MAT )
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
const cuda::GpuMat * const m = ((const cuda::GpuMat*)obj);
|
||||
return (size_t)(m->data - m->datastart);
|
||||
}
|
||||
|
||||
CV_Error(Error::StsNotImplemented, "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t _InputArray::step(int i) const
|
||||
{
|
||||
int k = kind();
|
||||
|
||||
if( k == MAT )
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
return ((const Mat*)obj)->step;
|
||||
}
|
||||
|
||||
if( k == UMAT )
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
return ((const UMat*)obj)->step;
|
||||
}
|
||||
|
||||
if( k == EXPR || k == MATX || k == STD_VECTOR || k == NONE || k == STD_VECTOR_VECTOR)
|
||||
return 0;
|
||||
|
||||
if( k == STD_VECTOR_MAT )
|
||||
{
|
||||
const std::vector<Mat>& vv = *(const std::vector<Mat>*)obj;
|
||||
if( i < 0 )
|
||||
return 1;
|
||||
CV_Assert( i < (int)vv.size() );
|
||||
return vv[i].step;
|
||||
}
|
||||
|
||||
if( k == STD_VECTOR_UMAT )
|
||||
{
|
||||
const std::vector<UMat>& vv = *(const std::vector<UMat>*)obj;
|
||||
CV_Assert((size_t)i < vv.size());
|
||||
return vv[i].step;
|
||||
}
|
||||
|
||||
if( k == GPU_MAT )
|
||||
{
|
||||
CV_Assert( i < 0 );
|
||||
return ((const cuda::GpuMat*)obj)->step;
|
||||
}
|
||||
|
||||
CV_Error(Error::StsNotImplemented, "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _InputArray::copyTo(const _OutputArray& arr) const
|
||||
{
|
||||
int k = kind();
|
||||
|
@ -1932,10 +1932,15 @@ struct Queue::Impl
|
||||
|
||||
~Impl()
|
||||
{
|
||||
if(handle)
|
||||
#ifdef _WIN32
|
||||
if (!cv::__termination)
|
||||
#endif
|
||||
{
|
||||
clFinish(handle);
|
||||
clReleaseCommandQueue(handle);
|
||||
if(handle)
|
||||
{
|
||||
clFinish(handle);
|
||||
clReleaseCommandQueue(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2379,7 +2384,7 @@ struct Program::Impl
|
||||
size_t retsz = 0;
|
||||
retval = clGetProgramBuildInfo(handle, (cl_device_id)deviceList[0],
|
||||
CL_PROGRAM_BUILD_LOG, 0, 0, &retsz);
|
||||
if( retval >= 0 && retsz > 0 )
|
||||
if( retval >= 0 && retsz > 1 )
|
||||
{
|
||||
AutoBuffer<char> bufbuf(retsz + 16);
|
||||
char* buf = bufbuf;
|
||||
|
@ -58,10 +58,10 @@
|
||||
*/
|
||||
|
||||
#ifdef DOUBLE_SUPPORT
|
||||
#ifdef cl_khr_fp64
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#elif defined (cl_amd_fp64)
|
||||
#ifdef cl_amd_fp64
|
||||
#pragma OPENCL EXTENSION cl_amd_fp64:enable
|
||||
#elif defined cl_khr_fp64
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
#define CV_EPSILON DBL_EPSILON
|
||||
#define CV_PI M_PI
|
||||
@ -76,12 +76,18 @@
|
||||
|
||||
#ifndef workT
|
||||
|
||||
#ifndef srcT1
|
||||
#define srcT1 dstT
|
||||
#endif
|
||||
#ifndef srcT2
|
||||
#define srcT2 dstT
|
||||
#endif
|
||||
#define workT dstT
|
||||
#define srcelem1 *(__global dstT*)(srcptr1 + src1_index)
|
||||
#define srcelem2 *(__global dstT*)(srcptr2 + src2_index)
|
||||
#define srcelem1 *(__global srcT1*)(srcptr1 + src1_index)
|
||||
#define srcelem2 *(__global srcT2*)(srcptr2 + src2_index)
|
||||
#ifndef convertToDT
|
||||
#define convertToDT noconvert
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
@ -160,6 +166,11 @@
|
||||
#elif defined OP_MAG
|
||||
#define PROCESS_ELEM dstelem = hypot(srcelem1, srcelem2)
|
||||
|
||||
#elif defined OP_ABS_NOSAT
|
||||
#define PROCESS_ELEM \
|
||||
dstT v = convertToDT(srcelem1); \
|
||||
dstelem = v >= 0 ? v : -v
|
||||
|
||||
#elif defined OP_PHASE_RADIANS
|
||||
#define PROCESS_ELEM \
|
||||
workT tmp = atan2(srcelem2, srcelem1); \
|
||||
|
102
modules/core/src/opencl/flip.cl
Normal file
102
modules/core/src/opencl/flip.cl
Normal file
@ -0,0 +1,102 @@
|
||||
/*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) 2013, OpenCV Foundation, 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 OpenCV Foundation 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*/
|
||||
|
||||
#define sizeoftype ((int)sizeof(type))
|
||||
|
||||
__kernel void arithm_flip_rows(__global const uchar* srcptr, int srcstep, int srcoffset,
|
||||
__global uchar* dstptr, int dststep, int dstoffset,
|
||||
int rows, int cols, int thread_rows, int thread_cols)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < cols && y < thread_rows)
|
||||
{
|
||||
__global const type* src0 = (__global const type*)(srcptr + mad24(y, srcstep, srcoffset + x * sizeoftype));
|
||||
__global const type* src1 = (__global const type*)(srcptr + mad24(rows - y - 1, srcstep, srcoffset + x * sizeoftype));
|
||||
|
||||
__global type* dst0 = (__global type*)(dstptr + mad24(y, dststep, dstoffset + x * sizeoftype));
|
||||
__global type* dst1 = (__global type*)(dstptr + mad24(rows - y - 1, dststep, dstoffset + x * sizeoftype));
|
||||
|
||||
dst0[0] = src1[0];
|
||||
dst1[0] = src0[0];
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void arithm_flip_rows_cols(__global const uchar* srcptr, int srcstep, int srcoffset,
|
||||
__global uchar* dstptr, int dststep, int dstoffset,
|
||||
int rows, int cols, int thread_rows, int thread_cols)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < cols && y < thread_rows)
|
||||
{
|
||||
__global const type* src0 = (__global const type*)(srcptr + mad24(y, srcstep, x*sizeoftype + srcoffset));
|
||||
__global const type* src1 = (__global const type*)(srcptr + mad24(rows - y - 1, srcstep, (cols - x - 1)*sizeoftype + srcoffset));
|
||||
|
||||
__global type* dst0 = (__global type*)(dstptr + mad24(rows - y - 1, dststep, (cols - x - 1)*sizeoftype + dstoffset));
|
||||
__global type* dst1 = (__global type*)(dstptr + mad24(y, dststep, x * sizeoftype + dstoffset));
|
||||
|
||||
dst0[0] = src0[0];
|
||||
dst1[0] = src1[0];
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void arithm_flip_cols(__global const uchar* srcptr, int srcstep, int srcoffset,
|
||||
__global uchar* dstptr, int dststep, int dstoffset,
|
||||
int rows, int cols, int thread_rows, int thread_cols)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < thread_cols && y < rows)
|
||||
{
|
||||
__global const type* src0 = (__global const type*)(srcptr + mad24(y, srcstep, x * sizeoftype + srcoffset));
|
||||
__global const type* src1 = (__global const type*)(srcptr + mad24(y, srcstep, (cols - x - 1)*sizeoftype + srcoffset));
|
||||
|
||||
__global type* dst0 = (__global type*)(dstptr + mad24(y, dststep, (cols - x - 1)*sizeoftype + dstoffset));
|
||||
__global type* dst1 = (__global type*)(dstptr + mad24(y, dststep, x * sizeoftype + dstoffset));
|
||||
|
||||
dst1[0] = src1[0];
|
||||
dst0[0] = src0[0];
|
||||
}
|
||||
}
|
88
modules/core/src/opencl/split_merge.cl
Normal file
88
modules/core/src/opencl/split_merge.cl
Normal file
@ -0,0 +1,88 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2013, OpenCV Foundation, 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 copyright holders 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*/
|
||||
|
||||
#ifdef OP_MERGE
|
||||
|
||||
#define DECLARE_SRC_PARAM(index) __global const uchar * src##index##ptr, int src##index##_step, int src##index##_offset,
|
||||
#define DECLARE_DATA(index) __global const T * src##index = \
|
||||
(__global T *)(src##index##ptr + mad24(src##index##_step, y, x * (int)sizeof(T) + src##index##_offset));
|
||||
#define PROCESS_ELEM(index) dst[index] = src##index[0];
|
||||
|
||||
__kernel void merge(DECLARE_SRC_PARAMS_N
|
||||
__global uchar * dstptr, int dst_step, int dst_offset,
|
||||
int rows, int cols)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < cols && y < rows)
|
||||
{
|
||||
DECLARE_DATA_N
|
||||
__global T * dst = (__global T *)(dstptr + mad24(dst_step, y, x * (int)sizeof(T) * cn + dst_offset));
|
||||
PROCESS_ELEMS_N
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined OP_SPLIT
|
||||
|
||||
#define DECLARE_DST_PARAM(index) , __global uchar * dst##index##ptr, int dst##index##_step, int dst##index##_offset
|
||||
#define DECLARE_DATA(index) __global T * dst##index = \
|
||||
(__global T *)(dst##index##ptr + mad24(y, dst##index##_step, x * (int)sizeof(T) + dst##index##_offset));
|
||||
#define PROCESS_ELEM(index) dst##index[0] = src[index];
|
||||
|
||||
__kernel void split(__global uchar* srcptr, int src_step, int src_offset, int rows, int cols DECLARE_DST_PARAMS)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < cols && y < rows)
|
||||
{
|
||||
DECLARE_DATA_N
|
||||
__global const T * src = (__global const T *)(srcptr + mad24(y, src_step, x * cn * (int)sizeof(T) + src_offset));
|
||||
PROCESS_ELEMS_N
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#error "No operation"
|
||||
#endif
|
@ -249,6 +249,9 @@ namespace ocl
|
||||
MatAllocator* getOpenCLAllocator();
|
||||
}
|
||||
|
||||
extern bool __termination; // skip some cleanups, because process is terminating
|
||||
// (for example, if ExitProcess() was already called)
|
||||
|
||||
}
|
||||
|
||||
#endif /*_CXCORE_INTERNAL_H_*/
|
||||
|
@ -1760,15 +1760,76 @@ static NormDiffFunc getNormDiffFunc(int normType, int depth)
|
||||
|
||||
}
|
||||
|
||||
namespace cv {
|
||||
|
||||
static bool ocl_norm( InputArray _src, int normType, double & result )
|
||||
{
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
|
||||
if ( !(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2) ||
|
||||
(!doubleSupport && depth == CV_64F))
|
||||
return false;
|
||||
|
||||
UMat src = _src.getUMat();
|
||||
|
||||
if (normType == NORM_INF)
|
||||
{
|
||||
UMat abssrc;
|
||||
|
||||
if (depth != CV_8U && depth != CV_16U)
|
||||
{
|
||||
int wdepth = std::max(CV_32S, depth);
|
||||
char cvt[50];
|
||||
|
||||
ocl::Kernel kabs("KF", ocl::core::arithm_oclsrc,
|
||||
format("-D UNARY_OP -D OP_ABS_NOSAT -D dstT=%s -D srcT1=%s -D convertToDT=%s%s",
|
||||
ocl::typeToStr(wdepth), ocl::typeToStr(depth),
|
||||
ocl::convertTypeStr(depth, wdepth, 1, cvt),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
|
||||
if (kabs.empty())
|
||||
return false;
|
||||
|
||||
abssrc.create(src.size(), CV_MAKE_TYPE(wdepth, cn));
|
||||
kabs.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(abssrc, cn));
|
||||
|
||||
size_t globalsize[2] = { src.cols * cn, src.rows };
|
||||
if (!kabs.run(2, globalsize, NULL, false))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
abssrc = src;
|
||||
|
||||
cv::minMaxIdx(abssrc.reshape(1), NULL, &result);
|
||||
}
|
||||
else if (normType == NORM_L1 || normType == NORM_L2)
|
||||
{
|
||||
Scalar s;
|
||||
bool unstype = depth == CV_8U || depth == CV_16U;
|
||||
|
||||
ocl_sum(src.reshape(1), s, normType == NORM_L2 ?
|
||||
OCL_OP_SUM_SQR : (unstype ? OCL_OP_SUM : OCL_OP_SUM_ABS) );
|
||||
result = normType == NORM_L1 ? s[0] : std::sqrt(s[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
double cv::norm( InputArray _src, int normType, InputArray _mask )
|
||||
{
|
||||
Mat src = _src.getMat(), mask = _mask.getMat();
|
||||
int depth = src.depth(), cn = src.channels();
|
||||
|
||||
normType &= 7;
|
||||
normType &= NORM_TYPE_MASK;
|
||||
CV_Assert( normType == NORM_INF || normType == NORM_L1 ||
|
||||
normType == NORM_L2 || normType == NORM_L2SQR ||
|
||||
((normType == NORM_HAMMING || normType == NORM_HAMMING2) && src.type() == CV_8U) );
|
||||
((normType == NORM_HAMMING || normType == NORM_HAMMING2) && _src.type() == CV_8U) );
|
||||
|
||||
double _result = 0;
|
||||
if (ocl::useOpenCL() && _mask.empty() && _src.isUMat() && _src.dims() <= 2 && ocl_norm(_src, normType, _result))
|
||||
return _result;
|
||||
|
||||
Mat src = _src.getMat(), mask = _mask.getMat();
|
||||
int depth = src.depth(), cn = src.channels();
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
size_t total_size = src.total();
|
||||
@ -2047,9 +2108,56 @@ double cv::norm( InputArray _src, int normType, InputArray _mask )
|
||||
return result.d;
|
||||
}
|
||||
|
||||
namespace cv {
|
||||
|
||||
static bool ocl_norm( InputArray _src1, InputArray _src2, int normType, double & result )
|
||||
{
|
||||
int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
bool relative = (normType & NORM_RELATIVE) != 0;
|
||||
normType &= ~NORM_RELATIVE;
|
||||
|
||||
if ( !(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2) ||
|
||||
(!doubleSupport && depth == CV_64F))
|
||||
return false;
|
||||
|
||||
int wdepth = std::max(CV_32S, depth);
|
||||
char cvt[50];
|
||||
ocl::Kernel k("KF", ocl::core::arithm_oclsrc,
|
||||
format("-D BINARY_OP -D OP_ABSDIFF -D dstT=%s -D workT=dstT -D srcT1=%s -D srcT2=srcT1"
|
||||
" -D convertToDT=%s -D convertToWT1=convertToDT -D convertToWT2=convertToDT%s",
|
||||
ocl::typeToStr(wdepth), ocl::typeToStr(depth),
|
||||
ocl::convertTypeStr(depth, wdepth, 1, cvt),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : ""));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat src1 = _src1.getUMat(), src2 = _src2.getUMat(), diff(src1.size(), CV_MAKE_TYPE(wdepth, cn));
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(src1), ocl::KernelArg::ReadOnlyNoSize(src2),
|
||||
ocl::KernelArg::WriteOnly(diff, cn));
|
||||
|
||||
size_t globalsize[2] = { diff.cols * cn, diff.rows };
|
||||
if (!k.run(2, globalsize, NULL, false))
|
||||
return false;
|
||||
|
||||
result = cv::norm(diff, normType);
|
||||
if (relative)
|
||||
result /= cv::norm(src2, normType) + DBL_EPSILON;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask )
|
||||
{
|
||||
CV_Assert( _src1.size() == _src2.size() && _src1.type() == _src2.type() );
|
||||
|
||||
double _result = 0;
|
||||
if (ocl::useOpenCL() && _mask.empty() && _src1.isUMat() && _src2.isUMat() &&
|
||||
_src1.dims() <= 2 && _src2.dims() <= 2 && ocl_norm(_src1, _src2, normType, _result))
|
||||
return _result;
|
||||
|
||||
if( normType & CV_RELATIVE )
|
||||
{
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
@ -2135,7 +2243,7 @@ double cv::norm( InputArray _src1, InputArray _src2, int normType, InputArray _m
|
||||
Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat();
|
||||
int depth = src1.depth(), cn = src1.channels();
|
||||
|
||||
CV_Assert( src1.size == src2.size && src1.type() == src2.type() );
|
||||
CV_Assert( src1.size == src2.size );
|
||||
|
||||
normType &= 7;
|
||||
CV_Assert( normType == NORM_INF || normType == NORM_L1 ||
|
||||
|
@ -734,18 +734,23 @@ cvErrorFromIppStatus( int status )
|
||||
}
|
||||
}
|
||||
|
||||
namespace cv {
|
||||
bool __termination = false;
|
||||
}
|
||||
|
||||
#if defined CVAPI_EXPORTS && defined WIN32 && !defined WINCE
|
||||
#ifdef HAVE_WINRT
|
||||
#pragma warning(disable:4447) // Disable warning 'main' signature found without threading model
|
||||
#endif
|
||||
|
||||
BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID );
|
||||
BOOL WINAPI DllMain( HINSTANCE, DWORD, LPVOID );
|
||||
|
||||
BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID )
|
||||
BOOL WINAPI DllMain( HINSTANCE, DWORD fdwReason, LPVOID lpReserved )
|
||||
{
|
||||
if( fdwReason == DLL_THREAD_DETACH || fdwReason == DLL_PROCESS_DETACH )
|
||||
{
|
||||
if (lpReserved != NULL) // called after ExitProcess() call
|
||||
cv::__termination = true;
|
||||
cv::deleteThreadAllocData();
|
||||
cv::deleteThreadData();
|
||||
}
|
||||
|
@ -92,8 +92,7 @@ PARAM_TEST_CASE(Lut, MatDepth, MatDepth, Channels, bool, bool)
|
||||
|
||||
void Near(double threshold = 0.)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst, udst, threshold);
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold)
|
||||
}
|
||||
};
|
||||
|
||||
@ -165,14 +164,12 @@ PARAM_TEST_CASE(ArithmTestBase, MatDepth, Channels, bool)
|
||||
|
||||
void Near(double threshold = 0.)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst1, udst1, threshold);
|
||||
EXPECT_MAT_NEAR(dst1_roi, udst1_roi, threshold);
|
||||
OCL_EXPECT_MATS_NEAR(dst1, threshold)
|
||||
}
|
||||
|
||||
void Near1(double threshold = 0.)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst2, udst2, threshold);
|
||||
EXPECT_MAT_NEAR(dst2_roi, udst2_roi, threshold);
|
||||
OCL_EXPECT_MATS_NEAR(dst2, threshold)
|
||||
}
|
||||
};
|
||||
|
||||
@ -532,8 +529,7 @@ OCL_TEST_P(Transpose, SquareInplace)
|
||||
OCL_OFF(cv::transpose(src1_roi, src1_roi));
|
||||
OCL_ON(cv::transpose(usrc1_roi, usrc1_roi));
|
||||
|
||||
EXPECT_MAT_NEAR(src1, usrc1, 0.0);
|
||||
EXPECT_MAT_NEAR(src1_roi, usrc1_roi, 0.0);
|
||||
OCL_EXPECT_MATS_NEAR(src1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -795,8 +791,8 @@ struct RepeatTestCase :
|
||||
{
|
||||
const int type = CV_MAKE_TYPE(depth, cn);
|
||||
|
||||
nx = 2;//randomInt(1, 4);
|
||||
ny = 2;//randomInt(1, 4);
|
||||
nx = randomInt(1, 4);
|
||||
ny = randomInt(1, 4);
|
||||
|
||||
Size srcRoiSize = randomSize(1, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
@ -813,7 +809,7 @@ struct RepeatTestCase :
|
||||
|
||||
typedef RepeatTestCase Repeat;
|
||||
|
||||
OCL_TEST_P(Repeat, DISABLED_Mat)
|
||||
OCL_TEST_P(Repeat, Mat)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
@ -964,6 +960,148 @@ OCL_TEST_P(Magnitude, Mat)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////// Flip /////////////////////////////////////////////////
|
||||
|
||||
typedef ArithmTestBase Flip;
|
||||
|
||||
OCL_TEST_P(Flip, X)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
OCL_OFF(cv::flip(src1_roi, dst1_roi, 0));
|
||||
OCL_ON(cv::flip(usrc1_roi, udst1_roi, 0));
|
||||
Near(0);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(Flip, Y)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
OCL_OFF(cv::flip(src1_roi, dst1_roi, 1));
|
||||
OCL_ON(cv::flip(usrc1_roi, udst1_roi, 1));
|
||||
Near(0);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(Flip, BOTH)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
OCL_OFF(cv::flip(src1_roi, dst1_roi, -1));
|
||||
OCL_ON(cv::flip(usrc1_roi, udst1_roi, -1));
|
||||
Near(0);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////// Norm /////////////////////////////////////////////////
|
||||
|
||||
static bool relativeError(double actual, double expected, double eps)
|
||||
{
|
||||
return std::abs(actual - expected) / actual < eps;
|
||||
}
|
||||
|
||||
typedef ArithmTestBase Norm;
|
||||
|
||||
OCL_TEST_P(Norm, NORM_INF_1arg)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
OCL_OFF(const double cpuRes = cv::norm(src1_roi, NORM_INF));
|
||||
OCL_ON(const double gpuRes = cv::norm(usrc1_roi, NORM_INF));
|
||||
|
||||
EXPECT_NEAR(cpuRes, gpuRes, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(Norm, NORM_L1_1arg)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
OCL_OFF(const double cpuRes = cv::norm(src1_roi, NORM_L1));
|
||||
OCL_ON(const double gpuRes = cv::norm(usrc1_roi, NORM_L1));
|
||||
|
||||
EXPECT_PRED3(relativeError, cpuRes, gpuRes, 1e-6);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(Norm, NORM_L2_1arg)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
OCL_OFF(const double cpuRes = cv::norm(src1_roi, NORM_L2));
|
||||
OCL_ON(const double gpuRes = cv::norm(usrc1_roi, NORM_L2));
|
||||
|
||||
EXPECT_PRED3(relativeError, cpuRes, gpuRes, 1e-6);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(Norm, NORM_INF_2args)
|
||||
{
|
||||
for (int relative = 0; relative < 2; ++relative)
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
int type = NORM_INF;
|
||||
if (relative == 1)
|
||||
type |= NORM_RELATIVE;
|
||||
|
||||
OCL_OFF(const double cpuRes = cv::norm(src1_roi, src2_roi, type));
|
||||
OCL_ON(const double gpuRes = cv::norm(usrc1_roi, usrc2_roi, type));
|
||||
|
||||
EXPECT_NEAR(cpuRes, gpuRes, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(Norm, NORM_L1_2args)
|
||||
{
|
||||
for (int relative = 0; relative < 2; ++relative)
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
int type = NORM_L1;
|
||||
if (relative == 1)
|
||||
type |= NORM_RELATIVE;
|
||||
|
||||
OCL_OFF(const double cpuRes = cv::norm(src1_roi, src2_roi, type));
|
||||
OCL_ON(const double gpuRes = cv::norm(usrc1_roi, usrc2_roi, type));
|
||||
|
||||
EXPECT_PRED3(relativeError, cpuRes, gpuRes, 1e-6);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_TEST_P(Norm, NORM_L2_2args)
|
||||
{
|
||||
for (int relative = 0; relative < 2; ++relative)
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
int type = NORM_L2;
|
||||
if (relative == 1)
|
||||
type |= NORM_RELATIVE;
|
||||
|
||||
OCL_OFF(const double cpuRes = cv::norm(src1_roi, src2_roi, type));
|
||||
OCL_ON(const double gpuRes = cv::norm(usrc1_roi, usrc2_roi, type));
|
||||
|
||||
EXPECT_PRED3(relativeError, cpuRes, gpuRes, 1e-6);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////// Instantiation /////////////////////////////////////////
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Lut, Combine(::testing::Values(CV_8U, CV_8S), OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool(), Bool()));
|
||||
@ -977,10 +1115,10 @@ OCL_INSTANTIATE_TEST_CASE_P(Arithm, Absdiff, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHA
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, CartToPolar, Combine(testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, PolarToCart, Combine(testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Transpose, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
//OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_and, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
//OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_not, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
//OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_xor, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
//OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_or, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_and, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_not, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_xor, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Bitwise_or, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Pow, Combine(testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Compare, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, AddWeighted, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
@ -993,6 +1131,8 @@ OCL_INSTANTIATE_TEST_CASE_P(Arithm, Log, Combine(::testing::Values(CV_32F, CV_64
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Exp, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Phase, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Magnitude, Combine(::testing::Values(CV_32F, CV_64F), OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Flip, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Arithm, Norm, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
|
||||
} } // namespace cvtest::ocl
|
||||
|
||||
|
222
modules/core/test/ocl/test_split_merge.cpp
Normal file
222
modules/core/test/ocl/test_split_merge.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
//
|
||||
// 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace cvtest {
|
||||
namespace ocl {
|
||||
|
||||
PARAM_TEST_CASE(MergeTestBase, MatDepth, Channels, bool)
|
||||
{
|
||||
int depth, cn;
|
||||
bool use_roi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src1)
|
||||
TEST_DECLARE_INPUT_PARAMETER(src2)
|
||||
TEST_DECLARE_INPUT_PARAMETER(src3)
|
||||
TEST_DECLARE_INPUT_PARAMETER(src4)
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst)
|
||||
|
||||
std::vector<Mat> src_roi;
|
||||
std::vector<UMat> usrc_roi;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
depth = GET_PARAM(0);
|
||||
cn = GET_PARAM(1);
|
||||
use_roi = GET_PARAM(2);
|
||||
|
||||
CV_Assert(cn >= 1 && cn <= 4);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
|
||||
{
|
||||
Border src1Border = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src1, src1_roi, roiSize, src1Border, depth, 2, 11);
|
||||
|
||||
Border src2Border = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src2, src2_roi, roiSize, src2Border, depth, -1540, 1740);
|
||||
|
||||
Border src3Border = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src3, src3_roi, roiSize, src3Border, depth, -1540, 1740);
|
||||
|
||||
Border src4Border = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src4, src4_roi, roiSize, src4Border, depth, -1540, 1740);
|
||||
}
|
||||
|
||||
Border dstBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, CV_MAKE_TYPE(depth, cn), 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src1)
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src2)
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src3)
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src4)
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst)
|
||||
|
||||
src_roi.push_back(src1_roi), usrc_roi.push_back(usrc1_roi);
|
||||
if (cn >= 2)
|
||||
src_roi.push_back(src2_roi), usrc_roi.push_back(usrc2_roi);
|
||||
if (cn >= 3)
|
||||
src_roi.push_back(src3_roi), usrc_roi.push_back(usrc3_roi);
|
||||
if (cn >= 4)
|
||||
src_roi.push_back(src4_roi), usrc_roi.push_back(usrc4_roi);
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.)
|
||||
{
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
typedef MergeTestBase Merge;
|
||||
|
||||
OCL_TEST_P(Merge, Accuracy)
|
||||
{
|
||||
for(int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::merge(src_roi, dst_roi));
|
||||
OCL_ON(cv::merge(usrc_roi, udst_roi));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
PARAM_TEST_CASE(SplitTestBase, MatType, Channels, bool)
|
||||
{
|
||||
int depth, cn;
|
||||
bool use_roi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src)
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst1)
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst2)
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst3)
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst4)
|
||||
|
||||
std::vector<Mat> dst_roi, dst;
|
||||
std::vector<UMat> udst_roi, udst;
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
depth = GET_PARAM(0);
|
||||
cn = GET_PARAM(1);
|
||||
use_roi = GET_PARAM(2);
|
||||
|
||||
CV_Assert(cn >= 1 && cn <= 4);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
Size roiSize = randomSize(1, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, CV_MAKE_TYPE(depth, cn), 5, 16);
|
||||
|
||||
{
|
||||
Border dst1Border = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst1, dst1_roi, roiSize, dst1Border, depth, 2, 11);
|
||||
|
||||
Border dst2Border = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst2, dst2_roi, roiSize, dst2Border, depth, -1540, 1740);
|
||||
|
||||
Border dst3Border = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst3, dst3_roi, roiSize, dst3Border, depth, -1540, 1740);
|
||||
|
||||
Border dst4Border = randomBorder(0, use_roi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst4, dst4_roi, roiSize, dst4Border, depth, -1540, 1740);
|
||||
}
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src)
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst1)
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst2)
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst3)
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst4)
|
||||
|
||||
dst_roi.push_back(dst1_roi), udst_roi.push_back(udst1_roi),
|
||||
dst.push_back(dst1), udst.push_back(udst1);
|
||||
if (cn >= 2)
|
||||
dst_roi.push_back(dst2_roi), udst_roi.push_back(udst2_roi),
|
||||
dst.push_back(dst2), udst.push_back(udst2);
|
||||
if (cn >= 3)
|
||||
dst_roi.push_back(dst3_roi), udst_roi.push_back(udst3_roi),
|
||||
dst.push_back(dst3), udst.push_back(udst3);
|
||||
if (cn >= 4)
|
||||
dst_roi.push_back(dst4_roi), udst_roi.push_back(udst4_roi),
|
||||
dst.push_back(dst4), udst.push_back(udst4);
|
||||
}
|
||||
};
|
||||
|
||||
typedef SplitTestBase Split;
|
||||
|
||||
OCL_TEST_P(Split, Accuracy)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::split(src_roi, dst_roi));
|
||||
OCL_ON(cv::split(usrc_roi, udst_roi));
|
||||
|
||||
for (int i = 0; i < cn; ++i)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst[i], udst[i], 0.0);
|
||||
EXPECT_MAT_NEAR(dst_roi[i], udst_roi[i], 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(SplitMerge, Merge, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
OCL_INSTANTIATE_TEST_CASE_P(SplitMerge, Split, Combine(OCL_ALL_DEPTHS, OCL_ALL_CHANNELS, Bool()));
|
||||
|
||||
} } // namespace cvtest::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
@ -2110,6 +2110,8 @@ void cv::cuda::cvtColor(InputArray src, OutputArray dst, int code, int dcn, Stre
|
||||
|
||||
void cv::cuda::demosaicing(InputArray _src, OutputArray _dst, int code, int dcn, Stream& stream)
|
||||
{
|
||||
CV_Assert( !_src.empty() );
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case cv::COLOR_BayerBG2GRAY: case cv::COLOR_BayerGB2GRAY: case cv::COLOR_BayerRG2GRAY: case cv::COLOR_BayerGR2GRAY:
|
||||
|
@ -2357,6 +2357,7 @@ struct Demosaicing : testing::TestWithParam<cv::cuda::DeviceInfo>
|
||||
CUDA_TEST_P(Demosaicing, BayerBG2BGR)
|
||||
{
|
||||
cv::Mat img = readImage("stereobm/aloe-L.png");
|
||||
ASSERT_FALSE(img.empty()) << "Can't load input image";
|
||||
|
||||
cv::Mat_<uchar> src;
|
||||
mosaic(img, src, cv::Point(1, 1));
|
||||
@ -2370,6 +2371,7 @@ CUDA_TEST_P(Demosaicing, BayerBG2BGR)
|
||||
CUDA_TEST_P(Demosaicing, BayerGB2BGR)
|
||||
{
|
||||
cv::Mat img = readImage("stereobm/aloe-L.png");
|
||||
ASSERT_FALSE(img.empty()) << "Can't load input image";
|
||||
|
||||
cv::Mat_<uchar> src;
|
||||
mosaic(img, src, cv::Point(0, 1));
|
||||
@ -2383,6 +2385,7 @@ CUDA_TEST_P(Demosaicing, BayerGB2BGR)
|
||||
CUDA_TEST_P(Demosaicing, BayerRG2BGR)
|
||||
{
|
||||
cv::Mat img = readImage("stereobm/aloe-L.png");
|
||||
ASSERT_FALSE(img.empty()) << "Can't load input image";
|
||||
|
||||
cv::Mat_<uchar> src;
|
||||
mosaic(img, src, cv::Point(0, 0));
|
||||
@ -2396,6 +2399,7 @@ CUDA_TEST_P(Demosaicing, BayerRG2BGR)
|
||||
CUDA_TEST_P(Demosaicing, BayerGR2BGR)
|
||||
{
|
||||
cv::Mat img = readImage("stereobm/aloe-L.png");
|
||||
ASSERT_FALSE(img.empty()) << "Can't load input image";
|
||||
|
||||
cv::Mat_<uchar> src;
|
||||
mosaic(img, src, cv::Point(1, 0));
|
||||
@ -2409,6 +2413,7 @@ CUDA_TEST_P(Demosaicing, BayerGR2BGR)
|
||||
CUDA_TEST_P(Demosaicing, BayerBG2BGR_MHT)
|
||||
{
|
||||
cv::Mat img = readImage("stereobm/aloe-L.png");
|
||||
ASSERT_FALSE(img.empty()) << "Can't load input image";
|
||||
|
||||
cv::Mat_<uchar> src;
|
||||
mosaic(img, src, cv::Point(1, 1));
|
||||
@ -2422,6 +2427,7 @@ CUDA_TEST_P(Demosaicing, BayerBG2BGR_MHT)
|
||||
CUDA_TEST_P(Demosaicing, BayerGB2BGR_MHT)
|
||||
{
|
||||
cv::Mat img = readImage("stereobm/aloe-L.png");
|
||||
ASSERT_FALSE(img.empty()) << "Can't load input image";
|
||||
|
||||
cv::Mat_<uchar> src;
|
||||
mosaic(img, src, cv::Point(0, 1));
|
||||
@ -2435,6 +2441,7 @@ CUDA_TEST_P(Demosaicing, BayerGB2BGR_MHT)
|
||||
CUDA_TEST_P(Demosaicing, BayerRG2BGR_MHT)
|
||||
{
|
||||
cv::Mat img = readImage("stereobm/aloe-L.png");
|
||||
ASSERT_FALSE(img.empty()) << "Can't load input image";
|
||||
|
||||
cv::Mat_<uchar> src;
|
||||
mosaic(img, src, cv::Point(0, 0));
|
||||
@ -2448,6 +2455,7 @@ CUDA_TEST_P(Demosaicing, BayerRG2BGR_MHT)
|
||||
CUDA_TEST_P(Demosaicing, BayerGR2BGR_MHT)
|
||||
{
|
||||
cv::Mat img = readImage("stereobm/aloe-L.png");
|
||||
ASSERT_FALSE(img.empty()) << "Can't load input image";
|
||||
|
||||
cv::Mat_<uchar> src;
|
||||
mosaic(img, src, cv::Point(1, 0));
|
||||
|
@ -141,12 +141,12 @@ static void computeOrbDescriptor(const KeyPoint& kpt,
|
||||
float x, y;
|
||||
int ix, iy;
|
||||
#if 1
|
||||
#define GET_VALUE(idx) \
|
||||
(x = pattern[idx].x*a - pattern[idx].y*b, \
|
||||
y = pattern[idx].x*b + pattern[idx].y*a, \
|
||||
ix = cvRound(x), \
|
||||
iy = cvRound(y), \
|
||||
*(center + iy*step + ix) )
|
||||
#define GET_VALUE(idx) \
|
||||
(x = pattern[idx].x*a - pattern[idx].y*b, \
|
||||
y = pattern[idx].x*b + pattern[idx].y*a, \
|
||||
ix = cvRound(x), \
|
||||
iy = cvRound(y), \
|
||||
*(center + iy*step + ix) )
|
||||
#else
|
||||
#define GET_VALUE(idx) \
|
||||
(x = pattern[idx].x*a - pattern[idx].y*b, \
|
||||
|
@ -152,7 +152,7 @@ public:
|
||||
task = new( tbb::task::allocate_root() ) TBBApproximateSynchronizerTask( *this );
|
||||
tbb::task::enqueue(*task);
|
||||
#else
|
||||
task->reset( new ApproximateSynchronizer( *this ) );
|
||||
task.reset( new ApproximateSynchronizer( *this ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1552,9 +1552,9 @@ static gboolean icvOnMouse( GtkWidget *widget, GdkEvent *event, gpointer user_da
|
||||
// image origin is not necessarily at (0,0)
|
||||
int x0 = (widget->allocation.width - image_widget->scaled_image->cols)/2;
|
||||
int y0 = (widget->allocation.height - image_widget->scaled_image->rows)/2;
|
||||
pt.x = cvRound( ((pt32f.x-x0)*image_widget->original_image->cols)/
|
||||
pt.x = cvFloor( ((pt32f.x-x0)*image_widget->original_image->cols)/
|
||||
image_widget->scaled_image->cols );
|
||||
pt.y = cvRound( ((pt32f.y-y0)*image_widget->original_image->rows)/
|
||||
pt.y = cvFloor( ((pt32f.y-y0)*image_widget->original_image->rows)/
|
||||
image_widget->scaled_image->rows );
|
||||
}
|
||||
else{
|
||||
|
@ -596,15 +596,15 @@ Calculates the integral of an image.
|
||||
|
||||
.. ocv:function:: void integral( InputArray src, OutputArray sum, int sdepth=-1 )
|
||||
|
||||
.. ocv:function:: void integral( InputArray src, OutputArray sum, OutputArray sqsum, int sdepth=-1 )
|
||||
.. ocv:function:: void integral( InputArray src, OutputArray sum, OutputArray sqsum, int sdepth=-1, int sqdepth=-1 )
|
||||
|
||||
.. ocv:function:: void integral( InputArray src, OutputArray sum, OutputArray sqsum, OutputArray tilted, int sdepth=-1 )
|
||||
.. ocv:function:: void integral( InputArray src, OutputArray sum, OutputArray sqsum, OutputArray tilted, int sdepth=-1, int sqdepth=-1 )
|
||||
|
||||
.. ocv:pyfunction:: cv2.integral(src[, sum[, sdepth]]) -> sum
|
||||
|
||||
.. ocv:pyfunction:: cv2.integral2(src[, sum[, sqsum[, sdepth]]]) -> sum, sqsum
|
||||
.. ocv:pyfunction:: cv2.integral2(src[, sum[, sqsum[, sdepth[, sqdepth]]]]) -> sum, sqsum
|
||||
|
||||
.. ocv:pyfunction:: cv2.integral3(src[, sum[, sqsum[, tilted[, sdepth]]]]) -> sum, sqsum, tilted
|
||||
.. ocv:pyfunction:: cv2.integral3(src[, sum[, sqsum[, tilted[, sdepth[, sqdepth]]]]]) -> sum, sqsum, tilted
|
||||
|
||||
.. ocv:cfunction:: void cvIntegral( const CvArr* image, CvArr* sum, CvArr* sqsum=NULL, CvArr* tilted_sum=NULL )
|
||||
|
||||
@ -618,6 +618,8 @@ Calculates the integral of an image.
|
||||
|
||||
:param sdepth: desired depth of the integral and the tilted integral images, ``CV_32S``, ``CV_32F``, or ``CV_64F``.
|
||||
|
||||
:param sqdepth: desired depth of the integral image of squared pixel values, ``CV_32F`` or ``CV_64F``.
|
||||
|
||||
The functions calculate one or more integral images for the source image as follows:
|
||||
|
||||
.. math::
|
||||
|
@ -1241,12 +1241,12 @@ CV_EXPORTS_W void integral( InputArray src, OutputArray sum, int sdepth = -1 );
|
||||
|
||||
//! computes the integral image and integral for the squared image
|
||||
CV_EXPORTS_AS(integral2) void integral( InputArray src, OutputArray sum,
|
||||
OutputArray sqsum, int sdepth = -1 );
|
||||
OutputArray sqsum, int sdepth = -1, int sqdepth = -1 );
|
||||
|
||||
//! computes the integral image, integral for the squared image and the tilted integral image
|
||||
CV_EXPORTS_AS(integral3) void integral( InputArray src, OutputArray sum,
|
||||
OutputArray sqsum, OutputArray tilted,
|
||||
int sdepth = -1 );
|
||||
int sdepth = -1, int sqdepth = -1 );
|
||||
|
||||
//! adds image to the accumulator (dst += src). Unlike cv::add, dst and src can have different types.
|
||||
CV_EXPORTS_W void accumulate( InputArray src, InputOutputArray dst,
|
||||
@ -1512,6 +1512,9 @@ CV_EXPORTS Ptr<GeneralizedHoughBallard> createGeneralizedHoughBallard();
|
||||
//! Detects position, traslation and rotation
|
||||
CV_EXPORTS Ptr<GeneralizedHoughGuil> createGeneralizedHoughGuil();
|
||||
|
||||
//! Performs linear blending of two images
|
||||
CV_EXPORTS void blendLinear(InputArray src1, InputArray src2, InputArray weights1, InputArray weights2, OutputArray dst);
|
||||
|
||||
} // cv
|
||||
|
||||
#endif
|
||||
|
145
modules/imgproc/src/blend.cpp
Normal file
145
modules/imgproc/src/blend.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Nathan, liujun@multicorewareinc.com
|
||||
//
|
||||
// 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"
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
namespace cv {
|
||||
|
||||
template <typename T>
|
||||
class BlendLinearInvoker :
|
||||
public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
BlendLinearInvoker(const Mat & _src1, const Mat & _src2, const Mat & _weights1,
|
||||
const Mat & _weights2, Mat & _dst) :
|
||||
src1(&_src1), src2(&_src2), weights1(&_weights1), weights2(&_weights2), dst(&_dst)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator() (const Range & range) const
|
||||
{
|
||||
int cn = src1->channels(), width = src1->cols * cn;
|
||||
|
||||
for (int y = range.start; y < range.end; ++y)
|
||||
{
|
||||
const float * const weights1_row = weights1->ptr<float>(y);
|
||||
const float * const weights2_row = weights2->ptr<float>(y);
|
||||
const T * const src1_row = src1->ptr<T>(y);
|
||||
const T * const src2_row = src2->ptr<T>(y);
|
||||
T * const dst_row = dst->ptr<T>(y);
|
||||
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
int x1 = x / cn;
|
||||
float w1 = weights1_row[x1], w2 = weights2_row[x1];
|
||||
float den = (w1 + w2 + 1e-5f);
|
||||
float num = (src1_row[x] * w1 + src2_row[x] * w2);
|
||||
|
||||
dst_row[x] = saturate_cast<T>(num / den);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const BlendLinearInvoker & operator= (const BlendLinearInvoker &);
|
||||
BlendLinearInvoker(const BlendLinearInvoker &);
|
||||
|
||||
const Mat * src1, * src2, * weights1, * weights2;
|
||||
Mat * dst;
|
||||
};
|
||||
|
||||
static bool ocl_blendLinear( InputArray _src1, InputArray _src2, InputArray _weights1, InputArray _weights2, OutputArray _dst )
|
||||
{
|
||||
int type = _src1.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
|
||||
char cvt[30];
|
||||
ocl::Kernel k("blendLinear", ocl::imgproc::blend_linear_oclsrc,
|
||||
format("-D T=%s -D cn=%d -D convertToT=%s", ocl::typeToStr(depth),
|
||||
cn, ocl::convertTypeStr(CV_32F, depth, 1, cvt)));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
UMat src1 = _src1.getUMat(), src2 = _src2.getUMat(), weights1 = _weights1.getUMat(),
|
||||
weights2 = _weights2.getUMat(), dst = _dst.getUMat();
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(src1), ocl::KernelArg::ReadOnlyNoSize(src2),
|
||||
ocl::KernelArg::ReadOnlyNoSize(weights1), ocl::KernelArg::ReadOnlyNoSize(weights2),
|
||||
ocl::KernelArg::WriteOnly(dst));
|
||||
|
||||
size_t globalsize[2] = { dst.cols, dst.rows };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cv::blendLinear( InputArray _src1, InputArray _src2, InputArray _weights1, InputArray _weights2, OutputArray _dst )
|
||||
{
|
||||
int type = _src1.type(), depth = CV_MAT_DEPTH(type);
|
||||
Size size = _src1.size();
|
||||
|
||||
CV_Assert(depth == CV_8U || depth == CV_32F);
|
||||
CV_Assert(size == _src2.size() && size == _weights1.size() && size == _weights2.size());
|
||||
CV_Assert(type == _src2.type() && _weights1.type() == CV_32FC1 && _weights2.type() == CV_32FC1);
|
||||
|
||||
_dst.create(size, type);
|
||||
|
||||
if (ocl::useOpenCL() && _dst.isUMat() && ocl_blendLinear(_src1, _src2, _weights1, _weights2, _dst))
|
||||
return;
|
||||
|
||||
Mat src1 = _src1.getMat(), src2 = _src2.getMat(), weights1 = _weights1.getMat(),
|
||||
weights2 = _weights2.getMat(), dst = _dst.getMat();
|
||||
|
||||
if (depth == CV_8U)
|
||||
{
|
||||
BlendLinearInvoker<uchar> invoker(src1, src2, weights1, weights2, dst);
|
||||
parallel_for_(Range(0, src1.rows), invoker, dst.total()/(double)(1<<16));
|
||||
}
|
||||
else if (depth == CV_32F)
|
||||
{
|
||||
BlendLinearInvoker<float> invoker(src1, src2, weights1, weights2, dst);
|
||||
parallel_for_(Range(0, src1.rows), invoker, dst.total()/(double)(1<<16));
|
||||
}
|
||||
}
|
@ -413,15 +413,15 @@ static bool IPPDeriv(const Mat& src, Mat& dst, int ddepth, int dx, int dy, int k
|
||||
void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy,
|
||||
int ksize, double scale, double delta, int borderType )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);
|
||||
if (ddepth < 0)
|
||||
ddepth = src.depth();
|
||||
_dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) );
|
||||
Mat dst = _dst.getMat();
|
||||
ddepth = sdepth;
|
||||
_dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) );
|
||||
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
if (scale == 1.0 && delta == 0)
|
||||
{
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
if (ksize == 3 && tegra::sobel3x3(src, dst, dx, dy, borderType))
|
||||
return;
|
||||
if (ksize == -1 && tegra::scharr(src, dst, dx, dy, borderType))
|
||||
@ -430,13 +430,14 @@ void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy,
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
if(dx < 3 && dy < 3 && src.channels() == 1 && borderType == 1)
|
||||
if(dx < 3 && dy < 3 && cn == 1 && borderType == BORDER_REPLICATE)
|
||||
{
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
if(IPPDeriv(src, dst, ddepth, dx, dy, ksize,scale))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
int ktype = std::max(CV_32F, std::max(ddepth, src.depth()));
|
||||
int ktype = std::max(CV_32F, std::max(ddepth, sdepth));
|
||||
|
||||
Mat kx, ky;
|
||||
getDerivKernels( kx, ky, dx, dy, ksize, false, ktype );
|
||||
@ -449,33 +450,36 @@ void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy,
|
||||
else
|
||||
ky *= scale;
|
||||
}
|
||||
sepFilter2D( src, dst, ddepth, kx, ky, Point(-1,-1), delta, borderType );
|
||||
sepFilter2D( _src, _dst, ddepth, kx, ky, Point(-1, -1), delta, borderType );
|
||||
}
|
||||
|
||||
|
||||
void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy,
|
||||
double scale, double delta, int borderType )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);
|
||||
if (ddepth < 0)
|
||||
ddepth = src.depth();
|
||||
_dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) );
|
||||
Mat dst = _dst.getMat();
|
||||
ddepth = sdepth;
|
||||
_dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) );
|
||||
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
if (scale == 1.0 && delta == 0)
|
||||
{
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
if (tegra::scharr(src, dst, dx, dy, borderType))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
if(dx < 2 && dy < 2 && src.channels() == 1 && borderType == 1)
|
||||
{
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
if(IPPDerivScharr(src, dst, ddepth, dx, dy, scale))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
int ktype = std::max(CV_32F, std::max(ddepth, src.depth()));
|
||||
int ktype = std::max(CV_32F, std::max(ddepth, sdepth));
|
||||
|
||||
Mat kx, ky;
|
||||
getScharrKernels( kx, ky, dx, dy, false, ktype );
|
||||
@ -488,22 +492,22 @@ void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy,
|
||||
else
|
||||
ky *= scale;
|
||||
}
|
||||
sepFilter2D( src, dst, ddepth, kx, ky, Point(-1,-1), delta, borderType );
|
||||
sepFilter2D( _src, _dst, ddepth, kx, ky, Point(-1, -1), delta, borderType );
|
||||
}
|
||||
|
||||
|
||||
void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize,
|
||||
double scale, double delta, int borderType )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype);
|
||||
if (ddepth < 0)
|
||||
ddepth = src.depth();
|
||||
_dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) );
|
||||
Mat dst = _dst.getMat();
|
||||
ddepth = sdepth;
|
||||
_dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) );
|
||||
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
if (scale == 1.0 && delta == 0)
|
||||
{
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
if (ksize == 1 && tegra::laplace1(src, dst, borderType))
|
||||
return;
|
||||
if (ksize == 3 && tegra::laplace3(src, dst, borderType))
|
||||
@ -516,15 +520,18 @@ void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize,
|
||||
if( ksize == 1 || ksize == 3 )
|
||||
{
|
||||
float K[2][9] =
|
||||
{{0, 1, 0, 1, -4, 1, 0, 1, 0},
|
||||
{2, 0, 2, 0, -8, 0, 2, 0, 2}};
|
||||
{
|
||||
{ 0, 1, 0, 1, -4, 1, 0, 1, 0 },
|
||||
{ 2, 0, 2, 0, -8, 0, 2, 0, 2 }
|
||||
};
|
||||
Mat kernel(3, 3, CV_32F, K[ksize == 3]);
|
||||
if( scale != 1 )
|
||||
kernel *= scale;
|
||||
filter2D( src, dst, ddepth, kernel, Point(-1,-1), delta, borderType );
|
||||
filter2D( _src, _dst, ddepth, kernel, Point(-1, -1), delta, borderType );
|
||||
}
|
||||
else
|
||||
{
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
const size_t STRIPE_SIZE = 1 << 14;
|
||||
|
||||
int depth = src.depth();
|
||||
|
@ -41,6 +41,7 @@
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
/****************************************************************************************\
|
||||
Base Image Filter
|
||||
@ -3115,6 +3116,206 @@ template<typename ST, class CastOp, class VecOp> struct Filter2D : public BaseFi
|
||||
|
||||
}
|
||||
|
||||
namespace cv
|
||||
{
|
||||
|
||||
#define DIVUP(total, grain) (((total) + (grain) - 1) / (grain))
|
||||
#define ROUNDUP(sz, n) ((sz) + (n) - 1 - (((sz) + (n) - 1) % (n)))
|
||||
|
||||
// prepare kernel: transpose and make double rows (+align). Returns size of aligned row
|
||||
// Samples:
|
||||
// a b c
|
||||
// Input: d e f
|
||||
// g h i
|
||||
// Output, last two zeros is the alignment:
|
||||
// a d g a d g 0 0
|
||||
// b e h b e h 0 0
|
||||
// c f i c f i 0 0
|
||||
template <typename T>
|
||||
static int _prepareKernelFilter2D(std::vector<T>& data, const Mat &kernel)
|
||||
{
|
||||
Mat _kernel; kernel.convertTo(_kernel, DataDepth<T>::value);
|
||||
int size_y_aligned = ROUNDUP(kernel.rows * 2, 4);
|
||||
data.clear(); data.resize(size_y_aligned * kernel.cols, 0);
|
||||
for (int x = 0; x < kernel.cols; x++)
|
||||
{
|
||||
for (int y = 0; y < kernel.rows; y++)
|
||||
{
|
||||
data[x * size_y_aligned + y] = _kernel.at<T>(y, x);
|
||||
data[x * size_y_aligned + y + kernel.rows] = _kernel.at<T>(y, x);
|
||||
}
|
||||
}
|
||||
return size_y_aligned;
|
||||
}
|
||||
|
||||
static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth,
|
||||
InputArray _kernel, Point anchor,
|
||||
double delta, int borderType )
|
||||
{
|
||||
if (abs(delta) > FLT_MIN)
|
||||
return false;
|
||||
|
||||
int type = _src.type();
|
||||
int cn = CV_MAT_CN(type);
|
||||
if ((1 != cn) && (2 != cn) && (4 != cn))
|
||||
return false;//TODO
|
||||
|
||||
int sdepth = CV_MAT_DEPTH(type);
|
||||
Size ksize = _kernel.size();
|
||||
if( anchor.x < 0 )
|
||||
anchor.x = ksize.width / 2;
|
||||
if( anchor.y < 0 )
|
||||
anchor.y = ksize.height / 2;
|
||||
if( ddepth < 0 )
|
||||
ddepth = sdepth;
|
||||
else if (ddepth != sdepth)
|
||||
return false;
|
||||
|
||||
bool isIsolatedBorder = (borderType & BORDER_ISOLATED) != 0;
|
||||
bool useDouble = (CV_64F == sdepth);
|
||||
const cv::ocl::Device &device = cv::ocl::Device::getDefault();
|
||||
int doubleFPConfig = device.doubleFPConfig();
|
||||
if (useDouble && (0 == doubleFPConfig))
|
||||
return false;
|
||||
|
||||
const char* btype = NULL;
|
||||
switch (borderType & ~BORDER_ISOLATED)
|
||||
{
|
||||
case BORDER_CONSTANT:
|
||||
btype = "BORDER_CONSTANT";
|
||||
break;
|
||||
case BORDER_REPLICATE:
|
||||
btype = "BORDER_REPLICATE";
|
||||
break;
|
||||
case BORDER_REFLECT:
|
||||
btype = "BORDER_REFLECT";
|
||||
break;
|
||||
case BORDER_WRAP:
|
||||
return false;
|
||||
case BORDER_REFLECT101:
|
||||
btype = "BORDER_REFLECT_101";
|
||||
break;
|
||||
}
|
||||
|
||||
cv::Mat kernelMat = _kernel.getMat();
|
||||
std::vector<float> kernelMatDataFloat;
|
||||
std::vector<double> kernelMatDataDouble;
|
||||
int kernel_size_y2_aligned = useDouble ?
|
||||
_prepareKernelFilter2D<double>(kernelMatDataDouble, kernelMat)
|
||||
: _prepareKernelFilter2D<float>(kernelMatDataFloat, kernelMat);
|
||||
|
||||
|
||||
cv::Size sz = _src.size();
|
||||
size_t globalsize[2] = {sz.width, sz.height};
|
||||
size_t localsize[2] = {0, 1};
|
||||
|
||||
ocl::Kernel kernel;
|
||||
UMat src; Size wholeSize;
|
||||
if (!isIsolatedBorder)
|
||||
{
|
||||
src = _src.getUMat();
|
||||
Point ofs;
|
||||
src.locateROI(wholeSize, ofs);
|
||||
}
|
||||
|
||||
size_t maxWorkItemSizes[32]; device.maxWorkItemSizes(maxWorkItemSizes);
|
||||
size_t tryWorkItems = maxWorkItemSizes[0];
|
||||
for (;;)
|
||||
{
|
||||
size_t BLOCK_SIZE = tryWorkItems;
|
||||
while (BLOCK_SIZE > 32 && BLOCK_SIZE >= (size_t)ksize.width * 2 && BLOCK_SIZE > (size_t)sz.width * 2)
|
||||
BLOCK_SIZE /= 2;
|
||||
#if 1 // TODO Mode with several blocks requires a much more VGPRs, so this optimization is not actual for the current devices
|
||||
size_t BLOCK_SIZE_Y = 1;
|
||||
#else
|
||||
size_t BLOCK_SIZE_Y = 8; // TODO Check heuristic value on devices
|
||||
while (BLOCK_SIZE_Y < BLOCK_SIZE / 8 && BLOCK_SIZE_Y * src.clCxt->getDeviceInfo().maxComputeUnits * 32 < (size_t)src.rows)
|
||||
BLOCK_SIZE_Y *= 2;
|
||||
#endif
|
||||
|
||||
if ((size_t)ksize.width > BLOCK_SIZE)
|
||||
return false;
|
||||
|
||||
int requiredTop = anchor.y;
|
||||
int requiredLeft = (int)BLOCK_SIZE; // not this: anchor.x;
|
||||
int requiredBottom = ksize.height - 1 - anchor.y;
|
||||
int requiredRight = (int)BLOCK_SIZE; // not this: ksize.width - 1 - anchor.x;
|
||||
int h = isIsolatedBorder ? sz.height : wholeSize.height;
|
||||
int w = isIsolatedBorder ? sz.width : wholeSize.width;
|
||||
bool extra_extrapolation = h < requiredTop || h < requiredBottom || w < requiredLeft || w < requiredRight;
|
||||
|
||||
if ((w < ksize.width) || (h < ksize.height))
|
||||
return false;
|
||||
|
||||
char build_options[1024];
|
||||
sprintf(build_options, "-D LOCAL_SIZE=%d -D BLOCK_SIZE_Y=%d -D DATA_DEPTH=%d -D DATA_CHAN=%d -D USE_DOUBLE=%d "
|
||||
"-D ANCHOR_X=%d -D ANCHOR_Y=%d -D KERNEL_SIZE_X=%d -D KERNEL_SIZE_Y=%d -D KERNEL_SIZE_Y2_ALIGNED=%d "
|
||||
"-D %s -D %s -D %s",
|
||||
(int)BLOCK_SIZE, (int)BLOCK_SIZE_Y,
|
||||
sdepth, cn, useDouble ? 1 : 0,
|
||||
anchor.x, anchor.y, ksize.width, ksize.height, kernel_size_y2_aligned,
|
||||
btype,
|
||||
extra_extrapolation ? "EXTRA_EXTRAPOLATION" : "NO_EXTRA_EXTRAPOLATION",
|
||||
isIsolatedBorder ? "BORDER_ISOLATED" : "NO_BORDER_ISOLATED");
|
||||
|
||||
localsize[0] = BLOCK_SIZE;
|
||||
globalsize[0] = DIVUP(sz.width, BLOCK_SIZE - (ksize.width - 1)) * BLOCK_SIZE;
|
||||
globalsize[1] = DIVUP(sz.height, BLOCK_SIZE_Y);
|
||||
|
||||
cv::String errmsg;
|
||||
if (!kernel.create("filter2D", cv::ocl::imgproc::filter2D_oclsrc, build_options))
|
||||
return false;
|
||||
size_t kernelWorkGroupSize = kernel.workGroupSize();
|
||||
if (localsize[0] <= kernelWorkGroupSize)
|
||||
break;
|
||||
if (BLOCK_SIZE < kernelWorkGroupSize)
|
||||
return false;
|
||||
tryWorkItems = kernelWorkGroupSize;
|
||||
}
|
||||
|
||||
_dst.create(sz, CV_MAKETYPE(ddepth, cn));
|
||||
UMat dst = _dst.getUMat();
|
||||
if (src.empty())
|
||||
src = _src.getUMat();
|
||||
|
||||
int idxArg = 0;
|
||||
idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(src));
|
||||
idxArg = kernel.set(idxArg, (int)src.step);
|
||||
|
||||
int srcOffsetX = (int)((src.offset % src.step) / src.elemSize());
|
||||
int srcOffsetY = (int)(src.offset / src.step);
|
||||
int srcEndX = (isIsolatedBorder ? (srcOffsetX + sz.width) : wholeSize.width);
|
||||
int srcEndY = (isIsolatedBorder ? (srcOffsetY + sz.height) : wholeSize.height);
|
||||
idxArg = kernel.set(idxArg, srcOffsetX);
|
||||
idxArg = kernel.set(idxArg, srcOffsetY);
|
||||
idxArg = kernel.set(idxArg, srcEndX);
|
||||
idxArg = kernel.set(idxArg, srcEndY);
|
||||
|
||||
idxArg = kernel.set(idxArg, ocl::KernelArg::WriteOnly(dst));
|
||||
float borderValue[4] = {0, 0, 0, 0};
|
||||
double borderValueDouble[4] = {0, 0, 0, 0};
|
||||
if ((borderType & ~BORDER_ISOLATED) == BORDER_CONSTANT)
|
||||
{
|
||||
int cnocl = (3 == cn) ? 4 : cn;
|
||||
if (useDouble)
|
||||
idxArg = kernel.set(idxArg, (void *)&borderValueDouble[0], sizeof(double) * cnocl);
|
||||
else
|
||||
idxArg = kernel.set(idxArg, (void *)&borderValue[0], sizeof(float) * cnocl);
|
||||
}
|
||||
if (useDouble)
|
||||
{
|
||||
UMat kernalDataUMat(kernelMatDataDouble, true);
|
||||
idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(kernalDataUMat));
|
||||
}
|
||||
else
|
||||
{
|
||||
UMat kernalDataUMat(kernelMatDataFloat, true);
|
||||
idxArg = kernel.set(idxArg, ocl::KernelArg::PtrReadOnly(kernalDataUMat));
|
||||
}
|
||||
return kernel.run(2, globalsize, localsize, true);
|
||||
}
|
||||
}
|
||||
|
||||
cv::Ptr<cv::BaseFilter> cv::getLinearFilter(int srcType, int dstType,
|
||||
InputArray filter_kernel, Point anchor,
|
||||
double delta, int bits)
|
||||
@ -3230,6 +3431,10 @@ void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth,
|
||||
InputArray _kernel, Point anchor,
|
||||
double delta, int borderType )
|
||||
{
|
||||
bool use_opencl = ocl::useOpenCL() && _dst.isUMat();
|
||||
if( use_opencl && ocl_filter2D(_src, _dst, ddepth, _kernel, anchor, delta, borderType))
|
||||
return;
|
||||
|
||||
Mat src = _src.getMat(), kernel = _kernel.getMat();
|
||||
|
||||
if( ddepth < 0 )
|
||||
|
59
modules/imgproc/src/opencl/bilateral.cl
Normal file
59
modules/imgproc/src/opencl/bilateral.cl
Normal file
@ -0,0 +1,59 @@
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Rock Li, Rock.li@amd.com
|
||||
//
|
||||
// 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.
|
||||
|
||||
__kernel void bilateral(__global const uchar * src, int src_step, int src_offset,
|
||||
__global uchar * dst, int dst_step, int dst_offset, int dst_rows, int dst_cols,
|
||||
__constant float * color_weight, __constant float * space_weight, __constant int * space_ofs)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (y < dst_rows && x < dst_cols)
|
||||
{
|
||||
int src_index = mad24(y + radius, src_step, x + radius + src_offset);
|
||||
int dst_index = mad24(y, dst_step, x + dst_offset);
|
||||
float sum = 0.f, wsum = 0.f;
|
||||
int val0 = convert_int(src[src_index]);
|
||||
|
||||
#pragma unroll
|
||||
for (int k = 0; k < maxk; k++ )
|
||||
{
|
||||
int val = convert_int(src[src_index + space_ofs[k]]);
|
||||
float w = space_weight[k] * color_weight[abs(val - val0)];
|
||||
sum += (float)(val) * w;
|
||||
wsum += w;
|
||||
}
|
||||
dst[dst_index] = convert_uchar_rtz(sum / wsum + 0.5f);
|
||||
}
|
||||
}
|
88
modules/imgproc/src/opencl/blend_linear.cl
Normal file
88
modules/imgproc/src/opencl/blend_linear.cl
Normal file
@ -0,0 +1,88 @@
|
||||
/*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) 2010-2012, MulticoreWare Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Liu Liujun, liujun@multicorewareinc.com
|
||||
//
|
||||
// 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*/
|
||||
|
||||
#ifdef DOUBLE_SUPPORT
|
||||
#ifdef cl_amd_fp64
|
||||
#pragma OPENCL EXTENSION cl_amd_fp64:enable
|
||||
#elif defined (cl_khr_fp64)
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define noconvert
|
||||
|
||||
__kernel void blendLinear(__global const uchar * src1ptr, int src1_step, int src1_offset,
|
||||
__global const uchar * src2ptr, int src2_step, int src2_offset,
|
||||
__global const uchar * weight1, int weight1_step, int weight1_offset,
|
||||
__global const uchar * weight2, int weight2_step, int weight2_offset,
|
||||
__global uchar * dstptr, int dst_step, int dst_offset, int dst_rows, int dst_cols)
|
||||
{
|
||||
int x = get_global_id(0);
|
||||
int y = get_global_id(1);
|
||||
|
||||
if (x < dst_cols && y < dst_rows)
|
||||
{
|
||||
int src1_index = mad24(y, src1_step, src1_offset + x * cn * (int)sizeof(T));
|
||||
int src2_index = mad24(y, src2_step, src2_offset + x * cn * (int)sizeof(T));
|
||||
int weight1_index = mad24(y, weight1_step, weight1_offset + x * (int)sizeof(float));
|
||||
int weight2_index = mad24(y, weight2_step, weight2_offset + x * (int)sizeof(float));
|
||||
int dst_index = mad24(y, dst_step, dst_offset + x * cn * (int)sizeof(T));
|
||||
|
||||
float w1 = *(__global const float *)(weight1 + weight1_index),
|
||||
w2 = *(__global const float *)(weight2 + weight2_index);
|
||||
float den = w1 + w2 + 1e-5f;
|
||||
|
||||
__global const T * src1 = (__global const T *)(src1ptr + src1_index);
|
||||
__global const T * src2 = (__global const T *)(src2ptr + src2_index);
|
||||
__global T * dst = (__global T *)(dstptr + dst_index);
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 0; i < cn; ++i)
|
||||
{
|
||||
float num = w1 * convert_float(src1[i]) + w2 * convert_float(src2[i]);
|
||||
dst[i] = convertToT(num / den);
|
||||
}
|
||||
}
|
||||
}
|
375
modules/imgproc/src/opencl/filter2D.cl
Normal file
375
modules/imgproc/src/opencl/filter2D.cl
Normal file
@ -0,0 +1,375 @@
|
||||
/*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) 2010-2013, Advanced Micro Devices, 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*/
|
||||
|
||||
#ifdef BORDER_REPLICATE
|
||||
//BORDER_REPLICATE: aaaaaa|abcdefgh|hhhhhhh
|
||||
#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? (l_edge) : (i))
|
||||
#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? (r_edge)-1 : (addr))
|
||||
#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? (t_edge) :(i))
|
||||
#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? (b_edge)-1 :(addr))
|
||||
#endif
|
||||
|
||||
#ifdef BORDER_REFLECT
|
||||
//BORDER_REFLECT: fedcba|abcdefgh|hgfedcb
|
||||
#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? -(i)-1 : (i))
|
||||
#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? -(i)-1+((r_edge)<<1) : (addr))
|
||||
#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? -(i)-1 : (i))
|
||||
#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? -(i)-1+((b_edge)<<1) : (addr))
|
||||
#endif
|
||||
|
||||
#ifdef BORDER_REFLECT_101
|
||||
//BORDER_REFLECT_101: gfedcb|abcdefgh|gfedcba
|
||||
#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? -(i) : (i))
|
||||
#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? -(i)-2+((r_edge)<<1) : (addr))
|
||||
#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? -(i) : (i))
|
||||
#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? -(i)-2+((b_edge)<<1) : (addr))
|
||||
#endif
|
||||
|
||||
//blur function does not support BORDER_WRAP
|
||||
#ifdef BORDER_WRAP
|
||||
//BORDER_WRAP: cdefgh|abcdefgh|abcdefg
|
||||
#define ADDR_L(i, l_edge, r_edge) ((i) < (l_edge) ? (i)+(r_edge) : (i))
|
||||
#define ADDR_R(i, r_edge, addr) ((i) >= (r_edge) ? (i)-(r_edge) : (addr))
|
||||
#define ADDR_H(i, t_edge, b_edge) ((i) < (t_edge) ? (i)+(b_edge) : (i))
|
||||
#define ADDR_B(i, b_edge, addr) ((i) >= (b_edge) ? (i)-(b_edge) : (addr))
|
||||
#endif
|
||||
|
||||
#ifdef EXTRA_EXTRAPOLATION // border > src image size
|
||||
#ifdef BORDER_CONSTANT
|
||||
// None
|
||||
#elif defined BORDER_REPLICATE
|
||||
#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \
|
||||
{ \
|
||||
x = max(min(x, maxX - 1), minX); \
|
||||
y = max(min(y, maxY - 1), minY); \
|
||||
}
|
||||
#elif defined BORDER_WRAP
|
||||
#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \
|
||||
{ \
|
||||
if (x < minX) \
|
||||
x -= ((x - maxX + 1) / maxX) * maxX; \
|
||||
if (x >= maxX) \
|
||||
x %= maxX; \
|
||||
if (y < minY) \
|
||||
y -= ((y - maxY + 1) / maxY) * maxY; \
|
||||
if (y >= maxY) \
|
||||
y %= maxY; \
|
||||
}
|
||||
#elif defined(BORDER_REFLECT) || defined(BORDER_REFLECT_101)
|
||||
#define EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, delta) \
|
||||
{ \
|
||||
if (maxX - minX == 1) \
|
||||
x = minX; \
|
||||
else \
|
||||
do \
|
||||
{ \
|
||||
if (x < minX) \
|
||||
x = minX - (x - minX) - 1 + delta; \
|
||||
else \
|
||||
x = maxX - 1 - (x - maxX) - delta; \
|
||||
} \
|
||||
while (x >= maxX || x < minX); \
|
||||
\
|
||||
if (maxY - minY == 1) \
|
||||
y = minY; \
|
||||
else \
|
||||
do \
|
||||
{ \
|
||||
if (y < minY) \
|
||||
y = minY - (y - minY) - 1 + delta; \
|
||||
else \
|
||||
y = maxY - 1 - (y - maxY) - delta; \
|
||||
} \
|
||||
while (y >= maxY || y < minY); \
|
||||
}
|
||||
#ifdef BORDER_REFLECT
|
||||
#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, 0)
|
||||
#elif defined(BORDER_REFLECT_101)
|
||||
#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) EXTRAPOLATE_(x, y, minX, minY, maxX, maxY, 1)
|
||||
#endif
|
||||
#else
|
||||
#error No extrapolation method
|
||||
#endif
|
||||
#else
|
||||
#define EXTRAPOLATE(x, y, minX, minY, maxX, maxY) \
|
||||
{ \
|
||||
int _row = y - minY, _col = x - minX; \
|
||||
_row = ADDR_H(_row, 0, maxY - minY); \
|
||||
_row = ADDR_B(_row, maxY - minY, _row); \
|
||||
y = _row + minY; \
|
||||
\
|
||||
_col = ADDR_L(_col, 0, maxX - minX); \
|
||||
_col = ADDR_R(_col, maxX - minX, _col); \
|
||||
x = _col + minX; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_DOUBLE
|
||||
#ifdef cl_amd_fp64
|
||||
#pragma OPENCL EXTENSION cl_amd_fp64:enable
|
||||
#elif defined (cl_khr_fp64)
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
#define FPTYPE double
|
||||
#define CONVERT_TO_FPTYPE CAT(convert_double, VEC_SIZE)
|
||||
#else
|
||||
#define FPTYPE float
|
||||
#define CONVERT_TO_FPTYPE CAT(convert_float, VEC_SIZE)
|
||||
#endif
|
||||
|
||||
#if DATA_DEPTH == 0
|
||||
#define BASE_TYPE uchar
|
||||
#elif DATA_DEPTH == 1
|
||||
#define BASE_TYPE char
|
||||
#elif DATA_DEPTH == 2
|
||||
#define BASE_TYPE ushort
|
||||
#elif DATA_DEPTH == 3
|
||||
#define BASE_TYPE short
|
||||
#elif DATA_DEPTH == 4
|
||||
#define BASE_TYPE int
|
||||
#elif DATA_DEPTH == 5
|
||||
#define BASE_TYPE float
|
||||
#elif DATA_DEPTH == 6
|
||||
#define BASE_TYPE double
|
||||
#else
|
||||
#error data_depth
|
||||
#endif
|
||||
|
||||
#define __CAT(x, y) x##y
|
||||
#define CAT(x, y) __CAT(x, y)
|
||||
|
||||
#define uchar1 uchar
|
||||
#define char1 char
|
||||
#define ushort1 ushort
|
||||
#define short1 short
|
||||
#define int1 int
|
||||
#define float1 float
|
||||
#define double1 double
|
||||
|
||||
#define convert_uchar1_sat_rte convert_uchar_sat_rte
|
||||
#define convert_char1_sat_rte convert_char_sat_rte
|
||||
#define convert_ushort1_sat_rte convert_ushort_sat_rte
|
||||
#define convert_short1_sat_rte convert_short_sat_rte
|
||||
#define convert_int1_sat_rte convert_int_sat_rte
|
||||
#define convert_float1
|
||||
#define convert_double1
|
||||
|
||||
#if DATA_DEPTH == 5 || DATA_DEPTH == 6
|
||||
#define CONVERT_TO_TYPE CAT(CAT(convert_, BASE_TYPE), VEC_SIZE)
|
||||
#else
|
||||
#define CONVERT_TO_TYPE CAT(CAT(CAT(convert_, BASE_TYPE), VEC_SIZE), _sat_rte)
|
||||
#endif
|
||||
|
||||
#define VEC_SIZE DATA_CHAN
|
||||
|
||||
#define VEC_TYPE CAT(BASE_TYPE, VEC_SIZE)
|
||||
#define TYPE VEC_TYPE
|
||||
|
||||
#define SCALAR_TYPE CAT(FPTYPE, VEC_SIZE)
|
||||
|
||||
#define INTERMEDIATE_TYPE CAT(FPTYPE, VEC_SIZE)
|
||||
|
||||
struct RectCoords
|
||||
{
|
||||
int x1, y1, x2, y2;
|
||||
};
|
||||
|
||||
//#define DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_ONLY(x) x
|
||||
#define ASSERT(condition) do { if (!(condition)) { printf("BUG in boxFilter kernel (global=%d,%d): " #condition "\n", get_global_id(0), get_global_id(1)); } } while (0)
|
||||
#else
|
||||
#define DEBUG_ONLY(x) (void)0
|
||||
#define ASSERT(condition) (void)0
|
||||
#endif
|
||||
|
||||
|
||||
inline INTERMEDIATE_TYPE readSrcPixel(int2 pos, __global const uchar* srcptr, int srcstep, const struct RectCoords srcCoords
|
||||
#ifdef BORDER_CONSTANT
|
||||
, SCALAR_TYPE borderValue
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#ifdef BORDER_ISOLATED
|
||||
if(pos.x >= srcCoords.x1 && pos.y >= srcCoords.y1 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2)
|
||||
#else
|
||||
if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2)
|
||||
#endif
|
||||
{
|
||||
//__global TYPE* ptr = (__global TYPE*)((__global char*)src + pos.x * sizeof(TYPE) + pos.y * srcStepBytes);
|
||||
__global TYPE* ptr = (__global TYPE*)(srcptr + pos.y * srcstep + pos.x * sizeof(TYPE));
|
||||
return CONVERT_TO_FPTYPE(*ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef BORDER_CONSTANT
|
||||
return borderValue;
|
||||
#else
|
||||
int selected_col = pos.x;
|
||||
int selected_row = pos.y;
|
||||
|
||||
EXTRAPOLATE(selected_col, selected_row,
|
||||
#ifdef BORDER_ISOLATED
|
||||
srcCoords.x1, srcCoords.y1,
|
||||
#else
|
||||
0, 0,
|
||||
#endif
|
||||
srcCoords.x2, srcCoords.y2
|
||||
);
|
||||
|
||||
// debug border mapping
|
||||
//printf("pos=%d,%d --> %d, %d\n", pos.x, pos.y, selected_col, selected_row);
|
||||
|
||||
pos = (int2)(selected_col, selected_row);
|
||||
if(pos.x >= 0 && pos.y >= 0 && pos.x < srcCoords.x2 && pos.y < srcCoords.y2)
|
||||
{
|
||||
//__global TYPE* ptr = (__global TYPE*)((__global char*)src + pos.x * sizeof(TYPE) + pos.y * srcStepBytes);
|
||||
__global TYPE* ptr = (__global TYPE*)(srcptr + pos.y * srcstep + pos.x * sizeof(TYPE));
|
||||
return CONVERT_TO_FPTYPE(*ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// for debug only
|
||||
DEBUG_ONLY(printf("BUG in boxFilter kernel\n"));
|
||||
return (FPTYPE)(0.0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// INPUT PARAMETER: BLOCK_SIZE_Y (via defines)
|
||||
|
||||
__kernel
|
||||
__attribute__((reqd_work_group_size(LOCAL_SIZE, 1, 1)))
|
||||
void filter2D(__global const uchar* srcptr, int srcstep, int srcOffsetX, int srcOffsetY, int srcEndX, int srcEndY,
|
||||
__global uchar* dstptr, int dststep, int dstoffset,
|
||||
int rows, int cols,
|
||||
#ifdef BORDER_CONSTANT
|
||||
SCALAR_TYPE borderValue,
|
||||
#endif
|
||||
__constant FPTYPE* kernelData // transposed: [KERNEL_SIZE_X][KERNEL_SIZE_Y2_ALIGNED]
|
||||
)
|
||||
{
|
||||
const struct RectCoords srcCoords = {srcOffsetX, srcOffsetY, srcEndX, srcEndY}; // for non-isolated border: offsetX, offsetY, wholeX, wholeY
|
||||
|
||||
const int local_id = get_local_id(0);
|
||||
const int x = local_id + (LOCAL_SIZE - (KERNEL_SIZE_X - 1)) * get_group_id(0) - ANCHOR_X;
|
||||
const int y = get_global_id(1) * BLOCK_SIZE_Y;
|
||||
|
||||
INTERMEDIATE_TYPE data[KERNEL_SIZE_Y];
|
||||
__local INTERMEDIATE_TYPE sumOfCols[LOCAL_SIZE];
|
||||
|
||||
int2 srcPos = (int2)(srcCoords.x1 + x, srcCoords.y1 + y - ANCHOR_Y);
|
||||
|
||||
int2 pos = (int2)(x, y);
|
||||
__global TYPE* dstPtr = (__global TYPE*)((__global char*)dstptr + pos.y * dststep + dstoffset + pos.x * sizeof(TYPE)); // Pointer can be out of bounds!
|
||||
bool writeResult = ((local_id >= ANCHOR_X) && (local_id < LOCAL_SIZE - (KERNEL_SIZE_X - 1 - ANCHOR_X)) &&
|
||||
(pos.x >= 0) && (pos.x < cols));
|
||||
|
||||
#if BLOCK_SIZE_Y > 1
|
||||
bool readAllpixels = true;
|
||||
int sy_index = 0; // current index in data[] array
|
||||
|
||||
dstRowsMax = min(rows, pos.y + BLOCK_SIZE_Y);
|
||||
for (;
|
||||
pos.y < dstRowsMax;
|
||||
pos.y++,
|
||||
dstPtr = (__global TYPE*)((__global char*)dstptr + dststep))
|
||||
#endif
|
||||
{
|
||||
ASSERT(pos.y < dstRowsMax);
|
||||
|
||||
for (
|
||||
#if BLOCK_SIZE_Y > 1
|
||||
int sy = readAllpixels ? 0 : -1; sy < (readAllpixels ? KERNEL_SIZE_Y : 0);
|
||||
#else
|
||||
int sy = 0, sy_index = 0; sy < KERNEL_SIZE_Y;
|
||||
#endif
|
||||
sy++, srcPos.y++)
|
||||
{
|
||||
data[sy + sy_index] = readSrcPixel(srcPos, srcptr, srcstep, srcCoords
|
||||
#ifdef BORDER_CONSTANT
|
||||
, borderValue
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
INTERMEDIATE_TYPE total_sum = 0;
|
||||
for (int sx = 0; sx < KERNEL_SIZE_X; sx++)
|
||||
{
|
||||
{
|
||||
__constant FPTYPE* k = &kernelData[KERNEL_SIZE_Y2_ALIGNED * sx
|
||||
#if BLOCK_SIZE_Y > 1
|
||||
+ KERNEL_SIZE_Y - sy_index
|
||||
#endif
|
||||
];
|
||||
INTERMEDIATE_TYPE tmp_sum = 0;
|
||||
for (int sy = 0; sy < KERNEL_SIZE_Y; sy++)
|
||||
{
|
||||
tmp_sum += data[sy] * k[sy];
|
||||
}
|
||||
|
||||
sumOfCols[local_id] = tmp_sum;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
|
||||
int id = local_id + sx - ANCHOR_X;
|
||||
if (id >= 0 && id < LOCAL_SIZE)
|
||||
total_sum += sumOfCols[id];
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
|
||||
if (writeResult)
|
||||
{
|
||||
*dstPtr = CONVERT_TO_TYPE(total_sum);
|
||||
}
|
||||
|
||||
#if BLOCK_SIZE_Y > 1
|
||||
readAllpixels = false;
|
||||
#if BLOCK_SIZE_Y > KERNEL_SIZE_Y
|
||||
sy_index = (sy_index + 1 <= KERNEL_SIZE_Y) ? sy_index + 1 : 1;
|
||||
#else
|
||||
sy_index++;
|
||||
#endif
|
||||
#endif // BLOCK_SIZE_Y == 1
|
||||
}
|
||||
}
|
512
modules/imgproc/src/opencl/integral_sqrsum.cl
Normal file
512
modules/imgproc/src/opencl/integral_sqrsum.cl
Normal file
@ -0,0 +1,512 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Shengen Yan,yanshengen@gmail.com
|
||||
//
|
||||
// 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*/
|
||||
|
||||
#ifdef DOUBLE_SUPPORT
|
||||
#ifdef cl_amd_fp64
|
||||
#pragma OPENCL EXTENSION cl_amd_fp64:enable
|
||||
#elif defined (cl_khr_fp64)
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if sqdepth == 6
|
||||
#define CONVERT(step) ((step)>>1)
|
||||
#else
|
||||
#define CONVERT(step) ((step))
|
||||
#endif
|
||||
|
||||
#define LSIZE 256
|
||||
#define LSIZE_1 255
|
||||
#define LSIZE_2 254
|
||||
#define HF_LSIZE 128
|
||||
#define LOG_LSIZE 8
|
||||
#define LOG_NUM_BANKS 5
|
||||
#define NUM_BANKS 32
|
||||
#define GET_CONFLICT_OFFSET(lid) ((lid) >> LOG_NUM_BANKS)
|
||||
|
||||
#define noconvert
|
||||
|
||||
#if sdepth == 4
|
||||
|
||||
kernel void integral_cols(__global uchar4 *src, __global int *sum, __global TYPE *sqsum,
|
||||
int src_offset, int pre_invalid, int rows, int cols, int src_step, int dst_step, int dst1_step)
|
||||
{
|
||||
int lid = get_local_id(0);
|
||||
int gid = get_group_id(0);
|
||||
int4 src_t[2], sum_t[2];
|
||||
TYPE4 sqsum_t[2];
|
||||
__local int4 lm_sum[2][LSIZE + LOG_LSIZE];
|
||||
__local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE];
|
||||
__local int* sum_p;
|
||||
__local TYPE* sqsum_p;
|
||||
src_step = src_step >> 2;
|
||||
gid = gid << 1;
|
||||
for(int i = 0; i < rows; i =i + LSIZE_1)
|
||||
{
|
||||
src_t[0] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + min(gid, cols - 1)]) : 0);
|
||||
src_t[1] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + min(gid + 1, cols - 1)]) : 0);
|
||||
|
||||
sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]);
|
||||
sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]);
|
||||
sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]);
|
||||
sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]);
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int bf_loc = lid + GET_CONFLICT_OFFSET(lid);
|
||||
lm_sum[0][bf_loc] = src_t[0];
|
||||
lm_sqsum[0][bf_loc] = convert_TYPE4(src_t[0] * src_t[0]);
|
||||
|
||||
lm_sum[1][bf_loc] = src_t[1];
|
||||
lm_sqsum[1][bf_loc] = convert_TYPE4(src_t[1] * src_t[1]);
|
||||
|
||||
int offset = 1;
|
||||
for(int d = LSIZE >> 1 ; d > 0; d>>=1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai];
|
||||
}
|
||||
offset <<= 1;
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(lid < 2)
|
||||
{
|
||||
lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0;
|
||||
lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0;
|
||||
}
|
||||
for(int d = 1; d < LSIZE; d <<= 1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
offset >>= 1;
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai];
|
||||
|
||||
lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai];
|
||||
lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step /4, loc_s1 = loc_s0 + dst_step ;
|
||||
int loc_sq0 = gid * CONVERT(dst1_step) + i + lid - 1 - pre_invalid * dst1_step / sizeof(TYPE),loc_sq1 = loc_sq0 + CONVERT(dst1_step);
|
||||
if(lid > 0 && (i+lid) <= rows)
|
||||
{
|
||||
lm_sum[0][bf_loc] += sum_t[0];
|
||||
lm_sum[1][bf_loc] += sum_t[1];
|
||||
lm_sqsum[0][bf_loc] += sqsum_t[0];
|
||||
lm_sqsum[1][bf_loc] += sqsum_t[1];
|
||||
sum_p = (__local int*)(&(lm_sum[0][bf_loc]));
|
||||
sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue;
|
||||
sum[loc_s0 + k * dst_step / 4] = sum_p[k];
|
||||
sqsum[loc_sq0 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k];
|
||||
}
|
||||
sum_p = (__local int*)(&(lm_sum[1][bf_loc]));
|
||||
sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 4 + k + 4 >= cols + pre_invalid) break;
|
||||
sum[loc_s1 + k * dst_step / 4] = sum_p[k];
|
||||
sqsum[loc_sq1 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
|
||||
kernel void integral_rows(__global int4 *srcsum, __global TYPE4 * srcsqsum,__global int *sum,
|
||||
__global TYPE *sqsum, int rows, int cols, int src_step, int src1_step, int sum_step,
|
||||
int sqsum_step, int sum_offset, int sqsum_offset)
|
||||
{
|
||||
int lid = get_local_id(0);
|
||||
int gid = get_group_id(0);
|
||||
int4 src_t[2], sum_t[2];
|
||||
TYPE4 sqsrc_t[2],sqsum_t[2];
|
||||
__local int4 lm_sum[2][LSIZE + LOG_LSIZE];
|
||||
__local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE];
|
||||
__local int *sum_p;
|
||||
__local TYPE *sqsum_p;
|
||||
src_step = src_step >> 4;
|
||||
src1_step = (src1_step / sizeof(TYPE)) >> 2 ;
|
||||
gid <<= 1;
|
||||
for(int i = 0; i < rows; i =i + LSIZE_1)
|
||||
{
|
||||
src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid ] : (int4)0;
|
||||
sqsrc_t[0] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid ] : (TYPE4)0;
|
||||
src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid + 1] : (int4)0;
|
||||
sqsrc_t[1] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid + 1] : (TYPE4)0;
|
||||
|
||||
sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]);
|
||||
sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]);
|
||||
sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]);
|
||||
sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]);
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int bf_loc = lid + GET_CONFLICT_OFFSET(lid);
|
||||
lm_sum[0][bf_loc] = src_t[0];
|
||||
lm_sqsum[0][bf_loc] = sqsrc_t[0];
|
||||
|
||||
lm_sum[1][bf_loc] = src_t[1];
|
||||
lm_sqsum[1][bf_loc] = sqsrc_t[1];
|
||||
|
||||
int offset = 1;
|
||||
for(int d = LSIZE >> 1 ; d > 0; d>>=1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai];
|
||||
}
|
||||
offset <<= 1;
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(lid < 2)
|
||||
{
|
||||
lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0;
|
||||
lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0;
|
||||
}
|
||||
for(int d = 1; d < LSIZE; d <<= 1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
offset >>= 1;
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai];
|
||||
|
||||
lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai];
|
||||
lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(gid == 0 && (i + lid) <= rows)
|
||||
{
|
||||
sum[sum_offset + i + lid] = 0;
|
||||
sqsum[sqsum_offset + i + lid] = 0;
|
||||
}
|
||||
if(i + lid == 0)
|
||||
{
|
||||
int loc0 = gid * sum_step;
|
||||
int loc1 = gid * CONVERT(sqsum_step);
|
||||
for(int k = 1; k <= 8; k++)
|
||||
{
|
||||
if(gid * 4 + k > cols) break;
|
||||
sum[sum_offset + loc0 + k * sum_step / 4] = 0;
|
||||
sqsum[sqsum_offset + loc1 + k * sqsum_step / sizeof(TYPE)] = 0;
|
||||
}
|
||||
}
|
||||
int loc_s0 = sum_offset + gid * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ;
|
||||
int loc_sq0 = sqsum_offset + gid * CONVERT(sqsum_step) + sqsum_step / sizeof(TYPE) + i + lid, loc_sq1 = loc_sq0 + CONVERT(sqsum_step) ;
|
||||
|
||||
if(lid > 0 && (i+lid) <= rows)
|
||||
{
|
||||
lm_sum[0][bf_loc] += sum_t[0];
|
||||
lm_sum[1][bf_loc] += sum_t[1];
|
||||
lm_sqsum[0][bf_loc] += sqsum_t[0];
|
||||
lm_sqsum[1][bf_loc] += sqsum_t[1];
|
||||
sum_p = (__local int*)(&(lm_sum[0][bf_loc]));
|
||||
sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 4 + k >= cols) break;
|
||||
sum[loc_s0 + k * sum_step / 4] = sum_p[k];
|
||||
sqsum[loc_sq0 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k];
|
||||
}
|
||||
sum_p = (__local int*)(&(lm_sum[1][bf_loc]));
|
||||
sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 4 + 4 + k >= cols) break;
|
||||
sum[loc_s1 + k * sum_step / 4] = sum_p[k];
|
||||
sqsum[loc_sq1 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
|
||||
#elif sdepth == 5
|
||||
|
||||
kernel void integral_cols(__global uchar4 *src, __global float *sum, __global TYPE *sqsum,
|
||||
int src_offset, int pre_invalid, int rows, int cols, int src_step, int dst_step, int dst1_step)
|
||||
{
|
||||
int lid = get_local_id(0);
|
||||
int gid = get_group_id(0);
|
||||
float4 src_t[2], sum_t[2];
|
||||
TYPE4 sqsum_t[2];
|
||||
__local float4 lm_sum[2][LSIZE + LOG_LSIZE];
|
||||
__local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE];
|
||||
__local float* sum_p;
|
||||
__local TYPE* sqsum_p;
|
||||
src_step = src_step >> 2;
|
||||
gid = gid << 1;
|
||||
for(int i = 0; i < rows; i =i + LSIZE_1)
|
||||
{
|
||||
src_t[0] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + min(gid, cols - 1)]) : (float4)0);
|
||||
src_t[1] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + min(gid + 1, cols - 1)]) : (float4)0);
|
||||
|
||||
sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]);
|
||||
sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]);
|
||||
sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]);
|
||||
sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]);
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int bf_loc = lid + GET_CONFLICT_OFFSET(lid);
|
||||
lm_sum[0][bf_loc] = src_t[0];
|
||||
lm_sqsum[0][bf_loc] = convert_TYPE4(src_t[0] * src_t[0]);
|
||||
// printf("%f\n", src_t[0].s0);
|
||||
|
||||
lm_sum[1][bf_loc] = src_t[1];
|
||||
lm_sqsum[1][bf_loc] = convert_TYPE4(src_t[1] * src_t[1]);
|
||||
|
||||
int offset = 1;
|
||||
for(int d = LSIZE >> 1 ; d > 0; d>>=1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai];
|
||||
}
|
||||
offset <<= 1;
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(lid < 2)
|
||||
{
|
||||
lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0;
|
||||
lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0;
|
||||
}
|
||||
for(int d = 1; d < LSIZE; d <<= 1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
offset >>= 1;
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai];
|
||||
|
||||
lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai];
|
||||
lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step / 4, loc_s1 = loc_s0 + dst_step ;
|
||||
int loc_sq0 = gid * CONVERT(dst1_step) + i + lid - 1 - pre_invalid * dst1_step / sizeof(TYPE), loc_sq1 = loc_sq0 + CONVERT(dst1_step);
|
||||
if(lid > 0 && (i+lid) <= rows)
|
||||
{
|
||||
lm_sum[0][bf_loc] += sum_t[0];
|
||||
lm_sum[1][bf_loc] += sum_t[1];
|
||||
lm_sqsum[0][bf_loc] += sqsum_t[0];
|
||||
lm_sqsum[1][bf_loc] += sqsum_t[1];
|
||||
sum_p = (__local float*)(&(lm_sum[0][bf_loc]));
|
||||
sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue;
|
||||
sum[loc_s0 + k * dst_step / 4] = sum_p[k];
|
||||
sqsum[loc_sq0 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k];
|
||||
}
|
||||
sum_p = (__local float*)(&(lm_sum[1][bf_loc]));
|
||||
sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 4 + k + 4 >= cols + pre_invalid) break;
|
||||
sum[loc_s1 + k * dst_step / 4] = sum_p[k];
|
||||
sqsum[loc_sq1 + k * dst1_step / sizeof(TYPE)] = sqsum_p[k];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
|
||||
kernel void integral_rows(__global float4 *srcsum, __global TYPE4 * srcsqsum, __global float *sum ,
|
||||
__global TYPE *sqsum, int rows, int cols, int src_step, int src1_step, int sum_step,
|
||||
int sqsum_step, int sum_offset, int sqsum_offset)
|
||||
{
|
||||
int lid = get_local_id(0);
|
||||
int gid = get_group_id(0);
|
||||
float4 src_t[2], sum_t[2];
|
||||
TYPE4 sqsrc_t[2],sqsum_t[2];
|
||||
__local float4 lm_sum[2][LSIZE + LOG_LSIZE];
|
||||
__local TYPE4 lm_sqsum[2][LSIZE + LOG_LSIZE];
|
||||
__local float *sum_p;
|
||||
__local TYPE *sqsum_p;
|
||||
src_step = src_step >> 4;
|
||||
src1_step = (src1_step / sizeof(TYPE)) >> 2;
|
||||
for(int i = 0; i < rows; i =i + LSIZE_1)
|
||||
{
|
||||
src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2] : (float4)0;
|
||||
sqsrc_t[0] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid * 2] : (TYPE4)0;
|
||||
src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2 + 1] : (float4)0;
|
||||
sqsrc_t[1] = i + lid < rows ? srcsqsum[(lid+i) * src1_step + gid * 2 + 1] : (TYPE4)0;
|
||||
|
||||
sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]);
|
||||
sqsum_t[0] = (i == 0 ? (TYPE4)0 : lm_sqsum[0][LSIZE_2 + LOG_LSIZE]);
|
||||
sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]);
|
||||
sqsum_t[1] = (i == 0 ? (TYPE4)0 : lm_sqsum[1][LSIZE_2 + LOG_LSIZE]);
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int bf_loc = lid + GET_CONFLICT_OFFSET(lid);
|
||||
lm_sum[0][bf_loc] = src_t[0];
|
||||
lm_sqsum[0][bf_loc] = sqsrc_t[0];
|
||||
|
||||
lm_sum[1][bf_loc] = src_t[1];
|
||||
lm_sqsum[1][bf_loc] = sqsrc_t[1];
|
||||
|
||||
int offset = 1;
|
||||
for(int d = LSIZE >> 1 ; d > 0; d>>=1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai];
|
||||
}
|
||||
offset <<= 1;
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(lid < 2)
|
||||
{
|
||||
lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0;
|
||||
lm_sqsum[lid][LSIZE_2 + LOG_LSIZE] = 0;
|
||||
}
|
||||
for(int d = 1; d < LSIZE; d <<= 1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
offset >>= 1;
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai];
|
||||
|
||||
lm_sqsum[lid >> 7][bi] += lm_sqsum[lid >> 7][ai];
|
||||
lm_sqsum[lid >> 7][ai] = lm_sqsum[lid >> 7][bi] - lm_sqsum[lid >> 7][ai];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(gid == 0 && (i + lid) <= rows)
|
||||
{
|
||||
sum[sum_offset + i + lid] = 0;
|
||||
sqsum[sqsum_offset + i + lid] = 0;
|
||||
}
|
||||
if(i + lid == 0)
|
||||
{
|
||||
int loc0 = gid * 2 * sum_step;
|
||||
int loc1 = gid * 2 * CONVERT(sqsum_step);
|
||||
for(int k = 1; k <= 8; k++)
|
||||
{
|
||||
if(gid * 8 + k > cols) break;
|
||||
sum[sum_offset + loc0 + k * sum_step / 4] = 0;
|
||||
sqsum[sqsum_offset + loc1 + k * sqsum_step / sizeof(TYPE)] = 0;
|
||||
}
|
||||
}
|
||||
int loc_s0 = sum_offset + gid * 2 * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ;
|
||||
int loc_sq0 = sqsum_offset + gid * 2 * CONVERT(sqsum_step) + sqsum_step / sizeof(TYPE) + i + lid, loc_sq1 = loc_sq0 + CONVERT(sqsum_step) ;
|
||||
if(lid > 0 && (i+lid) <= rows)
|
||||
{
|
||||
lm_sum[0][bf_loc] += sum_t[0];
|
||||
lm_sum[1][bf_loc] += sum_t[1];
|
||||
lm_sqsum[0][bf_loc] += sqsum_t[0];
|
||||
lm_sqsum[1][bf_loc] += sqsum_t[1];
|
||||
sum_p = (__local float*)(&(lm_sum[0][bf_loc]));
|
||||
sqsum_p = (__local TYPE*)(&(lm_sqsum[0][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 8 + k >= cols) break;
|
||||
sum[loc_s0 + k * sum_step / 4] = sum_p[k];
|
||||
sqsum[loc_sq0 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k];
|
||||
}
|
||||
sum_p = (__local float*)(&(lm_sum[1][bf_loc]));
|
||||
sqsum_p = (__local TYPE*)(&(lm_sqsum[1][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 8 + 4 + k >= cols) break;
|
||||
sum[loc_s1 + k * sum_step / 4] = sum_p[k];
|
||||
sqsum[loc_sq1 + k * sqsum_step / sizeof(TYPE)] = sqsum_p[k];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
413
modules/imgproc/src/opencl/integral_sum.cl
Normal file
413
modules/imgproc/src/opencl/integral_sum.cl
Normal file
@ -0,0 +1,413 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Shengen Yan,yanshengen@gmail.com
|
||||
//
|
||||
// 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*/
|
||||
|
||||
#ifdef DOUBLE_SUPPORT
|
||||
#ifdef cl_amd_fp64
|
||||
#pragma OPENCL EXTENSION cl_amd_fp64:enable
|
||||
#elif defined (cl_khr_fp64)
|
||||
#pragma OPENCL EXTENSION cl_khr_fp64:enable
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define LSIZE 256
|
||||
#define LSIZE_1 255
|
||||
#define LSIZE_2 254
|
||||
#define HF_LSIZE 128
|
||||
#define LOG_LSIZE 8
|
||||
#define LOG_NUM_BANKS 5
|
||||
#define NUM_BANKS 32
|
||||
#define GET_CONFLICT_OFFSET(lid) ((lid) >> LOG_NUM_BANKS)
|
||||
|
||||
#if sdepth == 4
|
||||
|
||||
kernel void integral_sum_cols(__global uchar4 *src, __global int *sum,
|
||||
int src_offset, int pre_invalid, int rows, int cols, int src_step, int dst_step)
|
||||
{
|
||||
int lid = get_local_id(0);
|
||||
int gid = get_group_id(0);
|
||||
int4 src_t[2], sum_t[2];
|
||||
__local int4 lm_sum[2][LSIZE + LOG_LSIZE];
|
||||
__local int* sum_p;
|
||||
src_step = src_step >> 2;
|
||||
gid = gid << 1;
|
||||
for(int i = 0; i < rows; i =i + LSIZE_1)
|
||||
{
|
||||
src_t[0] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + gid]) : 0);
|
||||
src_t[1] = (i + lid < rows ? convert_int4(src[src_offset + (lid+i) * src_step + gid + 1]) : 0);
|
||||
|
||||
sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]);
|
||||
sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]);
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int bf_loc = lid + GET_CONFLICT_OFFSET(lid);
|
||||
lm_sum[0][bf_loc] = src_t[0];
|
||||
|
||||
lm_sum[1][bf_loc] = src_t[1];
|
||||
|
||||
int offset = 1;
|
||||
for(int d = LSIZE >> 1 ; d > 0; d>>=1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
}
|
||||
offset <<= 1;
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(lid < 2)
|
||||
{
|
||||
lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0;
|
||||
}
|
||||
for(int d = 1; d < LSIZE; d <<= 1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
offset >>= 1;
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(lid > 0 && (i+lid) <= rows)
|
||||
{
|
||||
int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step / 4, loc_s1 = loc_s0 + dst_step ;
|
||||
lm_sum[0][bf_loc] += sum_t[0];
|
||||
lm_sum[1][bf_loc] += sum_t[1];
|
||||
sum_p = (__local int*)(&(lm_sum[0][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue;
|
||||
sum[loc_s0 + k * dst_step / 4] = sum_p[k];
|
||||
}
|
||||
sum_p = (__local int*)(&(lm_sum[1][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 4 + k + 4 >= cols + pre_invalid) break;
|
||||
sum[loc_s1 + k * dst_step / 4] = sum_p[k];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
|
||||
kernel void integral_sum_rows(__global int4 *srcsum, __global int *sum,
|
||||
int rows, int cols, int src_step, int sum_step, int sum_offset)
|
||||
{
|
||||
int lid = get_local_id(0);
|
||||
int gid = get_group_id(0);
|
||||
int4 src_t[2], sum_t[2];
|
||||
__local int4 lm_sum[2][LSIZE + LOG_LSIZE];
|
||||
__local int *sum_p;
|
||||
src_step = src_step >> 4;
|
||||
for(int i = 0; i < rows; i =i + LSIZE_1)
|
||||
{
|
||||
src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2] : 0;
|
||||
src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2 + 1] : 0;
|
||||
|
||||
sum_t[0] = (i == 0 ? 0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]);
|
||||
sum_t[1] = (i == 0 ? 0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]);
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int bf_loc = lid + GET_CONFLICT_OFFSET(lid);
|
||||
lm_sum[0][bf_loc] = src_t[0];
|
||||
|
||||
lm_sum[1][bf_loc] = src_t[1];
|
||||
|
||||
int offset = 1;
|
||||
for(int d = LSIZE >> 1 ; d > 0; d>>=1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
}
|
||||
offset <<= 1;
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(lid < 2)
|
||||
{
|
||||
lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0;
|
||||
}
|
||||
for(int d = 1; d < LSIZE; d <<= 1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
offset >>= 1;
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(gid == 0 && (i + lid) <= rows)
|
||||
{
|
||||
sum[sum_offset + i + lid] = 0;
|
||||
}
|
||||
if(i + lid == 0)
|
||||
{
|
||||
int loc0 = gid * 2 * sum_step;
|
||||
for(int k = 1; k <= 8; k++)
|
||||
{
|
||||
if(gid * 8 + k > cols) break;
|
||||
sum[sum_offset + loc0 + k * sum_step / 4] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(lid > 0 && (i+lid) <= rows)
|
||||
{
|
||||
int loc_s0 = sum_offset + gid * 2 * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ;
|
||||
lm_sum[0][bf_loc] += sum_t[0];
|
||||
lm_sum[1][bf_loc] += sum_t[1];
|
||||
sum_p = (__local int*)(&(lm_sum[0][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 8 + k >= cols) break;
|
||||
sum[loc_s0 + k * sum_step / 4] = sum_p[k];
|
||||
}
|
||||
sum_p = (__local int*)(&(lm_sum[1][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 8 + 4 + k >= cols) break;
|
||||
sum[loc_s1 + k * sum_step / 4] = sum_p[k];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
|
||||
#elif sdepth == 5
|
||||
|
||||
kernel void integral_sum_cols(__global uchar4 *src, __global float *sum,
|
||||
int src_offset, int pre_invalid, int rows, int cols, int src_step, int dst_step)
|
||||
{
|
||||
int lid = get_local_id(0);
|
||||
int gid = get_group_id(0);
|
||||
float4 src_t[2], sum_t[2];
|
||||
__local float4 lm_sum[2][LSIZE + LOG_LSIZE];
|
||||
__local float* sum_p;
|
||||
src_step = src_step >> 2;
|
||||
gid = gid << 1;
|
||||
for(int i = 0; i < rows; i =i + LSIZE_1)
|
||||
{
|
||||
src_t[0] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + gid]) : (float4)0);
|
||||
src_t[1] = (i + lid < rows ? convert_float4(src[src_offset + (lid+i) * src_step + gid + 1]) : (float4)0);
|
||||
|
||||
sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]);
|
||||
sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]);
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int bf_loc = lid + GET_CONFLICT_OFFSET(lid);
|
||||
lm_sum[0][bf_loc] = src_t[0];
|
||||
|
||||
lm_sum[1][bf_loc] = src_t[1];
|
||||
|
||||
int offset = 1;
|
||||
for(int d = LSIZE >> 1 ; d > 0; d>>=1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
}
|
||||
offset <<= 1;
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(lid < 2)
|
||||
{
|
||||
lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0;
|
||||
}
|
||||
for(int d = 1; d < LSIZE; d <<= 1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
offset >>= 1;
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(lid > 0 && (i+lid) <= rows)
|
||||
{
|
||||
int loc_s0 = gid * dst_step + i + lid - 1 - pre_invalid * dst_step / 4, loc_s1 = loc_s0 + dst_step ;
|
||||
lm_sum[0][bf_loc] += sum_t[0];
|
||||
lm_sum[1][bf_loc] += sum_t[1];
|
||||
sum_p = (__local float*)(&(lm_sum[0][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 4 + k >= cols + pre_invalid || gid * 4 + k < pre_invalid) continue;
|
||||
sum[loc_s0 + k * dst_step / 4] = sum_p[k];
|
||||
}
|
||||
sum_p = (__local float*)(&(lm_sum[1][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 4 + k + 4 >= cols + pre_invalid) break;
|
||||
sum[loc_s1 + k * dst_step / 4] = sum_p[k];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
|
||||
kernel void integral_sum_rows(__global float4 *srcsum, __global float *sum,
|
||||
int rows, int cols, int src_step, int sum_step, int sum_offset)
|
||||
{
|
||||
int lid = get_local_id(0);
|
||||
int gid = get_group_id(0);
|
||||
float4 src_t[2], sum_t[2];
|
||||
__local float4 lm_sum[2][LSIZE + LOG_LSIZE];
|
||||
__local float *sum_p;
|
||||
src_step = src_step >> 4;
|
||||
for(int i = 0; i < rows; i =i + LSIZE_1)
|
||||
{
|
||||
src_t[0] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2] : (float4)0;
|
||||
src_t[1] = i + lid < rows ? srcsum[(lid+i) * src_step + gid * 2 + 1] : (float4)0;
|
||||
|
||||
sum_t[0] = (i == 0 ? (float4)0 : lm_sum[0][LSIZE_2 + LOG_LSIZE]);
|
||||
sum_t[1] = (i == 0 ? (float4)0 : lm_sum[1][LSIZE_2 + LOG_LSIZE]);
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int bf_loc = lid + GET_CONFLICT_OFFSET(lid);
|
||||
lm_sum[0][bf_loc] = src_t[0];
|
||||
|
||||
lm_sum[1][bf_loc] = src_t[1];
|
||||
|
||||
int offset = 1;
|
||||
for(int d = LSIZE >> 1 ; d > 0; d>>=1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
}
|
||||
offset <<= 1;
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(lid < 2)
|
||||
{
|
||||
lm_sum[lid][LSIZE_2 + LOG_LSIZE] = 0;
|
||||
}
|
||||
for(int d = 1; d < LSIZE; d <<= 1)
|
||||
{
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
offset >>= 1;
|
||||
int ai = offset * (((lid & 127)<<1) +1) - 1,bi = ai + offset;
|
||||
ai += GET_CONFLICT_OFFSET(ai);
|
||||
bi += GET_CONFLICT_OFFSET(bi);
|
||||
|
||||
if((lid & 127) < d)
|
||||
{
|
||||
lm_sum[lid >> 7][bi] += lm_sum[lid >> 7][ai];
|
||||
lm_sum[lid >> 7][ai] = lm_sum[lid >> 7][bi] - lm_sum[lid >> 7][ai];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
if(gid == 0 && (i + lid) <= rows)
|
||||
{
|
||||
sum[sum_offset + i + lid] = 0;
|
||||
}
|
||||
if(i + lid == 0)
|
||||
{
|
||||
int loc0 = gid * 2 * sum_step;
|
||||
for(int k = 1; k <= 8; k++)
|
||||
{
|
||||
if(gid * 8 + k > cols) break;
|
||||
sum[sum_offset + loc0 + k * sum_step / 4] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(lid > 0 && (i+lid) <= rows)
|
||||
{
|
||||
int loc_s0 = sum_offset + gid * 2 * sum_step + sum_step / 4 + i + lid, loc_s1 = loc_s0 + sum_step ;
|
||||
lm_sum[0][bf_loc] += sum_t[0];
|
||||
lm_sum[1][bf_loc] += sum_t[1];
|
||||
sum_p = (__local float*)(&(lm_sum[0][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 8 + k >= cols) break;
|
||||
sum[loc_s0 + k * sum_step / 4] = sum_p[k];
|
||||
}
|
||||
sum_p = (__local float*)(&(lm_sum[1][bf_loc]));
|
||||
for(int k = 0; k < 4; k++)
|
||||
{
|
||||
if(gid * 8 + 4 + k >= cols) break;
|
||||
sum[loc_s1 + k * sum_step / 4] = sum_p[k];
|
||||
}
|
||||
}
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -64,7 +64,7 @@ adjustRect( const uchar* src, size_t src_step, int pix_size,
|
||||
rect.x = win_size.width;
|
||||
}
|
||||
|
||||
if( ip.x + win_size.width < src_size.width )
|
||||
if( ip.x < src_size.width - win_size.width )
|
||||
rect.width = win_size.width;
|
||||
else
|
||||
{
|
||||
@ -85,7 +85,7 @@ adjustRect( const uchar* src, size_t src_step, int pix_size,
|
||||
else
|
||||
rect.y = -ip.y;
|
||||
|
||||
if( ip.y + win_size.height < src_size.height )
|
||||
if( ip.y < src_size.height - win_size.height )
|
||||
rect.height = win_size.height;
|
||||
else
|
||||
{
|
||||
@ -155,8 +155,8 @@ void getRectSubPix_Cn_(const _Tp* src, size_t src_step, Size src_size,
|
||||
src_step /= sizeof(src[0]);
|
||||
dst_step /= sizeof(dst[0]);
|
||||
|
||||
if( 0 <= ip.x && ip.x + win_size.width < src_size.width &&
|
||||
0 <= ip.y && ip.y + win_size.height < src_size.height )
|
||||
if( 0 <= ip.x && ip.x < src_size.width - win_size.width &&
|
||||
0 <= ip.y && ip.y < src_size.height - win_size.height)
|
||||
{
|
||||
// extracted rectangle is totally inside the image
|
||||
src += ip.y * src_step + ip.x*cn;
|
||||
|
@ -41,6 +41,7 @@
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
/*
|
||||
* This file includes the code, contributed by Simon Perreault
|
||||
@ -797,10 +798,10 @@ cv::Mat cv::getGaussianKernel( int n, double sigma, int ktype )
|
||||
return kernel;
|
||||
}
|
||||
|
||||
namespace cv {
|
||||
|
||||
cv::Ptr<cv::FilterEngine> cv::createGaussianFilter( int type, Size ksize,
|
||||
double sigma1, double sigma2,
|
||||
int borderType )
|
||||
static void createGaussianKernels( Mat & kx, Mat & ky, int type, Size ksize,
|
||||
double sigma1, double sigma2 )
|
||||
{
|
||||
int depth = CV_MAT_DEPTH(type);
|
||||
if( sigma2 <= 0 )
|
||||
@ -818,12 +819,21 @@ cv::Ptr<cv::FilterEngine> cv::createGaussianFilter( int type, Size ksize,
|
||||
sigma1 = std::max( sigma1, 0. );
|
||||
sigma2 = std::max( sigma2, 0. );
|
||||
|
||||
Mat kx = getGaussianKernel( ksize.width, sigma1, std::max(depth, CV_32F) );
|
||||
Mat ky;
|
||||
kx = getGaussianKernel( ksize.width, sigma1, std::max(depth, CV_32F) );
|
||||
if( ksize.height == ksize.width && std::abs(sigma1 - sigma2) < DBL_EPSILON )
|
||||
ky = kx;
|
||||
else
|
||||
ky = getGaussianKernel( ksize.height, sigma2, std::max(depth, CV_32F) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cv::Ptr<cv::FilterEngine> cv::createGaussianFilter( int type, Size ksize,
|
||||
double sigma1, double sigma2,
|
||||
int borderType )
|
||||
{
|
||||
Mat kx, ky;
|
||||
createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2);
|
||||
|
||||
return createSeparableLinearFilter( type, type, kx, ky, Point(-1,-1), 0, borderType );
|
||||
}
|
||||
@ -833,33 +843,34 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize,
|
||||
double sigma1, double sigma2,
|
||||
int borderType )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
_dst.create( src.size(), src.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
int type = _src.type();
|
||||
Size size = _src.size();
|
||||
_dst.create( size, type );
|
||||
|
||||
if( borderType != BORDER_CONSTANT )
|
||||
{
|
||||
if( src.rows == 1 )
|
||||
if( size.height == 1 )
|
||||
ksize.height = 1;
|
||||
if( src.cols == 1 )
|
||||
if( size.width == 1 )
|
||||
ksize.width = 1;
|
||||
}
|
||||
|
||||
if( ksize.width == 1 && ksize.height == 1 )
|
||||
{
|
||||
src.copyTo(dst);
|
||||
_src.copyTo(_dst);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
if(sigma1 == 0 && sigma2 == 0 && tegra::gaussian(src, dst, ksize, borderType))
|
||||
if(sigma1 == 0 && sigma2 == 0 && tegra::gaussian(_src.getMat(), _dst.getMat(), ksize, borderType))
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7)
|
||||
if(src.type() == CV_32FC1 && sigma1 == sigma2 && ksize.width == ksize.height && sigma1 != 0.0 )
|
||||
if( type == CV_32FC1 && sigma1 == sigma2 && ksize.width == ksize.height && sigma1 != 0.0 )
|
||||
{
|
||||
IppiSize roi = {src.cols, src.rows};
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
IppiSize roi = { src.cols, src.rows };
|
||||
int bufSize = 0;
|
||||
ippiFilterGaussGetBufferSize_32f_C1R(roi, ksize.width, &bufSize);
|
||||
AutoBuffer<uchar> buf(bufSize+128);
|
||||
@ -872,11 +883,11 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize,
|
||||
}
|
||||
#endif
|
||||
|
||||
Ptr<FilterEngine> f = createGaussianFilter( src.type(), ksize, sigma1, sigma2, borderType );
|
||||
f->apply( src, dst );
|
||||
Mat kx, ky;
|
||||
createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2);
|
||||
sepFilter2D(_src, _dst, CV_MAT_DEPTH(type), kx, ky, Point(-1,-1), 0, borderType );
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************\
|
||||
Median Filter
|
||||
\****************************************************************************************/
|
||||
@ -1914,19 +1925,91 @@ private:
|
||||
};
|
||||
#endif
|
||||
|
||||
static bool ocl_bilateralFilter_8u(InputArray _src, OutputArray _dst, int d,
|
||||
double sigma_color, double sigma_space,
|
||||
int borderType)
|
||||
{
|
||||
int type = _src.type(), cn = CV_MAT_CN(type);
|
||||
int i, j, maxk, radius;
|
||||
|
||||
if ( type != CV_8UC1 )
|
||||
return false;
|
||||
|
||||
if (sigma_color <= 0)
|
||||
sigma_color = 1;
|
||||
if (sigma_space <= 0)
|
||||
sigma_space = 1;
|
||||
|
||||
double gauss_color_coeff = -0.5 / (sigma_color * sigma_color);
|
||||
double gauss_space_coeff = -0.5 / (sigma_space * sigma_space);
|
||||
|
||||
if ( d <= 0 )
|
||||
radius = cvRound(sigma_space * 1.5);
|
||||
else
|
||||
radius = d / 2;
|
||||
radius = MAX(radius, 1);
|
||||
d = radius * 2 + 1;
|
||||
|
||||
UMat src = _src.getUMat(), dst = _dst.getUMat(), temp;
|
||||
if (src.u == dst.u)
|
||||
return false;
|
||||
|
||||
copyMakeBorder(src, temp, radius, radius, radius, radius, borderType);
|
||||
|
||||
std::vector<float> _color_weight(cn * 256);
|
||||
std::vector<float> _space_weight(d * d);
|
||||
std::vector<int> _space_ofs(d * d);
|
||||
float *color_weight = &_color_weight[0];
|
||||
float *space_weight = &_space_weight[0];
|
||||
int *space_ofs = &_space_ofs[0];
|
||||
|
||||
// initialize color-related bilateral filter coefficients
|
||||
for( i = 0; i < 256 * cn; i++ )
|
||||
color_weight[i] = (float)std::exp(i * i * gauss_color_coeff);
|
||||
|
||||
// initialize space-related bilateral filter coefficients
|
||||
for( i = -radius, maxk = 0; i <= radius; i++ )
|
||||
for( j = -radius; j <= radius; j++ )
|
||||
{
|
||||
double r = std::sqrt((double)i * i + (double)j * j);
|
||||
if ( r > radius )
|
||||
continue;
|
||||
space_weight[maxk] = (float)std::exp(r * r * gauss_space_coeff);
|
||||
space_ofs[maxk++] = (int)(i * temp.step + j);
|
||||
}
|
||||
|
||||
ocl::Kernel k("bilateral", ocl::imgproc::bilateral_oclsrc,
|
||||
format("-D radius=%d -D maxk=%d", radius, maxk));
|
||||
if (k.empty())
|
||||
return false;
|
||||
|
||||
Mat mcolor_weight(1, cn * 256, CV_32FC1, color_weight);
|
||||
Mat mspace_weight(1, d * d, CV_32FC1, space_weight);
|
||||
Mat mspace_ofs(1, d * d, CV_32SC1, space_ofs);
|
||||
UMat ucolor_weight, uspace_weight, uspace_ofs;
|
||||
mcolor_weight.copyTo(ucolor_weight);
|
||||
mspace_weight.copyTo(uspace_weight);
|
||||
mspace_ofs.copyTo(uspace_ofs);
|
||||
|
||||
k.args(ocl::KernelArg::ReadOnlyNoSize(temp), ocl::KernelArg::WriteOnly(dst),
|
||||
ocl::KernelArg::PtrReadOnly(ucolor_weight),
|
||||
ocl::KernelArg::PtrReadOnly(uspace_weight),
|
||||
ocl::KernelArg::PtrReadOnly(uspace_ofs));
|
||||
|
||||
size_t globalsize[2] = { dst.cols, dst.rows };
|
||||
return k.run(2, globalsize, NULL, false);
|
||||
}
|
||||
|
||||
static void
|
||||
bilateralFilter_8u( const Mat& src, Mat& dst, int d,
|
||||
double sigma_color, double sigma_space,
|
||||
int borderType )
|
||||
{
|
||||
|
||||
int cn = src.channels();
|
||||
int i, j, maxk, radius;
|
||||
Size size = src.size();
|
||||
|
||||
CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) &&
|
||||
src.type() == dst.type() && src.size() == dst.size() &&
|
||||
src.data != dst.data );
|
||||
CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) && src.data != dst.data );
|
||||
|
||||
if( sigma_color <= 0 )
|
||||
sigma_color = 1;
|
||||
@ -1973,7 +2056,7 @@ bilateralFilter_8u( const Mat& src, Mat& dst, int d,
|
||||
{
|
||||
j = -radius;
|
||||
|
||||
for( ;j <= radius; j++ )
|
||||
for( ; j <= radius; j++ )
|
||||
{
|
||||
double r = std::sqrt((double)i*i + (double)j*j);
|
||||
if( r > radius )
|
||||
@ -2184,9 +2267,7 @@ bilateralFilter_32f( const Mat& src, Mat& dst, int d,
|
||||
float len, scale_index;
|
||||
Size size = src.size();
|
||||
|
||||
CV_Assert( (src.type() == CV_32FC1 || src.type() == CV_32FC3) &&
|
||||
src.type() == dst.type() && src.size() == dst.size() &&
|
||||
src.data != dst.data );
|
||||
CV_Assert( (src.type() == CV_32FC1 || src.type() == CV_32FC3) && src.data != dst.data );
|
||||
|
||||
if( sigma_color <= 0 )
|
||||
sigma_color = 1;
|
||||
@ -2267,9 +2348,13 @@ void cv::bilateralFilter( InputArray _src, OutputArray _dst, int d,
|
||||
double sigmaColor, double sigmaSpace,
|
||||
int borderType )
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
_dst.create( src.size(), src.type() );
|
||||
Mat dst = _dst.getMat();
|
||||
_dst.create( _src.size(), _src.type() );
|
||||
|
||||
if (ocl::useOpenCL() && _src.dims() <= 2 && _dst.isUMat() &&
|
||||
ocl_bilateralFilter_8u(_src, _dst, d, sigmaColor, sigmaSpace, borderType))
|
||||
return;
|
||||
|
||||
Mat src = _src.getMat(), dst = _dst.getMat();
|
||||
|
||||
if( src.depth() == CV_8U )
|
||||
bilateralFilter_8u( src, dst, d, sigmaColor, sigmaSpace, borderType );
|
||||
|
@ -41,6 +41,8 @@
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "opencl_kernels.hpp"
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
static IppStatus sts = ippInit();
|
||||
#endif
|
||||
@ -215,30 +217,140 @@ static void integral_##suffix( T* src, size_t srcstep, ST* sum, size_t sumstep,
|
||||
{ integral_(src, srcstep, sum, sumstep, sqsum, sqsumstep, tilted, tiltedstep, size, cn); }
|
||||
|
||||
DEF_INTEGRAL_FUNC(8u32s, uchar, int, double)
|
||||
DEF_INTEGRAL_FUNC(8u32f, uchar, float, double)
|
||||
DEF_INTEGRAL_FUNC(8u64f, uchar, double, double)
|
||||
DEF_INTEGRAL_FUNC(16u64f, ushort, double, double)
|
||||
DEF_INTEGRAL_FUNC(16s64f, short, double, double)
|
||||
DEF_INTEGRAL_FUNC(32f, float, float, double)
|
||||
DEF_INTEGRAL_FUNC(32f64f, float, double, double)
|
||||
DEF_INTEGRAL_FUNC(64f, double, double, double)
|
||||
DEF_INTEGRAL_FUNC(8u32f64f, uchar, float, double)
|
||||
DEF_INTEGRAL_FUNC(8u64f64f, uchar, double, double)
|
||||
DEF_INTEGRAL_FUNC(16u64f64f, ushort, double, double)
|
||||
DEF_INTEGRAL_FUNC(16s64f64f, short, double, double)
|
||||
DEF_INTEGRAL_FUNC(32f32f64f, float, float, double)
|
||||
DEF_INTEGRAL_FUNC(32f64f64f, float, double, double)
|
||||
DEF_INTEGRAL_FUNC(64f64f64f, double, double, double)
|
||||
|
||||
DEF_INTEGRAL_FUNC(8u32s32f, uchar, int, float)
|
||||
DEF_INTEGRAL_FUNC(8u32f32f, uchar, float, float)
|
||||
DEF_INTEGRAL_FUNC(32f32f32f, float, float, float)
|
||||
|
||||
typedef void (*IntegralFunc)(const uchar* src, size_t srcstep, uchar* sum, size_t sumstep,
|
||||
uchar* sqsum, size_t sqsumstep, uchar* tilted, size_t tstep,
|
||||
Size size, int cn );
|
||||
|
||||
enum { vlen = 4 };
|
||||
|
||||
static bool ocl_integral( InputArray _src, OutputArray _sum, int sdepth )
|
||||
{
|
||||
if ( _src.type() != CV_8UC1 || _src.step() % vlen != 0 || _src.offset() % vlen != 0 ||
|
||||
!(sdepth == CV_32S || sdepth == CV_32F) )
|
||||
return false;
|
||||
|
||||
ocl::Kernel k1("integral_sum_cols", ocl::imgproc::integral_sum_oclsrc,
|
||||
format("-D sdepth=%d", sdepth));
|
||||
if (k1.empty())
|
||||
return false;
|
||||
|
||||
Size size = _src.size(), t_size = Size(((size.height + vlen - 1) / vlen) * vlen, size.width),
|
||||
ssize(size.width + 1, size.height + 1);
|
||||
_sum.create(ssize, sdepth);
|
||||
UMat src = _src.getUMat(), t_sum(t_size, sdepth), sum = _sum.getUMat();
|
||||
t_sum = t_sum(Range::all(), Range(0, size.height));
|
||||
|
||||
int offset = (int)src.offset / vlen, pre_invalid = (int)src.offset % vlen;
|
||||
int vcols = (pre_invalid + src.cols + vlen - 1) / vlen;
|
||||
int sum_offset = (int)sum.offset / vlen;
|
||||
|
||||
k1.args(ocl::KernelArg::PtrReadOnly(src), ocl::KernelArg::PtrWriteOnly(t_sum),
|
||||
offset, pre_invalid, src.rows, src.cols, (int)src.step, (int)t_sum.step);
|
||||
size_t gt = ((vcols + 1) / 2) * 256, lt = 256;
|
||||
if (!k1.run(1, >, <, false))
|
||||
return false;
|
||||
|
||||
ocl::Kernel k2("integral_sum_rows", ocl::imgproc::integral_sum_oclsrc,
|
||||
format("-D sdepth=%d", sdepth));
|
||||
k2.args(ocl::KernelArg::PtrReadWrite(t_sum), ocl::KernelArg::PtrWriteOnly(sum),
|
||||
t_sum.rows, t_sum.cols, (int)t_sum.step, (int)sum.step, sum_offset);
|
||||
|
||||
size_t gt2 = t_sum.cols * 32, lt2 = 256;
|
||||
return k2.run(1, >2, <2, false);
|
||||
}
|
||||
|
||||
static bool ocl_integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, int sdepth, int sqdepth )
|
||||
{
|
||||
bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0;
|
||||
|
||||
if ( _src.type() != CV_8UC1 || _src.step() % vlen != 0 || _src.offset() % vlen != 0 ||
|
||||
(!doubleSupport && (sdepth == CV_64F || sqdepth == CV_64F)) )
|
||||
return false;
|
||||
|
||||
char cvt[40];
|
||||
String opts = format("-D sdepth=%d -D sqdepth=%d -D TYPE=%s -D TYPE4=%s4 -D convert_TYPE4=%s%s",
|
||||
sdepth, sqdepth, ocl::typeToStr(sqdepth), ocl::typeToStr(sqdepth),
|
||||
ocl::convertTypeStr(sdepth, sqdepth, 4, cvt),
|
||||
doubleSupport ? " -D DOUBLE_SUPPORT" : "");
|
||||
|
||||
ocl::Kernel k1("integral_cols", ocl::imgproc::integral_sqrsum_oclsrc, opts);
|
||||
if (k1.empty())
|
||||
return false;
|
||||
|
||||
Size size = _src.size(), dsize = Size(size.width + 1, size.height + 1),
|
||||
t_size = Size(((size.height + vlen - 1) / vlen) * vlen, size.width);
|
||||
UMat src = _src.getUMat(), t_sum(t_size, sdepth), t_sqsum(t_size, sqdepth);
|
||||
t_sum = t_sum(Range::all(), Range(0, size.height));
|
||||
t_sqsum = t_sqsum(Range::all(), Range(0, size.height));
|
||||
|
||||
_sum.create(dsize, sdepth);
|
||||
_sqsum.create(dsize, sqdepth);
|
||||
UMat sum = _sum.getUMat(), sqsum = _sqsum.getUMat();
|
||||
|
||||
int offset = (int)src.offset / vlen;
|
||||
int pre_invalid = src.offset % vlen;
|
||||
int vcols = (pre_invalid + src.cols + vlen - 1) / vlen;
|
||||
int sum_offset = (int)(sum.offset / sum.elemSize());
|
||||
int sqsum_offset = (int)(sqsum.offset / sqsum.elemSize());
|
||||
|
||||
k1.args(ocl::KernelArg::PtrReadOnly(src), ocl::KernelArg::PtrWriteOnly(t_sum),
|
||||
ocl::KernelArg::PtrWriteOnly(t_sqsum), offset, pre_invalid, src.rows,
|
||||
src.cols, (int)src.step, (int)t_sum.step, (int)t_sqsum.step);
|
||||
|
||||
size_t gt = ((vcols + 1) / 2) * 256, lt = 256;
|
||||
if (!k1.run(1, >, <, false))
|
||||
return false;
|
||||
|
||||
ocl::Kernel k2("integral_rows", ocl::imgproc::integral_sqrsum_oclsrc, opts);
|
||||
if (k2.empty())
|
||||
return false;
|
||||
|
||||
k2.args(ocl::KernelArg::PtrReadOnly(t_sum), ocl::KernelArg::PtrReadOnly(t_sqsum),
|
||||
ocl::KernelArg::PtrWriteOnly(sum), ocl::KernelArg::PtrWriteOnly(sqsum),
|
||||
t_sum.rows, t_sum.cols, (int)t_sum.step, (int)t_sqsum.step,
|
||||
(int)sum.step, (int)sqsum.step, sum_offset, sqsum_offset);
|
||||
|
||||
size_t gt2 = t_sum.cols * 32, lt2 = 256;
|
||||
return k2.run(1, >2, <2, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, OutputArray _tilted, int sdepth )
|
||||
void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, OutputArray _tilted, int sdepth, int sqdepth )
|
||||
{
|
||||
Mat src = _src.getMat(), sum, sqsum, tilted;
|
||||
int depth = src.depth(), cn = src.channels();
|
||||
Size isize(src.cols + 1, src.rows+1);
|
||||
|
||||
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||
if( sdepth <= 0 )
|
||||
sdepth = depth == CV_8U ? CV_32S : CV_64F;
|
||||
sdepth = CV_MAT_DEPTH(sdepth);
|
||||
if ( sqdepth <= 0 )
|
||||
sqdepth = CV_64F;
|
||||
sdepth = CV_MAT_DEPTH(sdepth), sqdepth = CV_MAT_DEPTH(sqdepth);
|
||||
|
||||
if (ocl::useOpenCL() && _sum.isUMat() && !_tilted.needed())
|
||||
{
|
||||
if (!_sqsum.needed())
|
||||
{
|
||||
if (ocl_integral(_src, _sum, sdepth))
|
||||
return;
|
||||
}
|
||||
else if (_sqsum.isUMat())
|
||||
{
|
||||
if (ocl_integral(_src, _sum, _sqsum, sdepth, sqdepth))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
|
||||
if( ( depth == CV_8U ) && ( !_tilted.needed() ) )
|
||||
@ -250,9 +362,9 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output
|
||||
IppiSize srcRoiSize = ippiSize( src.cols, src.rows );
|
||||
_sum.create( isize, CV_MAKETYPE( sdepth, cn ) );
|
||||
sum = _sum.getMat();
|
||||
if( _sqsum.needed() )
|
||||
if( _sqsum.needed() && sqdepth == CV_64F )
|
||||
{
|
||||
_sqsum.create( isize, CV_MAKETYPE( CV_64F, cn ) );
|
||||
_sqsum.create( isize, CV_MAKETYPE( sqdepth, cn ) );
|
||||
sqsum = _sqsum.getMat();
|
||||
ippiSqrIntegral_8u32f64f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32f*)sum.data, (int)sum.step, (Ipp64f*)sqsum.data, (int)sqsum.step, srcRoiSize, 0, 0 );
|
||||
}
|
||||
@ -270,9 +382,9 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output
|
||||
IppiSize srcRoiSize = ippiSize( src.cols, src.rows );
|
||||
_sum.create( isize, CV_MAKETYPE( sdepth, cn ) );
|
||||
sum = _sum.getMat();
|
||||
if( _sqsum.needed() )
|
||||
if( _sqsum.needed() && sqdepth == CV_64F )
|
||||
{
|
||||
_sqsum.create( isize, CV_MAKETYPE( CV_64F, cn ) );
|
||||
_sqsum.create( isize, CV_MAKETYPE( sqdepth, cn ) );
|
||||
sqsum = _sqsum.getMat();
|
||||
ippiSqrIntegral_8u32s64f_C1R( (const Ipp8u*)src.data, (int)src.step, (Ipp32s*)sum.data, (int)sum.step, (Ipp64f*)sqsum.data, (int)sqsum.step, srcRoiSize, 0, 0 );
|
||||
}
|
||||
@ -286,8 +398,15 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output
|
||||
}
|
||||
#endif
|
||||
|
||||
Size ssize = _src.size(), isize(ssize.width + 1, ssize.height + 1);
|
||||
_sum.create( isize, CV_MAKETYPE(sdepth, cn) );
|
||||
sum = _sum.getMat();
|
||||
Mat src = _src.getMat(), sum =_sum.getMat(), sqsum, tilted;
|
||||
|
||||
if( _sqsum.needed() )
|
||||
{
|
||||
_sqsum.create( isize, CV_MAKETYPE(sqdepth, cn) );
|
||||
sqsum = _sqsum.getMat();
|
||||
}
|
||||
|
||||
if( _tilted.needed() )
|
||||
{
|
||||
@ -295,30 +414,29 @@ void cv::integral( InputArray _src, OutputArray _sum, OutputArray _sqsum, Output
|
||||
tilted = _tilted.getMat();
|
||||
}
|
||||
|
||||
if( _sqsum.needed() )
|
||||
{
|
||||
_sqsum.create( isize, CV_MAKETYPE(CV_64F, cn) );
|
||||
sqsum = _sqsum.getMat();
|
||||
}
|
||||
|
||||
IntegralFunc func = 0;
|
||||
|
||||
if( depth == CV_8U && sdepth == CV_32S )
|
||||
if( depth == CV_8U && sdepth == CV_32S && sqdepth == CV_64F )
|
||||
func = (IntegralFunc)GET_OPTIMIZED(integral_8u32s);
|
||||
else if( depth == CV_8U && sdepth == CV_32F )
|
||||
func = (IntegralFunc)integral_8u32f;
|
||||
else if( depth == CV_8U && sdepth == CV_64F )
|
||||
func = (IntegralFunc)integral_8u64f;
|
||||
else if( depth == CV_16U && sdepth == CV_64F )
|
||||
func = (IntegralFunc)integral_16u64f;
|
||||
else if( depth == CV_16S && sdepth == CV_64F )
|
||||
func = (IntegralFunc)integral_16s64f;
|
||||
else if( depth == CV_32F && sdepth == CV_32F )
|
||||
func = (IntegralFunc)integral_32f;
|
||||
else if( depth == CV_32F && sdepth == CV_64F )
|
||||
func = (IntegralFunc)integral_32f64f;
|
||||
else if( depth == CV_64F && sdepth == CV_64F )
|
||||
func = (IntegralFunc)integral_64f;
|
||||
else if( depth == CV_8U && sdepth == CV_32S && sqdepth == CV_32F )
|
||||
func = (IntegralFunc)integral_8u32s32f;
|
||||
else if( depth == CV_8U && sdepth == CV_32F && sqdepth == CV_64F )
|
||||
func = (IntegralFunc)integral_8u32f64f;
|
||||
else if( depth == CV_8U && sdepth == CV_32F && sqdepth == CV_32F )
|
||||
func = (IntegralFunc)integral_8u32f32f;
|
||||
else if( depth == CV_8U && sdepth == CV_64F && sqdepth == CV_64F )
|
||||
func = (IntegralFunc)integral_8u64f64f;
|
||||
else if( depth == CV_16U && sdepth == CV_64F && sqdepth == CV_64F )
|
||||
func = (IntegralFunc)integral_16u64f64f;
|
||||
else if( depth == CV_16S && sdepth == CV_64F && sqdepth == CV_64F )
|
||||
func = (IntegralFunc)integral_16s64f64f;
|
||||
else if( depth == CV_32F && sdepth == CV_32F && sqdepth == CV_64F )
|
||||
func = (IntegralFunc)integral_32f32f64f;
|
||||
else if( depth == CV_32F && sdepth == CV_32F && sqdepth == CV_32F )
|
||||
func = (IntegralFunc)integral_32f32f32f;
|
||||
else if( depth == CV_32F && sdepth == CV_64F && sqdepth == CV_64F )
|
||||
func = (IntegralFunc)integral_32f64f64f;
|
||||
else if( depth == CV_64F && sdepth == CV_64F && sqdepth == CV_64F )
|
||||
func = (IntegralFunc)integral_64f64f64f;
|
||||
else
|
||||
CV_Error( CV_StsUnsupportedFormat, "" );
|
||||
|
||||
@ -331,9 +449,9 @@ void cv::integral( InputArray src, OutputArray sum, int sdepth )
|
||||
integral( src, sum, noArray(), noArray(), sdepth );
|
||||
}
|
||||
|
||||
void cv::integral( InputArray src, OutputArray sum, OutputArray sqsum, int sdepth )
|
||||
void cv::integral( InputArray src, OutputArray sum, OutputArray sqsum, int sdepth, int sqdepth )
|
||||
{
|
||||
integral( src, sum, sqsum, noArray(), sdepth );
|
||||
integral( src, sum, sqsum, noArray(), sdepth, sqdepth );
|
||||
}
|
||||
|
||||
|
||||
|
129
modules/imgproc/test/ocl/test_blend.cpp
Normal file
129
modules/imgproc/test/ocl/test_blend.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/*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) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Nathan, liujun@multicorewareinc.com
|
||||
//
|
||||
// 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 "cvconfig.h"
|
||||
#include "opencv2/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace cvtest {
|
||||
namespace ocl {
|
||||
|
||||
PARAM_TEST_CASE(BlendLinear, MatDepth, Channels, bool)
|
||||
{
|
||||
int depth, channels;
|
||||
bool useRoi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src1)
|
||||
TEST_DECLARE_INPUT_PARAMETER(src2)
|
||||
TEST_DECLARE_INPUT_PARAMETER(weights2)
|
||||
TEST_DECLARE_INPUT_PARAMETER(weights1)
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst)
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
depth = GET_PARAM(0);
|
||||
channels = GET_PARAM(1);
|
||||
useRoi = GET_PARAM(2);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
const int type = CV_MAKE_TYPE(depth, channels);
|
||||
const double upValue = 256;
|
||||
|
||||
Size roiSize = randomSize(1, 20);
|
||||
Border src1Border = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src1, src1_roi, roiSize, src1Border, type, -upValue, upValue);
|
||||
|
||||
Border src2Border = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src2, src2_roi, roiSize, src2Border, type, -upValue, upValue);
|
||||
|
||||
Border weights1Border = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(weights1, weights1_roi, roiSize, weights1Border, CV_32FC1, -upValue, upValue);
|
||||
|
||||
Border weights2Border = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(weights2, weights2_roi, roiSize, weights2Border, CV_32FC1, 1e-2, upValue);
|
||||
|
||||
weights2_roi -= weights1_roi;
|
||||
CV_Assert(checkNorm(weights2_roi, weights2(Rect(weights2Border.lef, weights2Border.top,
|
||||
roiSize.width, roiSize.height))) < 1e-6);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src1)
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src2)
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(weights1)
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(weights2)
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst)
|
||||
}
|
||||
|
||||
void Near(double eps = 0.0)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst, udst, eps);
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, eps);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(BlendLinear, Accuracy)
|
||||
{
|
||||
for (int i = 0; i < test_loop_times; ++i)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::blendLinear(src1_roi, src2_roi, weights1_roi, weights2_roi, dst_roi));
|
||||
OCL_ON(cv::blendLinear(usrc1_roi, usrc2_roi, uweights1_roi, uweights2_roi, udst_roi));
|
||||
|
||||
Near(depth <= CV_32S ? 1.0 : 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImgProc, BlendLinear, Combine(testing::Values(CV_8U, CV_32F), OCL_ALL_CHANNELS, Bool()));
|
||||
|
||||
} } // namespace cvtest::ocl
|
||||
|
||||
#endif
|
@ -86,8 +86,7 @@ PARAM_TEST_CASE(CvtColor, MatDepth, bool)
|
||||
|
||||
void Near(double threshold)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
|
||||
EXPECT_MAT_NEAR(dst, udst, threshold);
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold)
|
||||
}
|
||||
|
||||
void performTest(int channelsIn, int channelsOut, int code, double threshold = 1e-3)
|
||||
|
135
modules/imgproc/test/ocl/test_filter2d.cpp
Normal file
135
modules/imgproc/test/ocl/test_filter2d.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, 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/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace cvtest {
|
||||
namespace ocl {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Filter2D
|
||||
PARAM_TEST_CASE(Filter2D, MatDepth, Channels, BorderType, bool, bool)
|
||||
{
|
||||
static const int kernelMinSize = 2;
|
||||
static const int kernelMaxSize = 10;
|
||||
|
||||
int type;
|
||||
Size dsize;
|
||||
Point anchor;
|
||||
int borderType;
|
||||
bool useRoi;
|
||||
Mat kernel;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src)
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst)
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1));
|
||||
borderType = GET_PARAM(2) | (GET_PARAM(3) ? BORDER_ISOLATED : 0);
|
||||
useRoi = GET_PARAM(4);
|
||||
}
|
||||
|
||||
void random_roi()
|
||||
{
|
||||
dsize = randomSize(1, MAX_VALUE);
|
||||
|
||||
Size ksize = randomSize(kernelMinSize, kernelMaxSize);
|
||||
Mat temp = randomMat(ksize, CV_MAKE_TYPE(((CV_64F == CV_MAT_DEPTH(type)) ? CV_64F : CV_32F), 1), -MAX_VALUE, MAX_VALUE);
|
||||
cv::normalize(temp, kernel, 1.0, 0.0, NORM_L1);
|
||||
|
||||
Size roiSize = randomSize(ksize.width, MAX_VALUE, ksize.height, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, dsize, dstBorder, type, -MAX_VALUE, MAX_VALUE);
|
||||
|
||||
anchor.x = randomInt(-1, ksize.width);
|
||||
anchor.y = randomInt(-1, ksize.height);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src)
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst)
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst, udst, threshold);
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(Filter2D, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::filter2D(src_roi, dst_roi, -1, kernel, anchor, 0.0, borderType));
|
||||
OCL_ON(cv::filter2D(usrc_roi, udst_roi, -1, kernel, anchor, 0.0, borderType));
|
||||
|
||||
Near(1.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(ImageProc, Filter2D,
|
||||
Combine(
|
||||
Values(CV_8U, CV_16U, CV_16S, CV_32F, CV_64F),
|
||||
Values(1, 2, 4),
|
||||
Values((BorderType)BORDER_CONSTANT,
|
||||
(BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_REFLECT,
|
||||
(BorderType)BORDER_REFLECT_101),
|
||||
Bool(), // BORDER_ISOLATED
|
||||
Bool() // ROI
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
} } // namespace cvtest::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
290
modules/imgproc/test/ocl/test_filters.cpp
Normal file
290
modules/imgproc/test/ocl/test_filters.cpp
Normal file
@ -0,0 +1,290 @@
|
||||
/*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) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved.
|
||||
// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved.
|
||||
// Copyright (C) 2010-2012, Multicoreware, Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// @Authors
|
||||
// Niko Li, newlife20080214@gmail.com
|
||||
// Jia Haipeng, jiahaipeng95@gmail.com
|
||||
// Zero Lin, Zero.Lin@amd.com
|
||||
// Zhang Ying, zhangying913@gmail.com
|
||||
// Yao Wang, bitwangyaoyao@gmail.com
|
||||
//
|
||||
// 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 "cvconfig.h"
|
||||
#include "opencv2/ts/ocl_test.hpp"
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
namespace cvtest {
|
||||
namespace ocl {
|
||||
|
||||
PARAM_TEST_CASE(FilterTestBase, MatType,
|
||||
int, // kernel size
|
||||
Size, // dx, dy
|
||||
BorderType, // border type
|
||||
double, // optional parameter
|
||||
bool) // roi or not
|
||||
{
|
||||
int type, borderType, ksize;
|
||||
Size size;
|
||||
double param;
|
||||
bool useRoi;
|
||||
|
||||
TEST_DECLARE_INPUT_PARAMETER(src)
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst)
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
ksize = GET_PARAM(1);
|
||||
size = GET_PARAM(2);
|
||||
borderType = GET_PARAM(3);
|
||||
param = GET_PARAM(4);
|
||||
useRoi = GET_PARAM(5);
|
||||
}
|
||||
|
||||
void random_roi(int minSize = 1)
|
||||
{
|
||||
if (minSize == 0)
|
||||
minSize = ksize;
|
||||
|
||||
Size roiSize = randomSize(minSize, MAX_VALUE);
|
||||
Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0);
|
||||
randomSubMat(dst, dst_roi, roiSize, dstBorder, type, -60, 70);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src)
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst)
|
||||
}
|
||||
|
||||
void Near()
|
||||
{
|
||||
int depth = CV_MAT_DEPTH(type);
|
||||
bool isFP = depth >= CV_32F;
|
||||
|
||||
if (isFP)
|
||||
Near(1e-6, true);
|
||||
else
|
||||
Near(1, false);
|
||||
}
|
||||
|
||||
void Near(double threshold, bool relative)
|
||||
{
|
||||
if (relative)
|
||||
{
|
||||
EXPECT_MAT_NEAR_RELATIVE(dst, udst, threshold);
|
||||
EXPECT_MAT_NEAR_RELATIVE(dst_roi, udst_roi, threshold);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst, udst, threshold);
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Bilateral
|
||||
|
||||
typedef FilterTestBase Bilateral;
|
||||
|
||||
OCL_TEST_P(Bilateral, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
double sigmacolor = rng.uniform(20, 100);
|
||||
double sigmaspace = rng.uniform(10, 40);
|
||||
|
||||
OCL_OFF(cv::bilateralFilter(src_roi, dst_roi, ksize, sigmacolor, sigmaspace, borderType));
|
||||
OCL_ON(cv::bilateralFilter(usrc_roi, udst_roi, ksize, sigmacolor, sigmaspace, borderType));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Laplacian
|
||||
|
||||
typedef FilterTestBase LaplacianTest;
|
||||
|
||||
OCL_TEST_P(LaplacianTest, Accuracy)
|
||||
{
|
||||
double scale = param;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::Laplacian(src_roi, dst_roi, -1, ksize, scale, 0, borderType));
|
||||
OCL_ON(cv::Laplacian(usrc_roi, udst_roi, -1, ksize, scale, 0, borderType));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Sobel
|
||||
|
||||
typedef FilterTestBase SobelTest;
|
||||
|
||||
OCL_TEST_P(SobelTest, Mat)
|
||||
{
|
||||
int dx = size.width, dy = size.height;
|
||||
double scale = param;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::Sobel(src_roi, dst_roi, -1, dx, dy, ksize, scale, /* delta */0, borderType));
|
||||
OCL_ON(cv::Sobel(usrc_roi, udst_roi, -1, dx, dy, ksize, scale, /* delta */0, borderType));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Scharr
|
||||
|
||||
typedef FilterTestBase ScharrTest;
|
||||
|
||||
OCL_TEST_P(ScharrTest, Mat)
|
||||
{
|
||||
int dx = size.width, dy = size.height;
|
||||
double scale = param;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::Scharr(src_roi, dst_roi, -1, dx, dy, scale, /* delta */ 0, borderType));
|
||||
OCL_ON(cv::Scharr(usrc_roi, udst_roi, -1, dx, dy, scale, /* delta */ 0, borderType));
|
||||
|
||||
Near();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GaussianBlur
|
||||
|
||||
typedef FilterTestBase GaussianBlurTest;
|
||||
|
||||
OCL_TEST_P(GaussianBlurTest, Mat)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
double sigma1 = rng.uniform(0.1, 1.0);
|
||||
double sigma2 = rng.uniform(0.1, 1.0);
|
||||
|
||||
OCL_OFF(cv::GaussianBlur(src_roi, dst_roi, Size(ksize, ksize), sigma1, sigma2, borderType));
|
||||
OCL_ON(cv::GaussianBlur(usrc_roi, udst_roi, Size(ksize, ksize), sigma1, sigma2, borderType));
|
||||
|
||||
Near(CV_MAT_DEPTH(type) == CV_8U ? 3 : 5e-5, false);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define FILTER_BORDER_SET_NO_ISOLATED \
|
||||
Values((BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE, (BorderType)BORDER_REFLECT, (BorderType)BORDER_WRAP, (BorderType)BORDER_REFLECT_101/*, \
|
||||
(int)BORDER_CONSTANT|BORDER_ISOLATED, (int)BORDER_REPLICATE|BORDER_ISOLATED, \
|
||||
(int)BORDER_REFLECT|BORDER_ISOLATED, (int)BORDER_WRAP|BORDER_ISOLATED, \
|
||||
(int)BORDER_REFLECT_101|BORDER_ISOLATED*/) // WRAP and ISOLATED are not supported by cv:: version
|
||||
|
||||
#define FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED \
|
||||
Values((BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE, (BorderType)BORDER_REFLECT, /*(int)BORDER_WRAP,*/ (BorderType)BORDER_REFLECT_101/*, \
|
||||
(int)BORDER_CONSTANT|BORDER_ISOLATED, (int)BORDER_REPLICATE|BORDER_ISOLATED, \
|
||||
(int)BORDER_REFLECT|BORDER_ISOLATED, (int)BORDER_WRAP|BORDER_ISOLATED, \
|
||||
(int)BORDER_REFLECT_101|BORDER_ISOLATED*/) // WRAP and ISOLATED are not supported by cv:: version
|
||||
|
||||
#define FILTER_TYPES Values(CV_8UC1, CV_8UC2, CV_8UC4, CV_32FC1, CV_32FC4, CV_64FC1, CV_64FC4)
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, Bilateral, Combine(
|
||||
Values((MatType)CV_8UC1),
|
||||
Values(5, 9), // kernel size
|
||||
Values(Size(0, 0)), // not used
|
||||
FILTER_BORDER_SET_NO_ISOLATED,
|
||||
Values(0.0), // not used
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, LaplacianTest, Combine(
|
||||
FILTER_TYPES,
|
||||
Values(1, 3), // kernel size
|
||||
Values(Size(0, 0)), // not used
|
||||
FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED,
|
||||
Values(1.0, 0.2, 3.0), // kernel scale
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, SobelTest, Combine(
|
||||
FILTER_TYPES,
|
||||
Values(3, 5), // kernel size
|
||||
Values(Size(1, 0), Size(1, 1), Size(2, 0), Size(2, 1)), // dx, dy
|
||||
FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED,
|
||||
Values(0.0), // not used
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, ScharrTest, Combine(
|
||||
FILTER_TYPES,
|
||||
Values(0), // not used
|
||||
Values(Size(0, 1), Size(1, 0)), // dx, dy
|
||||
FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED,
|
||||
Values(1.0, 0.2), // kernel scale
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Filter, GaussianBlurTest, Combine(
|
||||
FILTER_TYPES,
|
||||
Values(3, 5), // kernel size
|
||||
Values(Size(0, 0)), // not used
|
||||
FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED,
|
||||
Values(0.0), // not used
|
||||
Bool()));
|
||||
|
||||
} } // namespace cvtest::ocl
|
||||
|
||||
#endif // HAVE_OPENCL
|
@ -97,15 +97,9 @@ PARAM_TEST_CASE(ImgprocTestBase, MatType,
|
||||
void Near(double threshold = 0.0, bool relative = false)
|
||||
{
|
||||
if (relative)
|
||||
{
|
||||
EXPECT_MAT_NEAR_RELATIVE(dst, udst, threshold);
|
||||
EXPECT_MAT_NEAR_RELATIVE(dst_roi, udst_roi, threshold);
|
||||
}
|
||||
OCL_EXPECT_MATS_NEAR_RELATIVE(dst, threshold)
|
||||
else
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst, udst, threshold);
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
|
||||
}
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold)
|
||||
}
|
||||
};
|
||||
|
||||
@ -158,10 +152,9 @@ PARAM_TEST_CASE(CopyMakeBorder, MatDepth, // depth
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst)
|
||||
}
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
void Near()
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst, udst, threshold);
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
|
||||
OCL_EXPECT_MATS_NEAR(dst, 0)
|
||||
}
|
||||
};
|
||||
|
||||
@ -271,15 +264,44 @@ OCL_TEST_P(CornerHarris, DISABLED_Mat)
|
||||
struct Integral :
|
||||
public ImgprocTestBase
|
||||
{
|
||||
int sdepth;
|
||||
int sdepth, sqdepth;
|
||||
|
||||
TEST_DECLARE_OUTPUT_PARAMETER(dst2)
|
||||
|
||||
virtual void SetUp()
|
||||
{
|
||||
type = GET_PARAM(0);
|
||||
blockSize = GET_PARAM(1);
|
||||
sdepth = GET_PARAM(2);
|
||||
sdepth = GET_PARAM(1);
|
||||
sqdepth = GET_PARAM(2);
|
||||
useRoi = GET_PARAM(3);
|
||||
}
|
||||
|
||||
virtual void random_roi()
|
||||
{
|
||||
ASSERT_EQ(CV_MAT_CN(type), 1);
|
||||
|
||||
Size roiSize = randomSize(1, MAX_VALUE), isize = Size(roiSize.width + 1, roiSize.height + 1);
|
||||
Border srcBorder = randomBorder(0, useRoi ? 2 : 0);
|
||||
randomSubMat(src, src_roi, roiSize, srcBorder, type, 5, 256);
|
||||
|
||||
Border dstBorder = randomBorder(0, useRoi ? 2 : 0);
|
||||
randomSubMat(dst, dst_roi, isize, dstBorder, sdepth, 5, 16);
|
||||
|
||||
Border dst2Border = randomBorder(0, useRoi ? 2 : 0);
|
||||
randomSubMat(dst2, dst2_roi, isize, dst2Border, sqdepth, 5, 16);
|
||||
|
||||
UMAT_UPLOAD_INPUT_PARAMETER(src)
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst)
|
||||
UMAT_UPLOAD_OUTPUT_PARAMETER(dst2)
|
||||
}
|
||||
|
||||
void Near2(double threshold = 0.0, bool relative = false)
|
||||
{
|
||||
if (relative)
|
||||
OCL_EXPECT_MATS_NEAR_RELATIVE(dst2, threshold)
|
||||
else
|
||||
OCL_EXPECT_MATS_NEAR(dst2, threshold)
|
||||
}
|
||||
};
|
||||
|
||||
OCL_TEST_P(Integral, Mat1)
|
||||
@ -297,19 +319,15 @@ OCL_TEST_P(Integral, Mat1)
|
||||
|
||||
OCL_TEST_P(Integral, Mat2)
|
||||
{
|
||||
Mat dst1;
|
||||
UMat udst1;
|
||||
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
random_roi();
|
||||
|
||||
OCL_OFF(cv::integral(src_roi, dst_roi, dst1, sdepth));
|
||||
OCL_ON(cv::integral(usrc_roi, udst_roi, udst1, sdepth));
|
||||
OCL_OFF(cv::integral(src_roi, dst_roi, dst2_roi, sdepth, sqdepth));
|
||||
OCL_ON(cv::integral(usrc_roi, udst_roi, udst2_roi, sdepth, sqdepth));
|
||||
|
||||
Near();
|
||||
if (cv::ocl::Device::getDefault().doubleFPConfig() > 0)
|
||||
EXPECT_MAT_NEAR(dst1, udst1, 0.);
|
||||
sqdepth == CV_32F ? Near2(1e-6, true) : Near2();
|
||||
}
|
||||
}
|
||||
|
||||
@ -381,8 +399,7 @@ PARAM_TEST_CASE(CLAHETest, Size, double, bool)
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst, udst, threshold);
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold)
|
||||
}
|
||||
};
|
||||
|
||||
@ -412,19 +429,21 @@ OCL_INSTANTIATE_TEST_CASE_P(Imgproc, EqualizeHist, Combine(
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, CornerMinEigenVal, Combine(
|
||||
Values((MatType)CV_8UC1, (MatType)CV_32FC1),
|
||||
Values(3, 5),
|
||||
Values((int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, (int)BORDER_REFLECT101),
|
||||
Values((BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_REFLECT, (BorderType)BORDER_REFLECT101),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, CornerHarris, Combine(
|
||||
Values((MatType)CV_8UC1, CV_32FC1),
|
||||
Values(3, 5),
|
||||
Values( (int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, (int)BORDER_REFLECT_101),
|
||||
Values( (BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE,
|
||||
(BorderType)BORDER_REFLECT, (BorderType)BORDER_REFLECT_101),
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, Integral, Combine(
|
||||
Values((MatType)CV_8UC1), // TODO does not work with CV_32F, CV_64F
|
||||
Values(0), // not used
|
||||
Values((MatType)CV_32SC1, (MatType)CV_32FC1),
|
||||
Values(CV_32SC1, CV_32FC1), // desired sdepth
|
||||
Values(CV_32FC1, CV_64FC1), // desired sqdepth
|
||||
Bool()));
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(Imgproc, Threshold, Combine(
|
||||
|
@ -104,8 +104,7 @@ PARAM_TEST_CASE(WarpTestBase, MatType, Interpolation, bool, bool)
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst, udst, threshold);
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold)
|
||||
}
|
||||
};
|
||||
|
||||
@ -203,8 +202,7 @@ PARAM_TEST_CASE(Resize, MatType, double, double, Interpolation, bool)
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
|
||||
EXPECT_MAT_NEAR(dst, udst, threshold);
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold)
|
||||
}
|
||||
};
|
||||
|
||||
@ -280,8 +278,7 @@ PARAM_TEST_CASE(Remap, MatDepth, Channels, std::pair<MatType, MatType>, BorderTy
|
||||
|
||||
void Near(double threshold = 0.0)
|
||||
{
|
||||
EXPECT_MAT_NEAR(dst, udst, threshold);
|
||||
EXPECT_MAT_NEAR(dst_roi, udst_roi, threshold);
|
||||
OCL_EXPECT_MATS_NEAR(dst, threshold)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1225,7 +1225,7 @@ public class ImgprocTest extends OpenCVTestCase {
|
||||
expSqsum.put(2, 0, 0, 18, 36, 54);
|
||||
expSqsum.put(3, 0, 0, 27, 54, 81);
|
||||
|
||||
Imgproc.integral2(src, sum, sqsum, CvType.CV_64F);
|
||||
Imgproc.integral2(src, sum, sqsum, CvType.CV_64F, CvType.CV_64F);
|
||||
|
||||
assertMatEqual(expSum, sum, EPS);
|
||||
assertMatEqual(expSqsum, sqsum, EPS);
|
||||
@ -1274,7 +1274,7 @@ public class ImgprocTest extends OpenCVTestCase {
|
||||
expTilted.put(0, 0, 0, 0);
|
||||
expTilted.put(1, 0, 0, 1);
|
||||
|
||||
Imgproc.integral3(src, sum, sqsum, tilted, CvType.CV_64F);
|
||||
Imgproc.integral3(src, sum, sqsum, tilted, CvType.CV_64F, CvType.CV_64F);
|
||||
|
||||
assertMatEqual(expSum, sum, EPS);
|
||||
assertMatEqual(expSqsum, sqsum, EPS);
|
||||
|
@ -221,44 +221,6 @@ The function is parallelized with the TBB library.
|
||||
* (Python) A face detection example using cascade classifiers can be found at opencv_source_code/samples/python2/facedetect.py
|
||||
|
||||
|
||||
CascadeClassifier::setImage
|
||||
-------------------------------
|
||||
Sets an image for detection.
|
||||
|
||||
.. ocv:function:: bool CascadeClassifier::setImage( Ptr<FeatureEvaluator>& feval, const Mat& image )
|
||||
|
||||
.. ocv:cfunction:: void cvSetImagesForHaarClassifierCascade( CvHaarClassifierCascade* cascade, const CvArr* sum, const CvArr* sqsum, const CvArr* tilted_sum, double scale )
|
||||
|
||||
:param cascade: Haar classifier cascade (OpenCV 1.x API only). See :ocv:func:`CascadeClassifier::detectMultiScale` for more information.
|
||||
|
||||
:param feval: Pointer to the feature evaluator used for computing features.
|
||||
|
||||
:param image: Matrix of the type ``CV_8UC1`` containing an image where the features are computed.
|
||||
|
||||
The function is automatically called by :ocv:func:`CascadeClassifier::detectMultiScale` at every image scale. But if you want to test various locations manually using :ocv:func:`CascadeClassifier::runAt`, you need to call the function before, so that the integral images are computed.
|
||||
|
||||
.. note:: in the old API you need to supply integral images (that can be obtained using :ocv:cfunc:`Integral`) instead of the original image.
|
||||
|
||||
|
||||
CascadeClassifier::runAt
|
||||
----------------------------
|
||||
Runs the detector at the specified point.
|
||||
|
||||
.. ocv:function:: int CascadeClassifier::runAt( Ptr<FeatureEvaluator>& feval, Point pt, double& weight )
|
||||
|
||||
.. ocv:cfunction:: int cvRunHaarClassifierCascade( const CvHaarClassifierCascade* cascade, CvPoint pt, int start_stage=0 )
|
||||
|
||||
:param cascade: Haar classifier cascade (OpenCV 1.x API only). See :ocv:func:`CascadeClassifier::detectMultiScale` for more information.
|
||||
|
||||
:param feval: Feature evaluator used for computing features.
|
||||
|
||||
:param pt: Upper left point of the window where the features are computed. Size of the window is equal to the size of training images.
|
||||
|
||||
The function returns 1 if the cascade classifier detects an object in the given location.
|
||||
Otherwise, it returns negated index of the stage at which the candidate has been rejected.
|
||||
|
||||
Use :ocv:func:`CascadeClassifier::setImage` to set the image for the detector to work with.
|
||||
|
||||
groupRectangles
|
||||
-------------------
|
||||
Groups the object candidate rectangles.
|
||||
|
@ -149,143 +149,97 @@ enum { CASCADE_DO_CANNY_PRUNING = 1,
|
||||
CASCADE_DO_ROUGH_SEARCH = 8
|
||||
};
|
||||
|
||||
class CV_EXPORTS_W CascadeClassifier
|
||||
class CV_EXPORTS_W BaseCascadeClassifier : public Algorithm
|
||||
{
|
||||
public:
|
||||
CV_WRAP CascadeClassifier();
|
||||
CV_WRAP CascadeClassifier( const String& filename );
|
||||
virtual ~CascadeClassifier();
|
||||
virtual ~BaseCascadeClassifier();
|
||||
virtual bool empty() const = 0;
|
||||
virtual bool load( const String& filename ) = 0;
|
||||
virtual void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
double scaleFactor,
|
||||
int minNeighbors, int flags,
|
||||
Size minSize, Size maxSize ) = 0;
|
||||
|
||||
CV_WRAP virtual bool empty() const;
|
||||
CV_WRAP bool load( const String& filename );
|
||||
virtual bool read( const FileNode& node );
|
||||
CV_WRAP virtual void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
double scaleFactor = 1.1,
|
||||
int minNeighbors = 3, int flags = 0,
|
||||
Size minSize = Size(),
|
||||
Size maxSize = Size() );
|
||||
virtual void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& numDetections,
|
||||
double scaleFactor,
|
||||
int minNeighbors, int flags,
|
||||
Size minSize, Size maxSize ) = 0;
|
||||
|
||||
CV_WRAP virtual void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& numDetections,
|
||||
double scaleFactor=1.1,
|
||||
int minNeighbors=3, int flags=0,
|
||||
Size minSize=Size(),
|
||||
Size maxSize=Size() );
|
||||
|
||||
CV_WRAP virtual void detectMultiScale( InputArray image,
|
||||
virtual void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& rejectLevels,
|
||||
CV_OUT std::vector<double>& levelWeights,
|
||||
double scaleFactor = 1.1,
|
||||
int minNeighbors = 3, int flags = 0,
|
||||
Size minSize = Size(),
|
||||
Size maxSize = Size(),
|
||||
bool outputRejectLevels = false );
|
||||
double scaleFactor,
|
||||
int minNeighbors, int flags,
|
||||
Size minSize, Size maxSize,
|
||||
bool outputRejectLevels ) = 0;
|
||||
|
||||
virtual bool isOldFormatCascade() const = 0;
|
||||
virtual Size getOriginalWindowSize() const = 0;
|
||||
virtual int getFeatureType() const = 0;
|
||||
virtual void* getOldCascade() = 0;
|
||||
|
||||
bool isOldFormatCascade() const;
|
||||
virtual Size getOriginalWindowSize() const;
|
||||
int getFeatureType() const;
|
||||
bool setImage( const Mat& );
|
||||
|
||||
protected:
|
||||
virtual bool detectSingleScale( const Mat& image, int stripCount, Size processingRectSize,
|
||||
int stripSize, int yStep, double factor, std::vector<Rect>& candidates,
|
||||
std::vector<int>& rejectLevels, std::vector<double>& levelWeights, bool outputRejectLevels = false );
|
||||
|
||||
virtual void detectMultiScaleNoGrouping( const Mat& image, std::vector<Rect>& candidates,
|
||||
std::vector<int>& rejectLevels, std::vector<double>& levelWeights,
|
||||
double scaleFactor, Size minObjectSize, Size maxObjectSize,
|
||||
bool outputRejectLevels = false );
|
||||
|
||||
protected:
|
||||
enum { BOOST = 0
|
||||
};
|
||||
enum { DO_CANNY_PRUNING = CASCADE_DO_CANNY_PRUNING,
|
||||
SCALE_IMAGE = CASCADE_SCALE_IMAGE,
|
||||
FIND_BIGGEST_OBJECT = CASCADE_FIND_BIGGEST_OBJECT,
|
||||
DO_ROUGH_SEARCH = CASCADE_DO_ROUGH_SEARCH
|
||||
};
|
||||
|
||||
friend class CascadeClassifierInvoker;
|
||||
|
||||
template<class FEval>
|
||||
friend int predictOrdered( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
|
||||
|
||||
template<class FEval>
|
||||
friend int predictCategorical( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
|
||||
|
||||
template<class FEval>
|
||||
friend int predictOrderedStump( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
|
||||
|
||||
template<class FEval>
|
||||
friend int predictCategoricalStump( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
|
||||
|
||||
bool setImage( Ptr<FeatureEvaluator>& feval, const Mat& image);
|
||||
virtual int runAt( Ptr<FeatureEvaluator>& feval, Point pt, double& weight );
|
||||
|
||||
class Data
|
||||
{
|
||||
public:
|
||||
struct CV_EXPORTS DTreeNode
|
||||
{
|
||||
int featureIdx;
|
||||
float threshold; // for ordered features only
|
||||
int left;
|
||||
int right;
|
||||
};
|
||||
|
||||
struct CV_EXPORTS DTree
|
||||
{
|
||||
int nodeCount;
|
||||
};
|
||||
|
||||
struct CV_EXPORTS Stage
|
||||
{
|
||||
int first;
|
||||
int ntrees;
|
||||
float threshold;
|
||||
};
|
||||
|
||||
bool read(const FileNode &node);
|
||||
|
||||
bool isStumpBased;
|
||||
|
||||
int stageType;
|
||||
int featureType;
|
||||
int ncategories;
|
||||
Size origWinSize;
|
||||
|
||||
std::vector<Stage> stages;
|
||||
std::vector<DTree> classifiers;
|
||||
std::vector<DTreeNode> nodes;
|
||||
std::vector<float> leaves;
|
||||
std::vector<int> subsets;
|
||||
};
|
||||
|
||||
Data data;
|
||||
Ptr<FeatureEvaluator> featureEvaluator;
|
||||
Ptr<CvHaarClassifierCascade> oldCascade;
|
||||
|
||||
public:
|
||||
class CV_EXPORTS MaskGenerator
|
||||
{
|
||||
public:
|
||||
virtual ~MaskGenerator() {}
|
||||
virtual cv::Mat generateMask(const cv::Mat& src)=0;
|
||||
virtual void initializeMask(const cv::Mat& /*src*/) {};
|
||||
virtual Mat generateMask(const Mat& src)=0;
|
||||
virtual void initializeMask(const Mat& /*src*/) {};
|
||||
};
|
||||
void setMaskGenerator(Ptr<MaskGenerator> maskGenerator);
|
||||
Ptr<MaskGenerator> getMaskGenerator();
|
||||
|
||||
void setFaceDetectionMaskGenerator();
|
||||
|
||||
protected:
|
||||
Ptr<MaskGenerator> maskGenerator;
|
||||
virtual void setMaskGenerator(const Ptr<MaskGenerator>& maskGenerator) = 0;
|
||||
virtual Ptr<MaskGenerator> getMaskGenerator() = 0;
|
||||
};
|
||||
|
||||
class CV_EXPORTS_W CascadeClassifier
|
||||
{
|
||||
public:
|
||||
CV_WRAP CascadeClassifier();
|
||||
CV_WRAP CascadeClassifier(const String& filename);
|
||||
~CascadeClassifier();
|
||||
CV_WRAP bool empty() const;
|
||||
CV_WRAP bool load( const String& filename );
|
||||
CV_WRAP bool read( const FileNode& node );
|
||||
CV_WRAP void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
double scaleFactor = 1.1,
|
||||
int minNeighbors = 3, int flags = 0,
|
||||
Size minSize = Size(),
|
||||
Size maxSize = Size() );
|
||||
|
||||
CV_WRAP void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& numDetections,
|
||||
double scaleFactor=1.1,
|
||||
int minNeighbors=3, int flags=0,
|
||||
Size minSize=Size(),
|
||||
Size maxSize=Size() );
|
||||
|
||||
CV_WRAP void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& rejectLevels,
|
||||
CV_OUT std::vector<double>& levelWeights,
|
||||
double scaleFactor = 1.1,
|
||||
int minNeighbors = 3, int flags = 0,
|
||||
Size minSize = Size(),
|
||||
Size maxSize = Size(),
|
||||
bool outputRejectLevels = false );
|
||||
|
||||
CV_WRAP bool isOldFormatCascade() const;
|
||||
CV_WRAP Size getOriginalWindowSize() const;
|
||||
CV_WRAP int getFeatureType() const;
|
||||
void* getOldCascade();
|
||||
|
||||
void setMaskGenerator(const Ptr<BaseCascadeClassifier::MaskGenerator>& maskGenerator);
|
||||
Ptr<BaseCascadeClassifier::MaskGenerator> getMaskGenerator();
|
||||
|
||||
Ptr<BaseCascadeClassifier> cc;
|
||||
};
|
||||
|
||||
CV_EXPORTS Ptr<BaseCascadeClassifier::MaskGenerator> createFaceDetectionMaskGenerator();
|
||||
|
||||
//////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector //////////////
|
||||
|
||||
// struct for detection region of interest (ROI)
|
||||
|
@ -430,7 +430,6 @@ void groupRectangles_meanshift(std::vector<Rect>& rectList, std::vector<double>&
|
||||
}
|
||||
|
||||
|
||||
|
||||
FeatureEvaluator::~FeatureEvaluator() {}
|
||||
bool FeatureEvaluator::read(const FileNode&) {return true;}
|
||||
Ptr<FeatureEvaluator> FeatureEvaluator::clone() const { return Ptr<FeatureEvaluator>(); }
|
||||
@ -834,25 +833,20 @@ Ptr<FeatureEvaluator> FeatureEvaluator::create( int featureType )
|
||||
|
||||
//---------------------------------------- Classifier Cascade --------------------------------------------
|
||||
|
||||
CascadeClassifier::CascadeClassifier()
|
||||
CascadeClassifierImpl::CascadeClassifierImpl()
|
||||
{
|
||||
}
|
||||
|
||||
CascadeClassifier::CascadeClassifier(const String& filename)
|
||||
{
|
||||
load(filename);
|
||||
}
|
||||
|
||||
CascadeClassifier::~CascadeClassifier()
|
||||
CascadeClassifierImpl::~CascadeClassifierImpl()
|
||||
{
|
||||
}
|
||||
|
||||
bool CascadeClassifier::empty() const
|
||||
bool CascadeClassifierImpl::empty() const
|
||||
{
|
||||
return !oldCascade && data.stages.empty();
|
||||
}
|
||||
|
||||
bool CascadeClassifier::load(const String& filename)
|
||||
bool CascadeClassifierImpl::load(const String& filename)
|
||||
{
|
||||
oldCascade.release();
|
||||
data = Data();
|
||||
@ -862,7 +856,7 @@ bool CascadeClassifier::load(const String& filename)
|
||||
if( !fs.isOpened() )
|
||||
return false;
|
||||
|
||||
if( read(fs.getFirstTopLevelNode()) )
|
||||
if( read_(fs.getFirstTopLevelNode()) )
|
||||
return true;
|
||||
|
||||
fs.release();
|
||||
@ -871,7 +865,12 @@ bool CascadeClassifier::load(const String& filename)
|
||||
return !oldCascade.empty();
|
||||
}
|
||||
|
||||
int CascadeClassifier::runAt( Ptr<FeatureEvaluator>& evaluator, Point pt, double& weight )
|
||||
void CascadeClassifierImpl::read(const FileNode& node)
|
||||
{
|
||||
read_(node);
|
||||
}
|
||||
|
||||
int CascadeClassifierImpl::runAt( Ptr<FeatureEvaluator>& evaluator, Point pt, double& weight )
|
||||
{
|
||||
CV_Assert( !oldCascade );
|
||||
|
||||
@ -905,33 +904,33 @@ int CascadeClassifier::runAt( Ptr<FeatureEvaluator>& evaluator, Point pt, double
|
||||
}
|
||||
}
|
||||
|
||||
bool CascadeClassifier::setImage( Ptr<FeatureEvaluator>& evaluator, const Mat& image )
|
||||
bool CascadeClassifierImpl::setImage( Ptr<FeatureEvaluator>& evaluator, const Mat& image )
|
||||
{
|
||||
return empty() ? false : evaluator->setImage(image, data.origWinSize);
|
||||
}
|
||||
|
||||
void CascadeClassifier::setMaskGenerator(Ptr<MaskGenerator> _maskGenerator)
|
||||
void CascadeClassifierImpl::setMaskGenerator(const Ptr<MaskGenerator>& _maskGenerator)
|
||||
{
|
||||
maskGenerator=_maskGenerator;
|
||||
}
|
||||
Ptr<CascadeClassifier::MaskGenerator> CascadeClassifier::getMaskGenerator()
|
||||
Ptr<CascadeClassifierImpl::MaskGenerator> CascadeClassifierImpl::getMaskGenerator()
|
||||
{
|
||||
return maskGenerator;
|
||||
}
|
||||
|
||||
void CascadeClassifier::setFaceDetectionMaskGenerator()
|
||||
Ptr<BaseCascadeClassifier::MaskGenerator> createFaceDetectionMaskGenerator()
|
||||
{
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
setMaskGenerator(tegra::getCascadeClassifierMaskGenerator(*this));
|
||||
return tegra::getCascadeClassifierMaskGenerator(*this);
|
||||
#else
|
||||
setMaskGenerator(Ptr<CascadeClassifier::MaskGenerator>());
|
||||
return Ptr<BaseCascadeClassifier::MaskGenerator>();
|
||||
#endif
|
||||
}
|
||||
|
||||
class CascadeClassifierInvoker : public ParallelLoopBody
|
||||
{
|
||||
public:
|
||||
CascadeClassifierInvoker( CascadeClassifier& _cc, Size _sz1, int _stripSize, int _yStep, double _factor,
|
||||
CascadeClassifierInvoker( CascadeClassifierImpl& _cc, Size _sz1, int _stripSize, int _yStep, double _factor,
|
||||
std::vector<Rect>& _vec, std::vector<int>& _levels, std::vector<double>& _weights, bool outputLevels, const Mat& _mask, Mutex* _mtx)
|
||||
{
|
||||
classifier = &_cc;
|
||||
@ -950,7 +949,8 @@ public:
|
||||
{
|
||||
Ptr<FeatureEvaluator> evaluator = classifier->featureEvaluator->clone();
|
||||
|
||||
Size winSize(cvRound(classifier->data.origWinSize.width * scalingFactor), cvRound(classifier->data.origWinSize.height * scalingFactor));
|
||||
Size winSize(cvRound(classifier->data.origWinSize.width * scalingFactor),
|
||||
cvRound(classifier->data.origWinSize.height * scalingFactor));
|
||||
|
||||
int y1 = range.start * stripSize;
|
||||
int y2 = std::min(range.end * stripSize, processingRectSize.height);
|
||||
@ -995,7 +995,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
CascadeClassifier* classifier;
|
||||
CascadeClassifierImpl* classifier;
|
||||
std::vector<Rect>* rectangles;
|
||||
Size processingRectSize;
|
||||
int stripSize, yStep;
|
||||
@ -1010,7 +1010,7 @@ struct getRect { Rect operator ()(const CvAvgComp& e) const { return e.rect; } }
|
||||
struct getNeighbors { int operator ()(const CvAvgComp& e) const { return e.neighbors; } };
|
||||
|
||||
|
||||
bool CascadeClassifier::detectSingleScale( const Mat& image, int stripCount, Size processingRectSize,
|
||||
bool CascadeClassifierImpl::detectSingleScale( const Mat& image, int stripCount, Size processingRectSize,
|
||||
int stripSize, int yStep, double factor, std::vector<Rect>& candidates,
|
||||
std::vector<int>& levels, std::vector<double>& weights, bool outputRejectLevels )
|
||||
{
|
||||
@ -1051,27 +1051,33 @@ bool CascadeClassifier::detectSingleScale( const Mat& image, int stripCount, Siz
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CascadeClassifier::isOldFormatCascade() const
|
||||
bool CascadeClassifierImpl::isOldFormatCascade() const
|
||||
{
|
||||
return !oldCascade.empty();
|
||||
}
|
||||
|
||||
|
||||
int CascadeClassifier::getFeatureType() const
|
||||
int CascadeClassifierImpl::getFeatureType() const
|
||||
{
|
||||
return featureEvaluator->getFeatureType();
|
||||
}
|
||||
|
||||
Size CascadeClassifier::getOriginalWindowSize() const
|
||||
Size CascadeClassifierImpl::getOriginalWindowSize() const
|
||||
{
|
||||
return data.origWinSize;
|
||||
}
|
||||
|
||||
bool CascadeClassifier::setImage(const Mat& image)
|
||||
bool CascadeClassifierImpl::setImage(InputArray _image)
|
||||
{
|
||||
Mat image = _image.getMat();
|
||||
return featureEvaluator->setImage(image, data.origWinSize);
|
||||
}
|
||||
|
||||
void* CascadeClassifierImpl::getOldCascade()
|
||||
{
|
||||
return oldCascade;
|
||||
}
|
||||
|
||||
static void detectMultiScaleOldFormat( const Mat& image, Ptr<CvHaarClassifierCascade> oldCascade,
|
||||
std::vector<Rect>& objects,
|
||||
std::vector<int>& rejectLevels,
|
||||
@ -1090,7 +1096,7 @@ static void detectMultiScaleOldFormat( const Mat& image, Ptr<CvHaarClassifierCas
|
||||
std::transform(vecAvgComp.begin(), vecAvgComp.end(), objects.begin(), getRect());
|
||||
}
|
||||
|
||||
void CascadeClassifier::detectMultiScaleNoGrouping( const Mat& image, std::vector<Rect>& candidates,
|
||||
void CascadeClassifierImpl::detectMultiScaleNoGrouping( const Mat& image, std::vector<Rect>& candidates,
|
||||
std::vector<int>& rejectLevels, std::vector<double>& levelWeights,
|
||||
double scaleFactor, Size minObjectSize, Size maxObjectSize,
|
||||
bool outputRejectLevels )
|
||||
@ -1154,7 +1160,7 @@ void CascadeClassifier::detectMultiScaleNoGrouping( const Mat& image, std::vecto
|
||||
}
|
||||
}
|
||||
|
||||
void CascadeClassifier::detectMultiScale( InputArray _image, std::vector<Rect>& objects,
|
||||
void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector<Rect>& objects,
|
||||
std::vector<int>& rejectLevels,
|
||||
std::vector<double>& levelWeights,
|
||||
double scaleFactor, int minNeighbors,
|
||||
@ -1189,7 +1195,7 @@ void CascadeClassifier::detectMultiScale( InputArray _image, std::vector<Rect>&
|
||||
}
|
||||
}
|
||||
|
||||
void CascadeClassifier::detectMultiScale( InputArray _image, std::vector<Rect>& objects,
|
||||
void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector<Rect>& objects,
|
||||
double scaleFactor, int minNeighbors,
|
||||
int flags, Size minObjectSize, Size maxObjectSize)
|
||||
{
|
||||
@ -1200,7 +1206,7 @@ void CascadeClassifier::detectMultiScale( InputArray _image, std::vector<Rect>&
|
||||
minNeighbors, flags, minObjectSize, maxObjectSize );
|
||||
}
|
||||
|
||||
void CascadeClassifier::detectMultiScale( InputArray _image, std::vector<Rect>& objects,
|
||||
void CascadeClassifierImpl::detectMultiScale( InputArray _image, std::vector<Rect>& objects,
|
||||
std::vector<int>& numDetections, double scaleFactor,
|
||||
int minNeighbors, int flags, Size minObjectSize,
|
||||
Size maxObjectSize )
|
||||
@ -1229,7 +1235,7 @@ void CascadeClassifier::detectMultiScale( InputArray _image, std::vector<Rect>&
|
||||
}
|
||||
}
|
||||
|
||||
bool CascadeClassifier::Data::read(const FileNode &root)
|
||||
bool CascadeClassifierImpl::Data::read(const FileNode &root)
|
||||
{
|
||||
static const float THRESHOLD_EPS = 1e-5f;
|
||||
|
||||
@ -1339,7 +1345,7 @@ bool CascadeClassifier::Data::read(const FileNode &root)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CascadeClassifier::read(const FileNode& root)
|
||||
bool CascadeClassifierImpl::read_(const FileNode& root)
|
||||
{
|
||||
if( !data.read(root) )
|
||||
return false;
|
||||
@ -1356,4 +1362,117 @@ bool CascadeClassifier::read(const FileNode& root)
|
||||
template<> void DefaultDeleter<CvHaarClassifierCascade>::operator ()(CvHaarClassifierCascade* obj) const
|
||||
{ cvReleaseHaarClassifierCascade(&obj); }
|
||||
|
||||
|
||||
BaseCascadeClassifier::~BaseCascadeClassifier()
|
||||
{
|
||||
}
|
||||
|
||||
CascadeClassifier::CascadeClassifier() {}
|
||||
CascadeClassifier::CascadeClassifier(const String& filename)
|
||||
{
|
||||
load(filename);
|
||||
}
|
||||
|
||||
CascadeClassifier::~CascadeClassifier()
|
||||
{
|
||||
}
|
||||
|
||||
bool CascadeClassifier::empty() const
|
||||
{
|
||||
return cc.empty() || cc->empty();
|
||||
}
|
||||
|
||||
bool CascadeClassifier::load( const String& filename )
|
||||
{
|
||||
cc = makePtr<CascadeClassifierImpl>();
|
||||
if(!cc->load(filename))
|
||||
cc.release();
|
||||
return !empty();
|
||||
}
|
||||
|
||||
bool CascadeClassifier::read(const FileNode &root)
|
||||
{
|
||||
Ptr<CascadeClassifierImpl> ccimpl;
|
||||
bool ok = ccimpl->read_(root);
|
||||
if( ok )
|
||||
cc = ccimpl.staticCast<BaseCascadeClassifier>();
|
||||
else
|
||||
cc.release();
|
||||
return ok;
|
||||
}
|
||||
|
||||
void CascadeClassifier::detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
double scaleFactor,
|
||||
int minNeighbors, int flags,
|
||||
Size minSize,
|
||||
Size maxSize )
|
||||
{
|
||||
CV_Assert(!empty());
|
||||
cc->detectMultiScale(image, objects, scaleFactor, minNeighbors, flags, minSize, maxSize);
|
||||
}
|
||||
|
||||
void CascadeClassifier::detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& numDetections,
|
||||
double scaleFactor,
|
||||
int minNeighbors, int flags,
|
||||
Size minSize, Size maxSize )
|
||||
{
|
||||
CV_Assert(!empty());
|
||||
cc->detectMultiScale(image, objects, numDetections,
|
||||
scaleFactor, minNeighbors, flags, minSize, maxSize);
|
||||
}
|
||||
|
||||
void CascadeClassifier::detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& rejectLevels,
|
||||
CV_OUT std::vector<double>& levelWeights,
|
||||
double scaleFactor,
|
||||
int minNeighbors, int flags,
|
||||
Size minSize, Size maxSize,
|
||||
bool outputRejectLevels )
|
||||
{
|
||||
CV_Assert(!empty());
|
||||
cc->detectMultiScale(image, objects, rejectLevels, levelWeights,
|
||||
scaleFactor, minNeighbors, flags,
|
||||
minSize, maxSize, outputRejectLevels);
|
||||
}
|
||||
|
||||
bool CascadeClassifier::isOldFormatCascade() const
|
||||
{
|
||||
CV_Assert(!empty());
|
||||
return cc->isOldFormatCascade();
|
||||
}
|
||||
|
||||
Size CascadeClassifier::getOriginalWindowSize() const
|
||||
{
|
||||
CV_Assert(!empty());
|
||||
return cc->getOriginalWindowSize();
|
||||
}
|
||||
|
||||
int CascadeClassifier::getFeatureType() const
|
||||
{
|
||||
CV_Assert(!empty());
|
||||
return cc->getFeatureType();
|
||||
}
|
||||
|
||||
void* CascadeClassifier::getOldCascade()
|
||||
{
|
||||
CV_Assert(!empty());
|
||||
return cc->getOldCascade();
|
||||
}
|
||||
|
||||
void CascadeClassifier::setMaskGenerator(const Ptr<BaseCascadeClassifier::MaskGenerator>& maskGenerator)
|
||||
{
|
||||
CV_Assert(!empty());
|
||||
cc->setMaskGenerator(maskGenerator);
|
||||
}
|
||||
|
||||
Ptr<BaseCascadeClassifier::MaskGenerator> CascadeClassifier::getMaskGenerator()
|
||||
{
|
||||
CV_Assert(!empty());
|
||||
return cc->getMaskGenerator();
|
||||
}
|
||||
|
||||
} // namespace cv
|
||||
|
@ -3,6 +3,132 @@
|
||||
namespace cv
|
||||
{
|
||||
|
||||
class CascadeClassifierImpl : public BaseCascadeClassifier
|
||||
{
|
||||
public:
|
||||
CascadeClassifierImpl();
|
||||
virtual ~CascadeClassifierImpl();
|
||||
|
||||
bool empty() const;
|
||||
bool load( const String& filename );
|
||||
void read( const FileNode& node );
|
||||
bool read_( const FileNode& node );
|
||||
void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
double scaleFactor = 1.1,
|
||||
int minNeighbors = 3, int flags = 0,
|
||||
Size minSize = Size(),
|
||||
Size maxSize = Size() );
|
||||
|
||||
void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& numDetections,
|
||||
double scaleFactor=1.1,
|
||||
int minNeighbors=3, int flags=0,
|
||||
Size minSize=Size(),
|
||||
Size maxSize=Size() );
|
||||
|
||||
void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
CV_OUT std::vector<int>& rejectLevels,
|
||||
CV_OUT std::vector<double>& levelWeights,
|
||||
double scaleFactor = 1.1,
|
||||
int minNeighbors = 3, int flags = 0,
|
||||
Size minSize = Size(),
|
||||
Size maxSize = Size(),
|
||||
bool outputRejectLevels = false );
|
||||
|
||||
|
||||
bool isOldFormatCascade() const;
|
||||
Size getOriginalWindowSize() const;
|
||||
int getFeatureType() const;
|
||||
bool setImage( InputArray );
|
||||
void* getOldCascade();
|
||||
|
||||
void setMaskGenerator(const Ptr<MaskGenerator>& maskGenerator);
|
||||
Ptr<MaskGenerator> getMaskGenerator();
|
||||
|
||||
protected:
|
||||
bool detectSingleScale( const Mat& image, int stripCount, Size processingRectSize,
|
||||
int stripSize, int yStep, double factor, std::vector<Rect>& candidates,
|
||||
std::vector<int>& rejectLevels, std::vector<double>& levelWeights, bool outputRejectLevels = false );
|
||||
|
||||
void detectMultiScaleNoGrouping( const Mat& image, std::vector<Rect>& candidates,
|
||||
std::vector<int>& rejectLevels, std::vector<double>& levelWeights,
|
||||
double scaleFactor, Size minObjectSize, Size maxObjectSize,
|
||||
bool outputRejectLevels = false );
|
||||
|
||||
enum { BOOST = 0
|
||||
};
|
||||
enum { DO_CANNY_PRUNING = CASCADE_DO_CANNY_PRUNING,
|
||||
SCALE_IMAGE = CASCADE_SCALE_IMAGE,
|
||||
FIND_BIGGEST_OBJECT = CASCADE_FIND_BIGGEST_OBJECT,
|
||||
DO_ROUGH_SEARCH = CASCADE_DO_ROUGH_SEARCH
|
||||
};
|
||||
|
||||
friend class CascadeClassifierInvoker;
|
||||
|
||||
template<class FEval>
|
||||
friend int predictOrdered( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
|
||||
|
||||
template<class FEval>
|
||||
friend int predictCategorical( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
|
||||
|
||||
template<class FEval>
|
||||
friend int predictOrderedStump( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
|
||||
|
||||
template<class FEval>
|
||||
friend int predictCategoricalStump( CascadeClassifierImpl& cascade, Ptr<FeatureEvaluator> &featureEvaluator, double& weight);
|
||||
|
||||
bool setImage( Ptr<FeatureEvaluator>& feval, const Mat& image);
|
||||
int runAt( Ptr<FeatureEvaluator>& feval, Point pt, double& weight );
|
||||
|
||||
class Data
|
||||
{
|
||||
public:
|
||||
struct DTreeNode
|
||||
{
|
||||
int featureIdx;
|
||||
float threshold; // for ordered features only
|
||||
int left;
|
||||
int right;
|
||||
};
|
||||
|
||||
struct DTree
|
||||
{
|
||||
int nodeCount;
|
||||
};
|
||||
|
||||
struct Stage
|
||||
{
|
||||
int first;
|
||||
int ntrees;
|
||||
float threshold;
|
||||
};
|
||||
|
||||
bool read(const FileNode &node);
|
||||
|
||||
bool isStumpBased;
|
||||
|
||||
int stageType;
|
||||
int featureType;
|
||||
int ncategories;
|
||||
Size origWinSize;
|
||||
|
||||
std::vector<Stage> stages;
|
||||
std::vector<DTree> classifiers;
|
||||
std::vector<DTreeNode> nodes;
|
||||
std::vector<float> leaves;
|
||||
std::vector<int> subsets;
|
||||
};
|
||||
|
||||
Data data;
|
||||
Ptr<FeatureEvaluator> featureEvaluator;
|
||||
Ptr<CvHaarClassifierCascade> oldCascade;
|
||||
|
||||
Ptr<MaskGenerator> maskGenerator;
|
||||
};
|
||||
|
||||
#define CC_CASCADE_PARAMS "cascadeParams"
|
||||
#define CC_STAGE_TYPE "stageType"
|
||||
#define CC_FEATURE_TYPE "featureType"
|
||||
@ -322,30 +448,31 @@ inline void HOGEvaluator::Feature :: updatePtrs( const std::vector<Mat> &_hist,
|
||||
//---------------------------------------------- predictor functions -------------------------------------
|
||||
|
||||
template<class FEval>
|
||||
inline int predictOrdered( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
inline int predictOrdered( CascadeClassifierImpl& cascade,
|
||||
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
int nstages = (int)cascade.data.stages.size();
|
||||
int nodeOfs = 0, leafOfs = 0;
|
||||
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
|
||||
float* cascadeLeaves = &cascade.data.leaves[0];
|
||||
CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifier::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
|
||||
CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifierImpl::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
|
||||
CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
for( int si = 0; si < nstages; si++ )
|
||||
{
|
||||
CascadeClassifier::Data::Stage& stage = cascadeStages[si];
|
||||
CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si];
|
||||
int wi, ntrees = stage.ntrees;
|
||||
sum = 0;
|
||||
|
||||
for( wi = 0; wi < ntrees; wi++ )
|
||||
{
|
||||
CascadeClassifier::Data::DTree& weak = cascadeWeaks[stage.first + wi];
|
||||
CascadeClassifierImpl::Data::DTree& weak = cascadeWeaks[stage.first + wi];
|
||||
int idx = 0, root = nodeOfs;
|
||||
|
||||
do
|
||||
{
|
||||
CascadeClassifier::Data::DTreeNode& node = cascadeNodes[root + idx];
|
||||
CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[root + idx];
|
||||
double val = featureEvaluator(node.featureIdx);
|
||||
idx = val < node.threshold ? node.left : node.right;
|
||||
}
|
||||
@ -361,7 +488,8 @@ inline int predictOrdered( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_f
|
||||
}
|
||||
|
||||
template<class FEval>
|
||||
inline int predictCategorical( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
inline int predictCategorical( CascadeClassifierImpl& cascade,
|
||||
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
int nstages = (int)cascade.data.stages.size();
|
||||
int nodeOfs = 0, leafOfs = 0;
|
||||
@ -369,23 +497,23 @@ inline int predictCategorical( CascadeClassifier& cascade, Ptr<FeatureEvaluator>
|
||||
size_t subsetSize = (cascade.data.ncategories + 31)/32;
|
||||
int* cascadeSubsets = &cascade.data.subsets[0];
|
||||
float* cascadeLeaves = &cascade.data.leaves[0];
|
||||
CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifier::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
|
||||
CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifierImpl::Data::DTree* cascadeWeaks = &cascade.data.classifiers[0];
|
||||
CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
for(int si = 0; si < nstages; si++ )
|
||||
{
|
||||
CascadeClassifier::Data::Stage& stage = cascadeStages[si];
|
||||
CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si];
|
||||
int wi, ntrees = stage.ntrees;
|
||||
sum = 0;
|
||||
|
||||
for( wi = 0; wi < ntrees; wi++ )
|
||||
{
|
||||
CascadeClassifier::Data::DTree& weak = cascadeWeaks[stage.first + wi];
|
||||
CascadeClassifierImpl::Data::DTree& weak = cascadeWeaks[stage.first + wi];
|
||||
int idx = 0, root = nodeOfs;
|
||||
do
|
||||
{
|
||||
CascadeClassifier::Data::DTreeNode& node = cascadeNodes[root + idx];
|
||||
CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[root + idx];
|
||||
int c = featureEvaluator(node.featureIdx);
|
||||
const int* subset = &cascadeSubsets[(root + idx)*subsetSize];
|
||||
idx = (subset[c>>5] & (1 << (c & 31))) ? node.left : node.right;
|
||||
@ -402,24 +530,25 @@ inline int predictCategorical( CascadeClassifier& cascade, Ptr<FeatureEvaluator>
|
||||
}
|
||||
|
||||
template<class FEval>
|
||||
inline int predictOrderedStump( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
inline int predictOrderedStump( CascadeClassifierImpl& cascade,
|
||||
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
int nodeOfs = 0, leafOfs = 0;
|
||||
FEval& featureEvaluator = (FEval&)*_featureEvaluator;
|
||||
float* cascadeLeaves = &cascade.data.leaves[0];
|
||||
CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
int nstages = (int)cascade.data.stages.size();
|
||||
for( int stageIdx = 0; stageIdx < nstages; stageIdx++ )
|
||||
{
|
||||
CascadeClassifier::Data::Stage& stage = cascadeStages[stageIdx];
|
||||
CascadeClassifierImpl::Data::Stage& stage = cascadeStages[stageIdx];
|
||||
sum = 0.0;
|
||||
|
||||
int ntrees = stage.ntrees;
|
||||
for( int i = 0; i < ntrees; i++, nodeOfs++, leafOfs+= 2 )
|
||||
{
|
||||
CascadeClassifier::Data::DTreeNode& node = cascadeNodes[nodeOfs];
|
||||
CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[nodeOfs];
|
||||
double value = featureEvaluator(node.featureIdx);
|
||||
sum += cascadeLeaves[ value < node.threshold ? leafOfs : leafOfs + 1 ];
|
||||
}
|
||||
@ -432,7 +561,8 @@ inline int predictOrderedStump( CascadeClassifier& cascade, Ptr<FeatureEvaluator
|
||||
}
|
||||
|
||||
template<class FEval>
|
||||
inline int predictCategoricalStump( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
inline int predictCategoricalStump( CascadeClassifierImpl& cascade,
|
||||
Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
|
||||
{
|
||||
int nstages = (int)cascade.data.stages.size();
|
||||
int nodeOfs = 0, leafOfs = 0;
|
||||
@ -440,15 +570,15 @@ inline int predictCategoricalStump( CascadeClassifier& cascade, Ptr<FeatureEvalu
|
||||
size_t subsetSize = (cascade.data.ncategories + 31)/32;
|
||||
int* cascadeSubsets = &cascade.data.subsets[0];
|
||||
float* cascadeLeaves = &cascade.data.leaves[0];
|
||||
CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
CascadeClassifierImpl::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];
|
||||
CascadeClassifierImpl::Data::Stage* cascadeStages = &cascade.data.stages[0];
|
||||
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
float tmp = 0; // float accumulator -- float operations are quicker
|
||||
#endif
|
||||
for( int si = 0; si < nstages; si++ )
|
||||
{
|
||||
CascadeClassifier::Data::Stage& stage = cascadeStages[si];
|
||||
CascadeClassifierImpl::Data::Stage& stage = cascadeStages[si];
|
||||
int wi, ntrees = stage.ntrees;
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
tmp = 0;
|
||||
@ -458,7 +588,7 @@ inline int predictCategoricalStump( CascadeClassifier& cascade, Ptr<FeatureEvalu
|
||||
|
||||
for( wi = 0; wi < ntrees; wi++ )
|
||||
{
|
||||
CascadeClassifier::Data::DTreeNode& node = cascadeNodes[nodeOfs];
|
||||
CascadeClassifierImpl::Data::DTreeNode& node = cascadeNodes[nodeOfs];
|
||||
int c = featureEvaluator(node.featureIdx);
|
||||
const int* subset = &cascadeSubsets[nodeOfs*subsetSize];
|
||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
||||
|
@ -144,14 +144,6 @@ OpenCV C++ 1-D or 2-D dense array class ::
|
||||
//! returns true if oclMatrix data is NULL
|
||||
bool empty() const;
|
||||
|
||||
//! returns pointer to y-th row
|
||||
uchar* ptr(int y = 0);
|
||||
const uchar *ptr(int y = 0) const;
|
||||
|
||||
//! template version of the above method
|
||||
template<typename _Tp> _Tp *ptr(int y = 0);
|
||||
template<typename _Tp> const _Tp *ptr(int y = 0) const;
|
||||
|
||||
//! matrix transposition
|
||||
oclMat t() const;
|
||||
|
||||
|
@ -378,14 +378,6 @@ namespace cv
|
||||
//! returns true if oclMatrix data is NULL
|
||||
bool empty() const;
|
||||
|
||||
//! returns pointer to y-th row
|
||||
uchar* ptr(int y = 0);
|
||||
const uchar *ptr(int y = 0) const;
|
||||
|
||||
//! template version of the above method
|
||||
template<typename _Tp> _Tp *ptr(int y = 0);
|
||||
template<typename _Tp> const _Tp *ptr(int y = 0) const;
|
||||
|
||||
//! matrix transposition
|
||||
oclMat t() const;
|
||||
|
||||
|
@ -456,36 +456,6 @@ namespace cv
|
||||
return data == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline uchar *oclMat::ptr(int y)
|
||||
{
|
||||
CV_DbgAssert( (unsigned)y < (unsigned)rows );
|
||||
CV_Error(Error::GpuNotSupported, "This function hasn't been supported yet.\n");
|
||||
return data + step * y;
|
||||
}
|
||||
|
||||
inline const uchar *oclMat::ptr(int y) const
|
||||
{
|
||||
CV_DbgAssert( (unsigned)y < (unsigned)rows );
|
||||
CV_Error(Error::GpuNotSupported, "This function hasn't been supported yet.\n");
|
||||
return data + step * y;
|
||||
}
|
||||
|
||||
template<typename _Tp> inline _Tp *oclMat::ptr(int y)
|
||||
{
|
||||
CV_DbgAssert( (unsigned)y < (unsigned)rows );
|
||||
CV_Error(Error::GpuNotSupported, "This function hasn't been supported yet.\n");
|
||||
return (_Tp *)(data + step * y);
|
||||
}
|
||||
|
||||
template<typename _Tp> inline const _Tp *oclMat::ptr(int y) const
|
||||
{
|
||||
CV_DbgAssert( (unsigned)y < (unsigned)rows );
|
||||
CV_Error(Error::GpuNotSupported, "This function hasn't been supported yet.\n");
|
||||
return (const _Tp *)(data + step * y);
|
||||
}
|
||||
|
||||
inline oclMat oclMat::t() const
|
||||
{
|
||||
oclMat tmp;
|
||||
|
@ -73,10 +73,10 @@ PERF_TEST_P(MomentsFixture, Moments,
|
||||
Mat src(srcSize, type), dst(7, 1, CV_64F);
|
||||
randu(src, 0, 255);
|
||||
|
||||
oclMat src_d(src);
|
||||
cv::Moments mom;
|
||||
if (RUN_OCL_IMPL)
|
||||
{
|
||||
oclMat src_d(src);
|
||||
OCL_TEST_CYCLE() mom = cv::ocl::ocl_moments(src_d, binaryImage);
|
||||
}
|
||||
else if (RUN_PLAIN_IMPL)
|
||||
|
@ -676,7 +676,7 @@ void cv::ocl::BruteForceMatcher_OCL_base::matchCollection(const oclMat &query, c
|
||||
ensureSizeIsEnough(1, nQuery, CV_32S, imgIdx);
|
||||
ensureSizeIsEnough(1, nQuery, CV_32F, distance);
|
||||
|
||||
matchDispatcher(query, (const oclMat *)trainCollection.ptr(), trainCollection.cols, masks, trainIdx, imgIdx, distance, distType);
|
||||
matchDispatcher(query, &trainCollection, trainCollection.cols, masks, trainIdx, imgIdx, distance, distType);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -290,8 +290,9 @@ void openCLFree(void *devPtr)
|
||||
}
|
||||
#else
|
||||
// TODO FIXIT Attach clReleaseMemObject call to event completion callback
|
||||
Context* ctx = Context::getContext();
|
||||
clFinish(getClCommandQueue(ctx));
|
||||
// TODO 2013/12/04 Disable workaround
|
||||
// Context* ctx = Context::getContext();
|
||||
// clFinish(getClCommandQueue(ctx));
|
||||
#endif
|
||||
openCLSafeCall(clReleaseMemObject(data.mainBuffer));
|
||||
}
|
||||
|
@ -655,7 +655,7 @@ void OclCascadeClassifier::detectMultiScale(oclMat &gimg, CV_OUT std::vector<cv:
|
||||
//CvSeq *cv::ocl::OclCascadeClassifier::oclHaarDetectObjects( oclMat &gimg, CvMemStorage *storage, double scaleFactor,
|
||||
// int minNeighbors, int flags, CvSize minSize, CvSize maxSize)
|
||||
{
|
||||
CvHaarClassifierCascade *cascade = oldCascade;
|
||||
CvHaarClassifierCascade *cascade = (CvHaarClassifierCascade*)getOldCascade();
|
||||
|
||||
const double GROUP_EPS = 0.2;
|
||||
|
||||
|
@ -62,13 +62,13 @@ typedef struct __attribute__((aligned (128) )) GpuHidHaarTreeNode
|
||||
GpuHidHaarTreeNode;
|
||||
|
||||
|
||||
typedef struct __attribute__((aligned (32))) GpuHidHaarClassifier
|
||||
{
|
||||
int count __attribute__((aligned (4)));
|
||||
GpuHidHaarTreeNode* node __attribute__((aligned (8)));
|
||||
float* alpha __attribute__((aligned (8)));
|
||||
}
|
||||
GpuHidHaarClassifier;
|
||||
//typedef struct __attribute__((aligned (32))) GpuHidHaarClassifier
|
||||
//{
|
||||
// int count __attribute__((aligned (4)));
|
||||
// GpuHidHaarTreeNode* node __attribute__((aligned (8)));
|
||||
// float* alpha __attribute__((aligned (8)));
|
||||
//}
|
||||
//GpuHidHaarClassifier;
|
||||
|
||||
|
||||
typedef struct __attribute__((aligned (64))) GpuHidHaarStageClassifier
|
||||
@ -84,22 +84,22 @@ typedef struct __attribute__((aligned (64))) GpuHidHaarStageClassifier
|
||||
GpuHidHaarStageClassifier;
|
||||
|
||||
|
||||
typedef struct __attribute__((aligned (64))) GpuHidHaarClassifierCascade
|
||||
{
|
||||
int count __attribute__((aligned (4)));
|
||||
int is_stump_based __attribute__((aligned (4)));
|
||||
int has_tilted_features __attribute__((aligned (4)));
|
||||
int is_tree __attribute__((aligned (4)));
|
||||
int pq0 __attribute__((aligned (4)));
|
||||
int pq1 __attribute__((aligned (4)));
|
||||
int pq2 __attribute__((aligned (4)));
|
||||
int pq3 __attribute__((aligned (4)));
|
||||
int p0 __attribute__((aligned (4)));
|
||||
int p1 __attribute__((aligned (4)));
|
||||
int p2 __attribute__((aligned (4)));
|
||||
int p3 __attribute__((aligned (4)));
|
||||
float inv_window_area __attribute__((aligned (4)));
|
||||
} GpuHidHaarClassifierCascade;
|
||||
//typedef struct __attribute__((aligned (64))) GpuHidHaarClassifierCascade
|
||||
//{
|
||||
// int count __attribute__((aligned (4)));
|
||||
// int is_stump_based __attribute__((aligned (4)));
|
||||
// int has_tilted_features __attribute__((aligned (4)));
|
||||
// int is_tree __attribute__((aligned (4)));
|
||||
// int pq0 __attribute__((aligned (4)));
|
||||
// int pq1 __attribute__((aligned (4)));
|
||||
// int pq2 __attribute__((aligned (4)));
|
||||
// int pq3 __attribute__((aligned (4)));
|
||||
// int p0 __attribute__((aligned (4)));
|
||||
// int p1 __attribute__((aligned (4)));
|
||||
// int p2 __attribute__((aligned (4)));
|
||||
// int p3 __attribute__((aligned (4)));
|
||||
// float inv_window_area __attribute__((aligned (4)));
|
||||
//} GpuHidHaarClassifierCascade;
|
||||
|
||||
|
||||
#ifdef PACKED_CLASSIFIER
|
||||
@ -196,10 +196,12 @@ __kernel void gpuRunHaarClassifierCascadePacked(
|
||||
for(int stageloop = start_stage; (stageloop < end_stage) && result; stageloop++ )
|
||||
{// iterate until candidate is exist
|
||||
float stage_sum = 0.0f;
|
||||
int2 stageinfo = *(global int2*)(stagecascadeptr+stageloop);
|
||||
float stagethreshold = as_float(stageinfo.y);
|
||||
__global GpuHidHaarStageClassifier* stageinfo = (__global GpuHidHaarStageClassifier*)
|
||||
((__global uchar*)stagecascadeptr+stageloop*sizeof(GpuHidHaarStageClassifier));
|
||||
int stagecount = stageinfo->count;
|
||||
float stagethreshold = stageinfo->threshold;
|
||||
int lcl_off = (lid_y*DATA_SIZE_X)+(lid_x);
|
||||
for(int nodeloop = 0; nodeloop < stageinfo.x; nodecounter++,nodeloop++ )
|
||||
for(int nodeloop = 0; nodeloop < stagecount; nodecounter++,nodeloop++ )
|
||||
{
|
||||
// simple macro to extract shorts from int
|
||||
#define M0(_t) ((_t)&0xFFFF)
|
||||
@ -355,14 +357,17 @@ __kernel void __attribute__((reqd_work_group_size(8,8,1)))gpuRunHaarClassifierCa
|
||||
variance_norm_factor = variance_norm_factor * correction - mean * mean;
|
||||
variance_norm_factor = variance_norm_factor >=0.f ? sqrt(variance_norm_factor) : 1.f;
|
||||
|
||||
for(int stageloop = start_stage; (stageloop < split_stage) && result; stageloop++ )
|
||||
for(int stageloop = start_stage; (stageloop < split_stage) && result; stageloop++ )
|
||||
{
|
||||
float stage_sum = 0.f;
|
||||
int2 stageinfo = *(global int2*)(stagecascadeptr+stageloop);
|
||||
float stagethreshold = as_float(stageinfo.y);
|
||||
for(int nodeloop = 0; nodeloop < stageinfo.x; )
|
||||
__global GpuHidHaarStageClassifier* stageinfo = (__global GpuHidHaarStageClassifier*)
|
||||
((__global uchar*)stagecascadeptr+stageloop*sizeof(GpuHidHaarStageClassifier));
|
||||
int stagecount = stageinfo->count;
|
||||
float stagethreshold = stageinfo->threshold;
|
||||
for(int nodeloop = 0; nodeloop < stagecount; )
|
||||
{
|
||||
__global GpuHidHaarTreeNode* currentnodeptr = (nodeptr + nodecounter);
|
||||
__global GpuHidHaarTreeNode* currentnodeptr = (__global GpuHidHaarTreeNode*)
|
||||
(((__global uchar*)nodeptr) + nodecounter * sizeof(GpuHidHaarTreeNode));
|
||||
|
||||
int4 info1 = *(__global int4*)(&(currentnodeptr->p[0][0]));
|
||||
int4 info2 = *(__global int4*)(&(currentnodeptr->p[1][0]));
|
||||
@ -418,7 +423,7 @@ __kernel void __attribute__((reqd_work_group_size(8,8,1)))gpuRunHaarClassifierCa
|
||||
#endif
|
||||
}
|
||||
|
||||
result = (stage_sum >= stagethreshold);
|
||||
result = (stage_sum >= stagethreshold) ? 1 : 0;
|
||||
}
|
||||
if(factor < 2)
|
||||
{
|
||||
@ -447,14 +452,17 @@ __kernel void __attribute__((reqd_work_group_size(8,8,1)))gpuRunHaarClassifierCa
|
||||
lclcount[0]=0;
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
|
||||
int2 stageinfo = *(global int2*)(stagecascadeptr+stageloop);
|
||||
float stagethreshold = as_float(stageinfo.y);
|
||||
//int2 stageinfo = *(global int2*)(stagecascadeptr+stageloop);
|
||||
__global GpuHidHaarStageClassifier* stageinfo = (__global GpuHidHaarStageClassifier*)
|
||||
((__global uchar*)stagecascadeptr+stageloop*sizeof(GpuHidHaarStageClassifier));
|
||||
int stagecount = stageinfo->count;
|
||||
float stagethreshold = stageinfo->threshold;
|
||||
|
||||
int perfscale = queuecount > 4 ? 3 : 2;
|
||||
int queuecount_loop = (queuecount + (1<<perfscale)-1) >> perfscale;
|
||||
int lcl_compute_win = lcl_sz >> perfscale;
|
||||
int lcl_compute_win_id = (lcl_id >>(6-perfscale));
|
||||
int lcl_loops = (stageinfo.x + lcl_compute_win -1) >> (6-perfscale);
|
||||
int lcl_loops = (stagecount + lcl_compute_win -1) >> (6-perfscale);
|
||||
int lcl_compute_id = lcl_id - (lcl_compute_win_id << (6-perfscale));
|
||||
for(int queueloop=0; queueloop<queuecount_loop; queueloop++)
|
||||
{
|
||||
@ -469,10 +477,10 @@ __kernel void __attribute__((reqd_work_group_size(8,8,1)))gpuRunHaarClassifierCa
|
||||
float part_sum = 0.f;
|
||||
const int stump_factor = STUMP_BASED ? 1 : 2;
|
||||
int root_offset = 0;
|
||||
for(int lcl_loop=0; lcl_loop<lcl_loops && tempnodecounter<stageinfo.x;)
|
||||
for(int lcl_loop=0; lcl_loop<lcl_loops && tempnodecounter<stagecount;)
|
||||
{
|
||||
__global GpuHidHaarTreeNode* currentnodeptr =
|
||||
nodeptr + (nodecounter + tempnodecounter) * stump_factor + root_offset;
|
||||
__global GpuHidHaarTreeNode* currentnodeptr = (__global GpuHidHaarTreeNode*)
|
||||
(((__global uchar*)nodeptr) + sizeof(GpuHidHaarTreeNode) * ((nodecounter + tempnodecounter) * stump_factor + root_offset));
|
||||
|
||||
int4 info1 = *(__global int4*)(&(currentnodeptr->p[0][0]));
|
||||
int4 info2 = *(__global int4*)(&(currentnodeptr->p[1][0]));
|
||||
@ -549,7 +557,7 @@ __kernel void __attribute__((reqd_work_group_size(8,8,1)))gpuRunHaarClassifierCa
|
||||
|
||||
queuecount = lclcount[0];
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
nodecounter += stageinfo.x;
|
||||
nodecounter += stagecount;
|
||||
}//end for(int stageloop = splitstage; stageloop< endstage && queuecount>0;stageloop++)
|
||||
|
||||
if(lcl_id<queuecount)
|
||||
|
@ -59,13 +59,13 @@ typedef struct __attribute__((aligned(128))) GpuHidHaarTreeNode
|
||||
int right __attribute__((aligned(4)));
|
||||
}
|
||||
GpuHidHaarTreeNode;
|
||||
typedef struct __attribute__((aligned(32))) GpuHidHaarClassifier
|
||||
{
|
||||
int count __attribute__((aligned(4)));
|
||||
GpuHidHaarTreeNode *node __attribute__((aligned(8)));
|
||||
float *alpha __attribute__((aligned(8)));
|
||||
}
|
||||
GpuHidHaarClassifier;
|
||||
//typedef struct __attribute__((aligned(32))) GpuHidHaarClassifier
|
||||
//{
|
||||
// int count __attribute__((aligned(4)));
|
||||
// GpuHidHaarTreeNode *node __attribute__((aligned(8)));
|
||||
// float *alpha __attribute__((aligned(8)));
|
||||
//}
|
||||
//GpuHidHaarClassifier;
|
||||
typedef struct __attribute__((aligned(64))) GpuHidHaarStageClassifier
|
||||
{
|
||||
int count __attribute__((aligned(4)));
|
||||
@ -77,29 +77,29 @@ typedef struct __attribute__((aligned(64))) GpuHidHaarStageClassifier
|
||||
int reserved3 __attribute__((aligned(8)));
|
||||
}
|
||||
GpuHidHaarStageClassifier;
|
||||
typedef struct __attribute__((aligned(64))) GpuHidHaarClassifierCascade
|
||||
{
|
||||
int count __attribute__((aligned(4)));
|
||||
int is_stump_based __attribute__((aligned(4)));
|
||||
int has_tilted_features __attribute__((aligned(4)));
|
||||
int is_tree __attribute__((aligned(4)));
|
||||
int pq0 __attribute__((aligned(4)));
|
||||
int pq1 __attribute__((aligned(4)));
|
||||
int pq2 __attribute__((aligned(4)));
|
||||
int pq3 __attribute__((aligned(4)));
|
||||
int p0 __attribute__((aligned(4)));
|
||||
int p1 __attribute__((aligned(4)));
|
||||
int p2 __attribute__((aligned(4)));
|
||||
int p3 __attribute__((aligned(4)));
|
||||
float inv_window_area __attribute__((aligned(4)));
|
||||
} GpuHidHaarClassifierCascade;
|
||||
//typedef struct __attribute__((aligned(64))) GpuHidHaarClassifierCascade
|
||||
//{
|
||||
// int count __attribute__((aligned(4)));
|
||||
// int is_stump_based __attribute__((aligned(4)));
|
||||
// int has_tilted_features __attribute__((aligned(4)));
|
||||
// int is_tree __attribute__((aligned(4)));
|
||||
// int pq0 __attribute__((aligned(4)));
|
||||
// int pq1 __attribute__((aligned(4)));
|
||||
// int pq2 __attribute__((aligned(4)));
|
||||
// int pq3 __attribute__((aligned(4)));
|
||||
// int p0 __attribute__((aligned(4)));
|
||||
// int p1 __attribute__((aligned(4)));
|
||||
// int p2 __attribute__((aligned(4)));
|
||||
// int p3 __attribute__((aligned(4)));
|
||||
// float inv_window_area __attribute__((aligned(4)));
|
||||
//} GpuHidHaarClassifierCascade;
|
||||
|
||||
__kernel void gpuRunHaarClassifierCascade_scaled2(
|
||||
global GpuHidHaarStageClassifier *stagecascadeptr,
|
||||
global GpuHidHaarStageClassifier *stagecascadeptr_,
|
||||
global int4 *info,
|
||||
global GpuHidHaarTreeNode *nodeptr,
|
||||
global GpuHidHaarTreeNode *nodeptr_,
|
||||
global const int *restrict sum,
|
||||
global const float *restrict sqsum,
|
||||
global const float *restrict sqsum,
|
||||
global int4 *candidate,
|
||||
const int rows,
|
||||
const int cols,
|
||||
@ -132,8 +132,7 @@ __kernel void gpuRunHaarClassifierCascade_scaled2(
|
||||
int max_idx = rows * cols - 1;
|
||||
for (int scalei = 0; scalei < loopcount; scalei++)
|
||||
{
|
||||
int4 scaleinfo1;
|
||||
scaleinfo1 = info[scalei];
|
||||
int4 scaleinfo1 = info[scalei];
|
||||
int grpnumperline = (scaleinfo1.y & 0xffff0000) >> 16;
|
||||
int totalgrp = scaleinfo1.y & 0xffff;
|
||||
float factor = as_float(scaleinfo1.w);
|
||||
@ -174,15 +173,18 @@ __kernel void gpuRunHaarClassifierCascade_scaled2(
|
||||
for (int stageloop = start_stage; (stageloop < end_stage) && result; stageloop++)
|
||||
{
|
||||
float stage_sum = 0.f;
|
||||
int stagecount = stagecascadeptr[stageloop].count;
|
||||
__global GpuHidHaarStageClassifier* stageinfo = (__global GpuHidHaarStageClassifier*)
|
||||
(((__global uchar*)stagecascadeptr_)+stageloop*sizeof(GpuHidHaarStageClassifier));
|
||||
int stagecount = stageinfo->count;
|
||||
for (int nodeloop = 0; nodeloop < stagecount;)
|
||||
{
|
||||
__global GpuHidHaarTreeNode *currentnodeptr = (nodeptr + nodecounter);
|
||||
__global GpuHidHaarTreeNode* currentnodeptr = (__global GpuHidHaarTreeNode*)
|
||||
(((__global uchar*)nodeptr_) + nodecounter * sizeof(GpuHidHaarTreeNode));
|
||||
int4 info1 = *(__global int4 *)(&(currentnodeptr->p[0][0]));
|
||||
int4 info2 = *(__global int4 *)(&(currentnodeptr->p[1][0]));
|
||||
int4 info3 = *(__global int4 *)(&(currentnodeptr->p[2][0]));
|
||||
float4 w = *(__global float4 *)(&(currentnodeptr->weight[0]));
|
||||
float3 alpha3 = *(__global float3 *)(&(currentnodeptr->alpha[0]));
|
||||
float3 alpha3 = *(__global float3*)(&(currentnodeptr->alpha[0]));
|
||||
float nodethreshold = w.w * variance_norm_factor;
|
||||
|
||||
info1.x += p_offset;
|
||||
@ -204,7 +206,7 @@ __kernel void gpuRunHaarClassifierCascade_scaled2(
|
||||
sum[clamp(mad24(info3.w, step, info3.x), 0, max_idx)]
|
||||
+ sum[clamp(mad24(info3.w, step, info3.z), 0, max_idx)]) * w.z;
|
||||
|
||||
bool passThres = classsum >= nodethreshold;
|
||||
bool passThres = (classsum >= nodethreshold) ? 1 : 0;
|
||||
|
||||
#if STUMP_BASED
|
||||
stage_sum += passThres ? alpha3.y : alpha3.x;
|
||||
@ -234,7 +236,8 @@ __kernel void gpuRunHaarClassifierCascade_scaled2(
|
||||
}
|
||||
#endif
|
||||
}
|
||||
result = (int)(stage_sum >= stagecascadeptr[stageloop].threshold);
|
||||
|
||||
result = (stage_sum >= stageinfo->threshold) ? 1 : 0;
|
||||
}
|
||||
|
||||
barrier(CLK_LOCAL_MEM_FENCE);
|
||||
@ -281,11 +284,14 @@ __kernel void gpuRunHaarClassifierCascade_scaled2(
|
||||
}
|
||||
}
|
||||
}
|
||||
__kernel void gpuscaleclassifier(global GpuHidHaarTreeNode *orinode, global GpuHidHaarTreeNode *newnode, float scale, float weight_scale, int nodenum)
|
||||
__kernel void gpuscaleclassifier(global GpuHidHaarTreeNode *orinode, global GpuHidHaarTreeNode *newnode, float scale, float weight_scale, const int nodenum)
|
||||
{
|
||||
int counter = get_global_id(0);
|
||||
const int counter = get_global_id(0);
|
||||
int tr_x[3], tr_y[3], tr_h[3], tr_w[3], i = 0;
|
||||
GpuHidHaarTreeNode t1 = *(orinode + counter);
|
||||
GpuHidHaarTreeNode t1 = *(__global GpuHidHaarTreeNode*)
|
||||
(((__global uchar*)orinode) + counter * sizeof(GpuHidHaarTreeNode));
|
||||
__global GpuHidHaarTreeNode* pNew = (__global GpuHidHaarTreeNode*)
|
||||
(((__global uchar*)newnode) + (counter + nodenum) * sizeof(GpuHidHaarTreeNode));
|
||||
|
||||
#pragma unroll
|
||||
for (i = 0; i < 3; i++)
|
||||
@ -297,22 +303,21 @@ __kernel void gpuscaleclassifier(global GpuHidHaarTreeNode *orinode, global GpuH
|
||||
}
|
||||
|
||||
t1.weight[0] = -(t1.weight[1] * tr_h[1] * tr_w[1] + t1.weight[2] * tr_h[2] * tr_w[2]) / (tr_h[0] * tr_w[0]);
|
||||
counter += nodenum;
|
||||
|
||||
#pragma unroll
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
newnode[counter].p[i][0] = tr_x[i];
|
||||
newnode[counter].p[i][1] = tr_y[i];
|
||||
newnode[counter].p[i][2] = tr_x[i] + tr_w[i];
|
||||
newnode[counter].p[i][3] = tr_y[i] + tr_h[i];
|
||||
newnode[counter].weight[i] = t1.weight[i] * weight_scale;
|
||||
pNew->p[i][0] = tr_x[i];
|
||||
pNew->p[i][1] = tr_y[i];
|
||||
pNew->p[i][2] = tr_x[i] + tr_w[i];
|
||||
pNew->p[i][3] = tr_y[i] + tr_h[i];
|
||||
pNew->weight[i] = t1.weight[i] * weight_scale;
|
||||
}
|
||||
|
||||
newnode[counter].left = t1.left;
|
||||
newnode[counter].right = t1.right;
|
||||
newnode[counter].threshold = t1.threshold;
|
||||
newnode[counter].alpha[0] = t1.alpha[0];
|
||||
newnode[counter].alpha[1] = t1.alpha[1];
|
||||
newnode[counter].alpha[2] = t1.alpha[2];
|
||||
pNew->left = t1.left;
|
||||
pNew->right = t1.right;
|
||||
pNew->threshold = t1.threshold;
|
||||
pNew->alpha[0] = t1.alpha[0];
|
||||
pNew->alpha[1] = t1.alpha[1];
|
||||
pNew->alpha[2] = t1.alpha[2];
|
||||
}
|
||||
|
@ -74,11 +74,11 @@ __kernel void threshold(__global const T * restrict src, int src_offset, int src
|
||||
VT vthresh = (VT)(thresh);
|
||||
|
||||
#ifdef THRESH_BINARY
|
||||
VT vecValue = sdata > vthresh ? max_val : (VT)(0);
|
||||
VT vecValue = sdata > vthresh ? (VT)max_val : (VT)(0);
|
||||
#elif defined THRESH_BINARY_INV
|
||||
VT vecValue = sdata > vthresh ? (VT)(0) : max_val;
|
||||
VT vecValue = sdata > vthresh ? (VT)(0) : (VT)max_val;
|
||||
#elif defined THRESH_TRUNC
|
||||
VT vecValue = sdata > vthresh ? thresh : sdata;
|
||||
VT vecValue = sdata > vthresh ? (VT)thresh : sdata;
|
||||
#elif defined THRESH_TOZERO
|
||||
VT vecValue = sdata > vthresh ? sdata : (VT)(0);
|
||||
#elif defined THRESH_TOZERO_INV
|
||||
|
99
modules/photo/doc/cloning.rst
Normal file
99
modules/photo/doc/cloning.rst
Normal file
@ -0,0 +1,99 @@
|
||||
Seamless Cloning
|
||||
================
|
||||
|
||||
.. highlight:: cpp
|
||||
|
||||
seamlessClone
|
||||
-------------
|
||||
Image editing tasks concern either global changes (color/intensity corrections, filters, deformations) or local changes concerned to a selection.
|
||||
Here we are interested in achieving local changes, ones that are restricted to a region manually selected (ROI), in a seamless and effortless manner.
|
||||
The extent of the changes ranges from slight distortions to complete replacement by novel content.
|
||||
|
||||
.. ocv:function:: void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p, OutputArray blend, int flags)
|
||||
|
||||
:param src: Input 8-bit 3-channel image.
|
||||
|
||||
:param dst: Input 8-bit 3-channel image.
|
||||
|
||||
:param mask: Input 8-bit 1 or 3-channel image.
|
||||
|
||||
:param p: Point in dst image where object is placed.
|
||||
|
||||
:param result: Output image with the same size and type as ``dst``.
|
||||
|
||||
:param flags: Cloning method that could be one of the following:
|
||||
|
||||
* **NORMAL_CLONE** The power of the method is fully expressed when inserting objects with complex outlines into a new background
|
||||
|
||||
* **MIXED_CLONE** The classic method, color-based selection and alpha
|
||||
masking might be time consuming and often leaves an undesirable halo. Seamless
|
||||
cloning, even averaged with the original image, is not effective. Mixed seamless
|
||||
cloning based on a loose selection proves effective.
|
||||
|
||||
* **FEATURE_EXCHANGE** Feature exchange allows the user to replace easily certain
|
||||
features of one object by alternative features.
|
||||
|
||||
|
||||
|
||||
colorChange
|
||||
-----------
|
||||
Given an original color image, two differently colored versions of this image can be mixed seamlessly.
|
||||
|
||||
.. ocv:function:: void colorChange( InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0f, float green_mul = 1.0f, float blue_mul = 1.0f)
|
||||
|
||||
:param src: Input 8-bit 3-channel image.
|
||||
|
||||
:param mask: Input 8-bit 1 or 3-channel image.
|
||||
|
||||
:param dst: Output image with the same size and type as ``src`` .
|
||||
|
||||
:param red_mul: R-channel multiply factor.
|
||||
|
||||
:param green_mul: G-channel multiply factor.
|
||||
|
||||
:param blue_mul: B-channel multiply factor.
|
||||
|
||||
Multiplication factor is between .5 to 2.5.
|
||||
|
||||
|
||||
illuminationChange
|
||||
------------------
|
||||
Applying an appropriate non-linear transformation to the gradient field inside the selection and then integrating back with a Poisson
|
||||
solver, modifies locally the apparent illumination of an image.
|
||||
|
||||
.. ocv:function:: void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2f, float beta = 0.4f)
|
||||
|
||||
:param src: Input 8-bit 3-channel image.
|
||||
|
||||
:param mask: Input 8-bit 1 or 3-channel image.
|
||||
|
||||
:param dst: Output image with the same size and type as ``src``.
|
||||
|
||||
:param alpha: Value ranges between 0-2.
|
||||
|
||||
:param beta: Value ranges between 0-2.
|
||||
|
||||
This is useful to highlight under-exposed foreground objects or to reduce specular reflections.
|
||||
|
||||
textureFlattening
|
||||
-----------------
|
||||
By retaining only the gradients at edge locations, before integrating with the Poisson solver, one washes out the texture of the selected
|
||||
region, giving its contents a flat aspect. Here Canny Edge Detector is used.
|
||||
|
||||
.. ocv:function:: void textureFlattening(InputArray src, InputArray mask, OutputArray dst, double low_threshold=30 , double high_threshold=45, int kernel_size=3)
|
||||
|
||||
:param src: Input 8-bit 3-channel image.
|
||||
|
||||
:param mask: Input 8-bit 1 or 3-channel image.
|
||||
|
||||
:param dst: Output image with the same size and type as ``src``.
|
||||
|
||||
:param low_threshold: Range from 0 to 100.
|
||||
|
||||
:param high_threshold: Value > 100.
|
||||
|
||||
:param kernel_size: The size of the Sobel kernel to be used.
|
||||
|
||||
**NOTE:**
|
||||
|
||||
The algorithm assumes that the color of the source image is close to that of the destination. This assumption means that when the colors don't match, the source image color gets tinted toward the color of the destination image.
|
19
modules/photo/doc/decolor.rst
Normal file
19
modules/photo/doc/decolor.rst
Normal file
@ -0,0 +1,19 @@
|
||||
Decolorization
|
||||
==============
|
||||
|
||||
.. highlight:: cpp
|
||||
|
||||
decolor
|
||||
-------
|
||||
|
||||
Transforms a color image to a grayscale image. It is a basic tool in digital printing, stylized black-and-white photograph rendering, and in many single channel image processing applications.
|
||||
|
||||
.. ocv:function:: void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost )
|
||||
|
||||
:param src: Input 8-bit 3-channel image.
|
||||
|
||||
:param grayscale: Output 8-bit 1-channel image.
|
||||
|
||||
:param color_boost: Output 8-bit 3-channel image.
|
||||
|
||||
This function is to be applied on color images.
|
74
modules/photo/doc/npr.rst
Normal file
74
modules/photo/doc/npr.rst
Normal file
@ -0,0 +1,74 @@
|
||||
Non-Photorealistic Rendering
|
||||
============================
|
||||
|
||||
.. highlight:: cpp
|
||||
|
||||
edgePreservingFilter
|
||||
--------------------
|
||||
|
||||
Filtering is the fundamental operation in image and video processing. Edge-preserving smoothing filters are used in many different applications.
|
||||
|
||||
.. ocv:function:: void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4f)
|
||||
|
||||
:param src: Input 8-bit 3-channel image.
|
||||
|
||||
:param dst: Output 8-bit 3-channel image.
|
||||
|
||||
:param flags: Edge preserving filters:
|
||||
|
||||
* **RECURS_FILTER**
|
||||
|
||||
* **NORMCONV_FILTER**
|
||||
|
||||
:param sigma_s: Range between 0 to 200.
|
||||
|
||||
:param sigma_r: Range between 0 to 1.
|
||||
|
||||
|
||||
detailEnhance
|
||||
-------------
|
||||
This filter enhances the details of a particular image.
|
||||
|
||||
.. ocv:function:: void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, float sigma_r = 0.15f)
|
||||
|
||||
:param src: Input 8-bit 3-channel image.
|
||||
|
||||
:param dst: Output image with the same size and type as ``src``.
|
||||
|
||||
:param sigma_s: Range between 0 to 200.
|
||||
|
||||
:param sigma_r: Range between 0 to 1.
|
||||
|
||||
|
||||
pencilSketch
|
||||
------------
|
||||
Pencil-like non-photorealistic line drawing
|
||||
|
||||
.. ocv:function:: void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, float sigma_s = 60, float sigma_r = 0.07f, float shade_factor = 0.02f)
|
||||
|
||||
:param src: Input 8-bit 3-channel image.
|
||||
|
||||
:param dst1: Output 8-bit 1-channel image.
|
||||
|
||||
:param dst2: Output image with the same size and type as ``src``.
|
||||
|
||||
:param sigma_s: Range between 0 to 200.
|
||||
|
||||
:param sigma_r: Range between 0 to 1.
|
||||
|
||||
:param shade_factor: Range between 0 to 0.1.
|
||||
|
||||
|
||||
stylization
|
||||
-----------
|
||||
Stylization aims to produce digital imagery with a wide variety of effects not focused on photorealism. Edge-aware filters are ideal for stylization, as they can abstract regions of low contrast while preserving, or enhancing, high-contrast features.
|
||||
|
||||
.. ocv:function:: void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45f)
|
||||
|
||||
:param src: Input 8-bit 3-channel image.
|
||||
|
||||
:param dst: Output image with the same size and type as ``src``.
|
||||
|
||||
:param sigma_s: Range between 0 to 200.
|
||||
|
||||
:param sigma_r: Range between 0 to 1.
|
@ -9,4 +9,7 @@ photo. Computational Photography
|
||||
|
||||
inpainting
|
||||
denoising
|
||||
hdr_imaging
|
||||
hdr_imaging
|
||||
decolor
|
||||
cloning
|
||||
npr
|
||||
|
@ -47,7 +47,7 @@
|
||||
#include "opencv2/imgproc.hpp"
|
||||
|
||||
/*! \namespace cv
|
||||
Namespace where all the C++ OpenCV functionality resides
|
||||
Namespace where all the C++ OpenCV functionality resides
|
||||
*/
|
||||
namespace cv
|
||||
{
|
||||
@ -59,26 +59,39 @@ enum
|
||||
INPAINT_TELEA = 1 // A. Telea algorithm
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
NORMAL_CLONE = 1,
|
||||
MIXED_CLONE = 2,
|
||||
MONOCHROME_TRANSFER = 3
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
RECURS_FILTER = 1,
|
||||
NORMCONV_FILTER = 2
|
||||
};
|
||||
|
||||
//! restores the damaged image areas using one of the available intpainting algorithms
|
||||
CV_EXPORTS_W void inpaint( InputArray src, InputArray inpaintMask,
|
||||
OutputArray dst, double inpaintRadius, int flags );
|
||||
OutputArray dst, double inpaintRadius, int flags );
|
||||
|
||||
|
||||
CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3,
|
||||
int templateWindowSize = 7, int searchWindowSize = 21);
|
||||
int templateWindowSize = 7, int searchWindowSize = 21);
|
||||
|
||||
CV_EXPORTS_W void fastNlMeansDenoisingColored( InputArray src, OutputArray dst,
|
||||
float h = 3, float hColor = 3,
|
||||
int templateWindowSize = 7, int searchWindowSize = 21);
|
||||
float h = 3, float hColor = 3,
|
||||
int templateWindowSize = 7, int searchWindowSize = 21);
|
||||
|
||||
CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputArray dst,
|
||||
int imgToDenoiseIndex, int temporalWindowSize,
|
||||
float h = 3, int templateWindowSize = 7, int searchWindowSize = 21);
|
||||
int imgToDenoiseIndex, int temporalWindowSize,
|
||||
float h = 3, int templateWindowSize = 7, int searchWindowSize = 21);
|
||||
|
||||
CV_EXPORTS_W void fastNlMeansDenoisingColoredMulti( InputArrayOfArrays srcImgs, OutputArray dst,
|
||||
int imgToDenoiseIndex, int temporalWindowSize,
|
||||
float h = 3, float hColor = 3,
|
||||
int templateWindowSize = 7, int searchWindowSize = 21);
|
||||
int imgToDenoiseIndex, int temporalWindowSize,
|
||||
float h = 3, float hColor = 3,
|
||||
int templateWindowSize = 7, int searchWindowSize = 21);
|
||||
|
||||
enum { LDR_SIZE = 256 };
|
||||
|
||||
@ -288,6 +301,33 @@ public:
|
||||
|
||||
CV_EXPORTS_W Ptr<MergeRobertson> createMergeRobertson();
|
||||
|
||||
CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost);
|
||||
|
||||
CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p,
|
||||
OutputArray blend, int flags);
|
||||
|
||||
CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0f,
|
||||
float green_mul = 1.0f, float blue_mul = 1.0f);
|
||||
|
||||
CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst,
|
||||
float alpha = 0.2f, float beta = 0.4f);
|
||||
|
||||
CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst,
|
||||
double low_threshold = 30, double high_threshold = 45,
|
||||
int kernel_size = 3);
|
||||
|
||||
CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1,
|
||||
float sigma_s = 60, float sigma_r = 0.4f);
|
||||
|
||||
CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10,
|
||||
float sigma_r = 0.15f);
|
||||
|
||||
CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2,
|
||||
float sigma_s = 60, float sigma_r = 0.07f, float shade_factor = 0.02f);
|
||||
|
||||
CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60,
|
||||
float sigma_r = 0.45f);
|
||||
|
||||
} // cv
|
||||
|
||||
#endif
|
||||
|
210
modules/photo/src/contrast_preserve.cpp
Normal file
210
modules/photo/src/contrast_preserve.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
/*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) 2013, OpenCV Foundation, 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"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include "math.h"
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <iostream>
|
||||
#include "contrast_preserve.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _color_boost)
|
||||
{
|
||||
Mat I = _src.getMat();
|
||||
_dst.create(I.size(), CV_8UC1);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
_color_boost.create(I.size(), CV_8UC3);
|
||||
Mat color_boost = _color_boost.getMat();
|
||||
|
||||
if(!I.data )
|
||||
{
|
||||
cout << "Could not open or find the image" << endl ;
|
||||
return;
|
||||
}
|
||||
if(I.channels() !=3)
|
||||
{
|
||||
cout << "Input Color Image" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Parameter Setting
|
||||
int maxIter = 15;
|
||||
int iterCount = 0;
|
||||
double tol = .0001;
|
||||
double E = 0;
|
||||
double pre_E = std::numeric_limits<double>::infinity();
|
||||
|
||||
Decolor obj;
|
||||
|
||||
Mat img;
|
||||
|
||||
img = Mat(I.size(),CV_32FC3);
|
||||
I.convertTo(img,CV_32FC3,1.0/255.0);
|
||||
|
||||
// Initialization
|
||||
obj.init();
|
||||
|
||||
vector <double> Cg;
|
||||
vector < vector <double> > polyGrad;
|
||||
vector < vector < int > > comb;
|
||||
|
||||
vector <double> alf;
|
||||
|
||||
obj.grad_system(img,polyGrad,Cg,comb);
|
||||
obj.weak_order(img,alf);
|
||||
|
||||
// Solver
|
||||
Mat Mt = Mat((int)polyGrad.size(),(int)polyGrad[0].size(), CV_32FC1);
|
||||
obj.wei_update_matrix(polyGrad,Cg,Mt);
|
||||
|
||||
vector <double> wei;
|
||||
obj.wei_inti(comb,wei);
|
||||
|
||||
//////////////////////////////// main loop starting ////////////////////////////////////////
|
||||
|
||||
while(sqrt(pow(E-pre_E,2)) > tol)
|
||||
{
|
||||
iterCount +=1;
|
||||
pre_E = E;
|
||||
|
||||
vector <double> G_pos;
|
||||
vector <double> G_neg;
|
||||
|
||||
vector <double> temp;
|
||||
vector <double> temp1;
|
||||
|
||||
double val = 0.0;
|
||||
for(unsigned int i=0;i< polyGrad[0].size();i++)
|
||||
{
|
||||
val = 0.0;
|
||||
for(unsigned int j =0;j<polyGrad.size();j++)
|
||||
val = val + (polyGrad[j][i] * wei[j]);
|
||||
temp.push_back(val - Cg[i]);
|
||||
temp1.push_back(val + Cg[i]);
|
||||
}
|
||||
|
||||
double pos = 0.0;
|
||||
double neg = 0.0;
|
||||
for(unsigned int i =0;i<alf.size();i++)
|
||||
{
|
||||
pos = ((1 + alf[i])/2) * exp((-1.0 * 0.5 * pow(temp[i],2))/pow(obj.sigma,2));
|
||||
neg = ((1 - alf[i])/2) * exp((-1.0 * 0.5 * pow(temp1[i],2))/pow(obj.sigma,2));
|
||||
G_pos.push_back(pos);
|
||||
G_neg.push_back(neg);
|
||||
}
|
||||
|
||||
vector <double> EXPsum;
|
||||
vector <double> EXPterm;
|
||||
|
||||
for(unsigned int i = 0;i<G_pos.size();i++)
|
||||
EXPsum.push_back(G_pos[i]+G_neg[i]);
|
||||
|
||||
vector <double> temp2;
|
||||
|
||||
for(unsigned int i=0;i<EXPsum.size();i++)
|
||||
{
|
||||
if(EXPsum[i] == 0)
|
||||
temp2.push_back(1.0);
|
||||
else
|
||||
temp2.push_back(0.0);
|
||||
}
|
||||
|
||||
for(unsigned int i =0; i < G_pos.size();i++)
|
||||
EXPterm.push_back((G_pos[i] - G_neg[i])/(EXPsum[i] + temp2[i]));
|
||||
|
||||
double val1 = 0.0;
|
||||
vector <double> wei1;
|
||||
|
||||
for(unsigned int i=0;i< polyGrad.size();i++)
|
||||
{
|
||||
val1 = 0.0;
|
||||
for(unsigned int j =0;j<polyGrad[0].size();j++)
|
||||
{
|
||||
val1 = val1 + (Mt.at<float>(i,j) * EXPterm[j]);
|
||||
}
|
||||
wei1.push_back(val1);
|
||||
}
|
||||
|
||||
for(unsigned int i =0;i<wei.size();i++)
|
||||
wei[i] = wei1[i];
|
||||
|
||||
E = obj.energyCalcu(Cg,polyGrad,wei);
|
||||
|
||||
if(iterCount > maxIter)
|
||||
break;
|
||||
|
||||
G_pos.clear();
|
||||
G_neg.clear();
|
||||
temp.clear();
|
||||
temp1.clear();
|
||||
EXPsum.clear();
|
||||
EXPterm.clear();
|
||||
temp2.clear();
|
||||
wei1.clear();
|
||||
}
|
||||
|
||||
Mat Gray = Mat::zeros(img.size(),CV_32FC1);
|
||||
obj.grayImContruct(wei, img, Gray);
|
||||
|
||||
Gray.convertTo(dst,CV_8UC1,255);
|
||||
|
||||
/////////////////////////////////// Contrast Boosting /////////////////////////////////
|
||||
|
||||
Mat lab = Mat(img.size(),CV_8UC3);
|
||||
Mat color = Mat(img.size(),CV_8UC3);
|
||||
|
||||
cvtColor(I,lab,COLOR_BGR2Lab);
|
||||
|
||||
vector <Mat> lab_channel;
|
||||
split(lab,lab_channel);
|
||||
|
||||
dst.copyTo(lab_channel[0]);
|
||||
|
||||
merge(lab_channel,lab);
|
||||
|
||||
cvtColor(lab,color_boost,COLOR_Lab2BGR);
|
||||
}
|
433
modules/photo/src/contrast_preserve.hpp
Normal file
433
modules/photo/src/contrast_preserve.hpp
Normal file
@ -0,0 +1,433 @@
|
||||
/*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) 2013, OpenCV Foundation, 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"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include "math.h"
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
class Decolor
|
||||
{
|
||||
private:
|
||||
Mat kernelx;
|
||||
Mat kernely;
|
||||
int order;
|
||||
|
||||
public:
|
||||
float sigma;
|
||||
void init();
|
||||
vector<double> product(vector < vector<int> > &comb, vector <double> &initRGB);
|
||||
double energyCalcu(vector <double> &Cg, vector < vector <double> > &polyGrad, vector <double> &wei);
|
||||
void singleChannelGradx(const Mat &img, Mat& dest);
|
||||
void singleChannelGrady(const Mat &img, Mat& dest);
|
||||
void gradvector(const Mat &img, vector <double> &grad);
|
||||
void colorGrad(Mat img, vector <double> &Cg);
|
||||
void add_vector(vector < vector <int> > &comb, int r,int g,int b);
|
||||
void add_to_vector_poly(vector < vector <double> > &polyGrad, vector <double> &curGrad);
|
||||
void weak_order(Mat img, vector <double> &alf);
|
||||
void grad_system(Mat img, vector < vector < double > > &polyGrad,
|
||||
vector < double > &Cg, vector < vector <int> >& comb);
|
||||
void wei_update_matrix(vector < vector <double> > &poly, vector <double> &Cg, Mat &X);
|
||||
void wei_inti(vector < vector <int> > &comb, vector <double> &wei);
|
||||
void grayImContruct(vector <double> &wei, Mat img, Mat &Gray);
|
||||
};
|
||||
|
||||
int round_num(double a);
|
||||
|
||||
int round_num(double a)
|
||||
{
|
||||
return int(a + 0.5);
|
||||
}
|
||||
|
||||
double Decolor::energyCalcu(vector <double> &Cg, vector < vector <double> > &polyGrad, vector <double> &wei)
|
||||
{
|
||||
vector <double> energy;
|
||||
vector <double> temp;
|
||||
vector <double> temp1;
|
||||
|
||||
double val = 0.0;
|
||||
for(unsigned int i=0;i< polyGrad[0].size();i++)
|
||||
{
|
||||
val = 0.0;
|
||||
for(unsigned int j =0;j<polyGrad.size();j++)
|
||||
val = val + (polyGrad[j][i] * wei[j]);
|
||||
temp.push_back(val - Cg[i]);
|
||||
temp1.push_back(val + Cg[i]);
|
||||
}
|
||||
|
||||
for(unsigned int i=0;i<polyGrad[0].size();i++)
|
||||
energy.push_back(-1.0*log(exp(-1.0*pow(temp[i],2)/sigma) + exp(-1.0*pow(temp1[i],2)/sigma)));
|
||||
|
||||
double sum = 0.0;
|
||||
for(unsigned int i=0;i<polyGrad[0].size();i++)
|
||||
sum +=energy[i];
|
||||
|
||||
return (sum/polyGrad[0].size());
|
||||
|
||||
}
|
||||
|
||||
void Decolor::init()
|
||||
{
|
||||
kernelx = Mat(1,2, CV_32FC1);
|
||||
kernely = Mat(2,1, CV_32FC1);
|
||||
kernelx.at<float>(0,0)=1.0;
|
||||
kernelx.at<float>(0,1)=-1.0;
|
||||
kernely.at<float>(0,0)=1.0;
|
||||
kernely.at<float>(1,0)=-1.0;
|
||||
order = 2;
|
||||
sigma = 0.02f;
|
||||
}
|
||||
|
||||
vector<double> Decolor::product(vector < vector<int> > &comb, vector <double> &initRGB)
|
||||
{
|
||||
vector <double> res;
|
||||
double dp;
|
||||
for (unsigned int i=0;i<comb.size();i++)
|
||||
{
|
||||
dp = 0.0;
|
||||
for(int j=0;j<3;j++)
|
||||
dp = dp + (comb[i][j] * initRGB[j]);
|
||||
res.push_back(dp);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void Decolor::singleChannelGradx(const Mat &img, Mat& dest)
|
||||
{
|
||||
int w=img.size().width;
|
||||
int h=img.size().height;
|
||||
Point anchor(kernelx.cols - kernelx.cols/2 - 1, kernelx.rows - kernelx.rows/2 - 1);
|
||||
filter2D(img, dest, -1, kernelx, anchor, 0.0, BORDER_CONSTANT);
|
||||
for(int i=0;i<h;i++)
|
||||
dest.at<float>(i,w-1)=0.0;
|
||||
}
|
||||
|
||||
void Decolor::singleChannelGrady(const Mat &img, Mat& dest)
|
||||
{
|
||||
int w=img.size().width;
|
||||
int h=img.size().height;
|
||||
Point anchor(kernely.cols - kernely.cols/2 - 1, kernely.rows - kernely.rows/2 - 1);
|
||||
filter2D(img, dest, -1, kernely, anchor, 0.0, BORDER_CONSTANT);
|
||||
for(int j=0;j<w;j++)
|
||||
dest.at<float>(h-1,j)=0.0;
|
||||
}
|
||||
|
||||
void Decolor::gradvector(const Mat &img, vector <double> &grad)
|
||||
{
|
||||
Mat dest= Mat(img.size().height,img.size().width, CV_32FC1);
|
||||
Mat dest1= Mat(img.size().height,img.size().width, CV_32FC1);
|
||||
singleChannelGradx(img,dest);
|
||||
singleChannelGrady(img,dest1);
|
||||
|
||||
Mat d_trans=dest.t();
|
||||
Mat d1_trans=dest1.t();
|
||||
|
||||
int height = d_trans.size().height;
|
||||
int width = d_trans.size().width;
|
||||
|
||||
for(int i=0;i<height;i++)
|
||||
for(int j=0;j<width;j++)
|
||||
grad.push_back(d_trans.at<float>(i,j));
|
||||
|
||||
for(int i=0;i<height;i++)
|
||||
for(int j=0;j<width;j++)
|
||||
grad.push_back(d1_trans.at<float>(i,j));
|
||||
dest.release();
|
||||
dest1.release();
|
||||
}
|
||||
|
||||
void Decolor::colorGrad(Mat img, vector <double> &Cg)
|
||||
{
|
||||
|
||||
Mat lab = Mat(img.size(),CV_32FC3);
|
||||
|
||||
cvtColor(img,lab,COLOR_BGR2Lab);
|
||||
|
||||
vector <Mat> lab_channel;
|
||||
split(lab,lab_channel);
|
||||
|
||||
vector <double> ImL;
|
||||
vector <double> Ima;
|
||||
vector <double> Imb;
|
||||
|
||||
gradvector(lab_channel[0],ImL);
|
||||
gradvector(lab_channel[1],Ima);
|
||||
gradvector(lab_channel[2],Imb);
|
||||
|
||||
double res =0.0;
|
||||
for(unsigned int i=0;i<ImL.size();i++)
|
||||
{
|
||||
res=sqrt(pow(ImL[i],2) + pow(Ima[i],2) + pow(Imb[i],2))/100;
|
||||
Cg.push_back(res);
|
||||
}
|
||||
|
||||
ImL.clear();
|
||||
Ima.clear();
|
||||
Imb.clear();
|
||||
}
|
||||
|
||||
void Decolor::add_vector(vector < vector <int> > &comb, int r,int g,int b)
|
||||
{
|
||||
static int idx =0;
|
||||
comb.push_back( vector <int>() );
|
||||
comb.at(idx).push_back( r );
|
||||
comb.at(idx).push_back( g );
|
||||
comb.at(idx).push_back( b );
|
||||
idx++;
|
||||
}
|
||||
|
||||
void Decolor::add_to_vector_poly(vector < vector <double> > &polyGrad, vector <double> &curGrad)
|
||||
{
|
||||
static int idx1 =0;
|
||||
polyGrad.push_back( vector <double>() );
|
||||
for(unsigned int i=0;i<curGrad.size();i++)
|
||||
polyGrad.at(idx1).push_back(curGrad[i]);
|
||||
idx1++;
|
||||
}
|
||||
|
||||
void Decolor::weak_order(Mat img, vector <double> &alf)
|
||||
{
|
||||
int h = img.size().height;
|
||||
int w = img.size().width;
|
||||
double sizefactor;
|
||||
if((h + w) > 800)
|
||||
{
|
||||
sizefactor = (double)800/(h+w);
|
||||
resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor)));
|
||||
}
|
||||
|
||||
Mat curIm = Mat(img.size(),CV_32FC1);
|
||||
vector <Mat> rgb_channel;
|
||||
split(img,rgb_channel);
|
||||
|
||||
vector <double> Rg, Gg, Bg;
|
||||
vector <double> t1, t2, t3;
|
||||
vector <double> tmp1, tmp2, tmp3;
|
||||
|
||||
gradvector(rgb_channel[2],Rg);
|
||||
gradvector(rgb_channel[1],Gg);
|
||||
gradvector(rgb_channel[0],Bg);
|
||||
|
||||
double level = .05;
|
||||
|
||||
for(unsigned int i=0;i<Rg.size();i++)
|
||||
{
|
||||
if(Rg[i] > level)
|
||||
t1.push_back(1.0);
|
||||
else
|
||||
t1.push_back(0.0);
|
||||
|
||||
if(Gg[i] > level)
|
||||
t2.push_back(1.0);
|
||||
else
|
||||
t2.push_back(0.0);
|
||||
|
||||
if(Bg[i] > level)
|
||||
t3.push_back(1.0);
|
||||
else
|
||||
t3.push_back(0.0);
|
||||
|
||||
if(Rg[i] < -1.0*level)
|
||||
tmp1.push_back(1.0);
|
||||
else
|
||||
tmp1.push_back(0.0);
|
||||
|
||||
if(Gg[i] < -1.0*level)
|
||||
tmp2.push_back(1.0);
|
||||
else
|
||||
tmp2.push_back(0.0);
|
||||
|
||||
if(Bg[i] < -1.0*level)
|
||||
tmp3.push_back(1.0);
|
||||
else
|
||||
tmp3.push_back(0.0);
|
||||
}
|
||||
for(unsigned int i =0 ;i < Rg.size();i++)
|
||||
alf.push_back(t1[i] * t2[i] * t3[i]);
|
||||
|
||||
for(unsigned int i =0 ;i < Rg.size();i++)
|
||||
alf[i] -= tmp1[i] * tmp2[i] * tmp3[i];
|
||||
|
||||
double sum =0.0;
|
||||
for(unsigned int i=0;i<alf.size();i++)
|
||||
sum += abs(alf[i]);
|
||||
|
||||
sum = (double)100*sum/alf.size();
|
||||
|
||||
Rg.clear(); Gg.clear(); Bg.clear();
|
||||
t1.clear(); t2.clear(); t3.clear();
|
||||
tmp1.clear(); tmp2.clear(); tmp3.clear();
|
||||
}
|
||||
|
||||
void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad,
|
||||
vector < double > &Cg, vector < vector <int> >& comb)
|
||||
{
|
||||
int h = img.size().height;
|
||||
int w = img.size().width;
|
||||
|
||||
double sizefactor;
|
||||
if((h + w) > 800)
|
||||
{
|
||||
sizefactor = (double)800/(h+w);
|
||||
resize(img,img,Size(round_num(h*sizefactor),round_num(w*sizefactor)));
|
||||
}
|
||||
|
||||
h = img.size().height;
|
||||
w = img.size().width;
|
||||
colorGrad(img,Cg);
|
||||
|
||||
Mat curIm = Mat(img.size(),CV_32FC1);
|
||||
vector <Mat> rgb_channel;
|
||||
split(img,rgb_channel);
|
||||
|
||||
for(int r=0 ;r <=order; r++)
|
||||
for(int g=0; g<=order;g++)
|
||||
for(int b =0; b <=order;b++)
|
||||
{
|
||||
if((r+g+b)<=order && (r+g+b) > 0)
|
||||
{
|
||||
add_vector(comb,r,g,b);
|
||||
for(int i = 0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
curIm.at<float>(i,j)=
|
||||
pow(rgb_channel[2].at<float>(i,j),r)*pow(rgb_channel[1].at<float>(i,j),g)*
|
||||
pow(rgb_channel[0].at<float>(i,j),b);
|
||||
vector <double> curGrad;
|
||||
gradvector(curIm,curGrad);
|
||||
add_to_vector_poly(polyGrad,curGrad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Decolor::wei_update_matrix(vector < vector <double> > &poly, vector <double> &Cg, Mat &X)
|
||||
{
|
||||
int size = static_cast<int>(poly.size()), size0 = static_cast<int>(poly[0].size());
|
||||
Mat P = Mat(size, size0, CV_32FC1);
|
||||
Mat A = Mat(size, size, CV_32FC1);
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
for (int j = 0; j < size0;j++)
|
||||
P.at<float>(i,j) = (float) poly[i][j];
|
||||
|
||||
Mat P_trans = P.t();
|
||||
Mat B = Mat(size, size0, CV_32FC1);
|
||||
for(int i =0;i < size;i++)
|
||||
{
|
||||
for(int j = 0, end = (int)Cg.size(); j < end;j++)
|
||||
B.at<float>(i,j) = (float) (poly[i][j] * Cg[j]);
|
||||
}
|
||||
|
||||
A = P*P_trans;
|
||||
solve(A, B, X, DECOMP_NORMAL);
|
||||
|
||||
}
|
||||
|
||||
void Decolor::wei_inti(vector < vector <int> > &comb, vector <double> &wei)
|
||||
{
|
||||
vector <double> initRGB;
|
||||
|
||||
initRGB.push_back( .33 );
|
||||
initRGB.push_back( .33 );
|
||||
initRGB.push_back( .33 );
|
||||
wei = product(comb,initRGB);
|
||||
|
||||
vector <int> sum;
|
||||
|
||||
for(unsigned int i=0;i<comb.size();i++)
|
||||
sum.push_back(comb[i][0] + comb[i][1] + comb[i][2]);
|
||||
|
||||
for(unsigned int i=0;i<sum.size();i++)
|
||||
{
|
||||
if(sum[i] == 1)
|
||||
wei[i] = wei[i] * double(1);
|
||||
else
|
||||
wei[i] = wei[i] * double(0);
|
||||
}
|
||||
|
||||
initRGB.clear();
|
||||
sum.clear();
|
||||
|
||||
}
|
||||
|
||||
void Decolor::grayImContruct(vector <double> &wei, Mat img, Mat &Gray)
|
||||
{
|
||||
int h=img.size().height;
|
||||
int w=img.size().width;
|
||||
|
||||
vector <Mat> rgb_channel;
|
||||
split(img,rgb_channel);
|
||||
|
||||
int kk =0;
|
||||
|
||||
for(int r =0;r<=order;r++)
|
||||
for(int g=0;g<=order;g++)
|
||||
for(int b=0;b<=order;b++)
|
||||
if((r + g + b) <=order && (r+g+b) > 0)
|
||||
{
|
||||
for(int i = 0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
Gray.at<float>(i,j)=Gray.at<float>(i,j) +
|
||||
(float) wei[kk]*pow(rgb_channel[2].at<float>(i,j),r)*pow(rgb_channel[1].at<float>(i,j),g)*
|
||||
pow(rgb_channel[0].at<float>(i,j),b);
|
||||
|
||||
kk=kk+1;
|
||||
}
|
||||
|
||||
float minval = FLT_MAX;
|
||||
float maxval = -FLT_MAX;
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
for(int j =0;j<w;j++)
|
||||
{
|
||||
if(Gray.at<float>(i,j) < minval)
|
||||
minval = Gray.at<float>(i,j);
|
||||
|
||||
if(Gray.at<float>(i,j) > maxval)
|
||||
maxval = Gray.at<float>(i,j);
|
||||
}
|
||||
|
||||
Gray -= minval;
|
||||
Gray /= maxval - minval;
|
||||
}
|
173
modules/photo/src/npr.cpp
Normal file
173
modules/photo/src/npr.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
/*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) 2013, OpenCV Foundation, 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"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "npr.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void cv::edgePreservingFilter(InputArray _src, OutputArray _dst, int flags, float sigma_s, float sigma_r)
|
||||
{
|
||||
Mat I = _src.getMat();
|
||||
_dst.create(I.size(), CV_8UC3);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
int h = I.size().height;
|
||||
int w = I.size().width;
|
||||
|
||||
Mat res = Mat(h,w,CV_32FC3);
|
||||
dst.convertTo(res,CV_32FC3,1.0/255.0);
|
||||
|
||||
Domain_Filter obj;
|
||||
|
||||
Mat img = Mat(I.size(),CV_32FC3);
|
||||
I.convertTo(img,CV_32FC3,1.0/255.0);
|
||||
|
||||
obj.filter(img, res, sigma_s, sigma_r, flags);
|
||||
|
||||
convertScaleAbs(res, dst, 255,0);
|
||||
}
|
||||
|
||||
void cv::detailEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r)
|
||||
{
|
||||
Mat I = _src.getMat();
|
||||
_dst.create(I.size(), CV_8UC3);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
int h = I.size().height;
|
||||
int w = I.size().width;
|
||||
float factor = 3.0f;
|
||||
|
||||
Mat img = Mat(I.size(),CV_32FC3);
|
||||
I.convertTo(img,CV_32FC3,1.0/255.0);
|
||||
|
||||
Mat res = Mat(h,w,CV_32FC1);
|
||||
dst.convertTo(res,CV_32FC3,1.0/255.0);
|
||||
|
||||
Mat result = Mat(img.size(),CV_32FC3);
|
||||
Mat lab = Mat(img.size(),CV_32FC3);
|
||||
vector <Mat> lab_channel;
|
||||
|
||||
cvtColor(img,lab,COLOR_BGR2Lab);
|
||||
split(lab,lab_channel);
|
||||
|
||||
Mat L = Mat(img.size(),CV_32FC1);
|
||||
|
||||
lab_channel[0].convertTo(L,CV_32FC1,1.0/255.0);
|
||||
|
||||
Domain_Filter obj;
|
||||
|
||||
obj.filter(L, res, sigma_s, sigma_r, 1);
|
||||
|
||||
Mat detail = Mat(h,w,CV_32FC1);
|
||||
|
||||
detail = L - res;
|
||||
multiply(detail,factor,detail);
|
||||
L = res + detail;
|
||||
|
||||
L.convertTo(lab_channel[0],CV_32FC1,255);
|
||||
|
||||
merge(lab_channel,lab);
|
||||
|
||||
cvtColor(lab,result,COLOR_Lab2BGR);
|
||||
result.convertTo(dst,CV_8UC3,255);
|
||||
}
|
||||
|
||||
void cv::pencilSketch(InputArray _src, OutputArray _dst1, OutputArray _dst2, float sigma_s, float sigma_r, float shade_factor)
|
||||
{
|
||||
Mat I = _src.getMat();
|
||||
_dst1.create(I.size(), CV_8UC1);
|
||||
Mat dst1 = _dst1.getMat();
|
||||
|
||||
_dst2.create(I.size(), CV_8UC3);
|
||||
Mat dst2 = _dst2.getMat();
|
||||
|
||||
Mat img = Mat(I.size(),CV_32FC3);
|
||||
I.convertTo(img,CV_32FC3,1.0/255.0);
|
||||
|
||||
Domain_Filter obj;
|
||||
|
||||
Mat sketch = Mat(I.size(),CV_32FC1);
|
||||
Mat color_sketch = Mat(I.size(),CV_32FC3);
|
||||
|
||||
obj.pencil_sketch(img, sketch, color_sketch, sigma_s, sigma_r, shade_factor);
|
||||
|
||||
sketch.convertTo(dst1,CV_8UC1,255);
|
||||
color_sketch.convertTo(dst2,CV_8UC3,255);
|
||||
|
||||
}
|
||||
|
||||
void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r)
|
||||
{
|
||||
Mat I = _src.getMat();
|
||||
_dst.create(I.size(), CV_8UC3);
|
||||
Mat dst = _dst.getMat();
|
||||
|
||||
Mat img = Mat(I.size(),CV_32FC3);
|
||||
I.convertTo(img,CV_32FC3,1.0/255.0);
|
||||
|
||||
int h = img.size().height;
|
||||
int w = img.size().width;
|
||||
|
||||
Mat res = Mat(h,w,CV_32FC3);
|
||||
Mat magnitude = Mat(h,w,CV_32FC1);
|
||||
|
||||
Domain_Filter obj;
|
||||
obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER);
|
||||
|
||||
obj.find_magnitude(res,magnitude);
|
||||
|
||||
Mat stylized = Mat(h,w,CV_32FC3);
|
||||
|
||||
vector <Mat> temp;
|
||||
split(res,temp);
|
||||
multiply(temp[0],magnitude,temp[0]);
|
||||
multiply(temp[1],magnitude,temp[1]);
|
||||
multiply(temp[2],magnitude,temp[2]);
|
||||
merge(temp,stylized);
|
||||
|
||||
stylized.convertTo(dst,CV_8UC3,255);
|
||||
}
|
582
modules/photo/src/npr.hpp
Normal file
582
modules/photo/src/npr.hpp
Normal file
@ -0,0 +1,582 @@
|
||||
/*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) 2013, OpenCV Foundation, 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"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <limits>
|
||||
#include "math.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
double myinf = std::numeric_limits<double>::infinity();
|
||||
|
||||
class Domain_Filter
|
||||
{
|
||||
public:
|
||||
Mat ct_H, ct_V, horiz, vert, O, O_t, lower_idx, upper_idx;
|
||||
void init(const Mat &img, int flags, float sigma_s, float sigma_r);
|
||||
void getGradientx( const Mat &img, Mat &gx);
|
||||
void getGradienty( const Mat &img, Mat &gy);
|
||||
void diffx(const Mat &img, Mat &temp);
|
||||
void diffy(const Mat &img, Mat &temp);
|
||||
void find_magnitude(Mat &img, Mat &mag);
|
||||
void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius);
|
||||
void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h);
|
||||
void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius);
|
||||
void filter(const Mat &img, Mat &res, float sigma_s, float sigma_r, int flags);
|
||||
void pencil_sketch(const Mat &img, Mat &sketch, Mat &color_res, float sigma_s, float sigma_r, float shade_factor);
|
||||
void Depth_of_field(const Mat &img, Mat &img1, float sigma_s, float sigma_r);
|
||||
};
|
||||
|
||||
void Domain_Filter::diffx(const Mat &img, Mat &temp)
|
||||
{
|
||||
int channel = img.channels();
|
||||
|
||||
for(int i = 0; i < img.size().height; i++)
|
||||
for(int j = 0; j < img.size().width-1; j++)
|
||||
{
|
||||
for(int c =0; c < channel; c++)
|
||||
{
|
||||
temp.at<float>(i,j*channel+c) =
|
||||
img.at<float>(i,(j+1)*channel+c) - img.at<float>(i,j*channel+c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Domain_Filter::diffy(const Mat &img, Mat &temp)
|
||||
{
|
||||
int channel = img.channels();
|
||||
|
||||
for(int i = 0; i < img.size().height-1; i++)
|
||||
for(int j = 0; j < img.size().width; j++)
|
||||
{
|
||||
for(int c =0; c < channel; c++)
|
||||
{
|
||||
temp.at<float>(i,j*channel+c) =
|
||||
img.at<float>((i+1),j*channel+c) - img.at<float>(i,j*channel+c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Domain_Filter::getGradientx( const Mat &img, Mat &gx)
|
||||
{
|
||||
int w = img.cols;
|
||||
int h = img.rows;
|
||||
int channel = img.channels();
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
for(int c=0;c<channel;++c)
|
||||
{
|
||||
gx.at<float>(i,j*channel+c) =
|
||||
img.at<float>(i,(j+1)*channel+c) - img.at<float>(i,j*channel+c);
|
||||
}
|
||||
}
|
||||
|
||||
void Domain_Filter::getGradienty( const Mat &img, Mat &gy)
|
||||
{
|
||||
int w = img.cols;
|
||||
int h = img.rows;
|
||||
int channel = img.channels();
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
for(int c=0;c<channel;++c)
|
||||
{
|
||||
gy.at<float>(i,j*channel+c) =
|
||||
img.at<float>(i+1,j*channel+c) - img.at<float>(i,j*channel+c);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Domain_Filter::find_magnitude(Mat &img, Mat &mag)
|
||||
{
|
||||
int h = img.rows;
|
||||
int w = img.cols;
|
||||
|
||||
vector <Mat> planes;
|
||||
split(img, planes);
|
||||
|
||||
Mat magXR = Mat(h, w, CV_32FC1);
|
||||
Mat magYR = Mat(h, w, CV_32FC1);
|
||||
|
||||
Mat magXG = Mat(h, w, CV_32FC1);
|
||||
Mat magYG = Mat(h, w, CV_32FC1);
|
||||
|
||||
Mat magXB = Mat(h, w, CV_32FC1);
|
||||
Mat magYB = Mat(h, w, CV_32FC1);
|
||||
|
||||
Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3);
|
||||
Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3);
|
||||
|
||||
Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3);
|
||||
Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3);
|
||||
|
||||
Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3);
|
||||
Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3);
|
||||
|
||||
Mat mag1 = Mat(h,w,CV_32FC1);
|
||||
Mat mag2 = Mat(h,w,CV_32FC1);
|
||||
Mat mag3 = Mat(h,w,CV_32FC1);
|
||||
|
||||
magnitude(magXR,magYR,mag1);
|
||||
magnitude(magXG,magYG,mag2);
|
||||
magnitude(magXB,magYB,mag3);
|
||||
|
||||
mag = mag1 + mag2 + mag3;
|
||||
mag = 1.0f - mag;
|
||||
}
|
||||
|
||||
void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h)
|
||||
{
|
||||
int h = output.rows;
|
||||
int w = output.cols;
|
||||
|
||||
float a = (float) exp((-1.0 * sqrt(2.0)) / sigma_h);
|
||||
|
||||
Mat temp = Mat(h,w,CV_32FC3);
|
||||
|
||||
output.copyTo(temp);
|
||||
Mat V = Mat(h,w,CV_32FC1);
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
V.at<float>(i,j) = pow(a,hz.at<float>(i,j));
|
||||
|
||||
for(int i=0; i<h; i++)
|
||||
{
|
||||
for(int j =1; j < w; j++)
|
||||
{
|
||||
temp.at<float>(i,j) = temp.at<float>(i,j) + (temp.at<float>(i,j-1) - temp.at<float>(i,j)) * V.at<float>(i,j);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<h; i++)
|
||||
{
|
||||
for(int j =w-2; j >= 0; j--)
|
||||
{
|
||||
temp.at<float>(i,j) = temp.at<float>(i,j) + (temp.at<float>(i,j+1) - temp.at<float>(i,j)) * V.at<float>(i,j+1);
|
||||
}
|
||||
}
|
||||
|
||||
temp.copyTo(output);
|
||||
}
|
||||
|
||||
void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius)
|
||||
{
|
||||
int h = output.rows;
|
||||
int w = output.cols;
|
||||
Mat lower_pos = Mat(h,w,CV_32FC1);
|
||||
Mat upper_pos = Mat(h,w,CV_32FC1);
|
||||
|
||||
lower_pos = hz - radius;
|
||||
upper_pos = hz + radius;
|
||||
|
||||
lower_idx = Mat::zeros(h,w,CV_32FC1);
|
||||
upper_idx = Mat::zeros(h,w,CV_32FC1);
|
||||
|
||||
Mat domain_row = Mat::zeros(1,w+1,CV_32FC1);
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
{
|
||||
for(int j=0;j<w;j++)
|
||||
domain_row.at<float>(0,j) = hz.at<float>(i,j);
|
||||
domain_row.at<float>(0,w) = (float) myinf;
|
||||
|
||||
Mat lower_pos_row = Mat::zeros(1,w,CV_32FC1);
|
||||
Mat upper_pos_row = Mat::zeros(1,w,CV_32FC1);
|
||||
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
lower_pos_row.at<float>(0,j) = lower_pos.at<float>(i,j);
|
||||
upper_pos_row.at<float>(0,j) = upper_pos.at<float>(i,j);
|
||||
}
|
||||
|
||||
Mat temp_lower_idx = Mat::zeros(1,w,CV_32FC1);
|
||||
Mat temp_upper_idx = Mat::zeros(1,w,CV_32FC1);
|
||||
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
if(domain_row.at<float>(0,j) > lower_pos_row.at<float>(0,0))
|
||||
{
|
||||
temp_lower_idx.at<float>(0,0) = (float) j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
if(domain_row.at<float>(0,j) > upper_pos_row.at<float>(0,0))
|
||||
{
|
||||
temp_upper_idx.at<float>(0,0) = (float) j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int temp = 0;
|
||||
for(int j=1;j<w;j++)
|
||||
{
|
||||
int count=0;
|
||||
for(int k=(int) temp_lower_idx.at<float>(0,j-1);k<w+1;k++)
|
||||
{
|
||||
if(domain_row.at<float>(0,k) > lower_pos_row.at<float>(0,j))
|
||||
{
|
||||
temp = count;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
temp_lower_idx.at<float>(0,j) = temp_lower_idx.at<float>(0,j-1) + temp;
|
||||
|
||||
count = 0;
|
||||
for(int k=(int) temp_upper_idx.at<float>(0,j-1);k<w+1;k++)
|
||||
{
|
||||
|
||||
|
||||
if(domain_row.at<float>(0,k) > upper_pos_row.at<float>(0,j))
|
||||
{
|
||||
temp = count;
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
temp_upper_idx.at<float>(0,j) = temp_upper_idx.at<float>(0,j-1) + temp;
|
||||
}
|
||||
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
lower_idx.at<float>(i,j) = temp_lower_idx.at<float>(0,j) + 1;
|
||||
upper_idx.at<float>(i,j) = temp_upper_idx.at<float>(0,j) + 1;
|
||||
}
|
||||
|
||||
}
|
||||
psketch = upper_idx - lower_idx;
|
||||
}
|
||||
void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float radius)
|
||||
{
|
||||
int h = output.rows;
|
||||
int w = output.cols;
|
||||
int channel = output.channels();
|
||||
|
||||
compute_boxfilter(output,hz,psketch,radius);
|
||||
|
||||
Mat box_filter = Mat::zeros(h,w+1,CV_32FC3);
|
||||
|
||||
for(int i = 0; i < h; i++)
|
||||
{
|
||||
box_filter.at<float>(i,1*channel+0) = output.at<float>(i,0*channel+0);
|
||||
box_filter.at<float>(i,1*channel+1) = output.at<float>(i,0*channel+1);
|
||||
box_filter.at<float>(i,1*channel+2) = output.at<float>(i,0*channel+2);
|
||||
for(int j = 2; j < w+1; j++)
|
||||
{
|
||||
for(int c=0;c<channel;c++)
|
||||
box_filter.at<float>(i,j*channel+c) = output.at<float>(i,(j-1)*channel+c) + box_filter.at<float>(i,(j-1)*channel+c);
|
||||
}
|
||||
}
|
||||
|
||||
Mat indices = Mat::zeros(h,w,CV_32FC1);
|
||||
Mat final = Mat::zeros(h,w,CV_32FC3);
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
indices.at<float>(i,j) = (float) i+1;
|
||||
|
||||
Mat a = Mat::zeros(h,w,CV_32FC1);
|
||||
Mat b = Mat::zeros(h,w,CV_32FC1);
|
||||
|
||||
// Compute the box filter using a summed area table.
|
||||
for(int c=0;c<channel;c++)
|
||||
{
|
||||
Mat flag = Mat::ones(h,w,CV_32FC1);
|
||||
multiply(flag,c+1,flag);
|
||||
|
||||
Mat temp1, temp2;
|
||||
multiply(flag - 1,h*(w+1),temp1);
|
||||
multiply(lower_idx - 1,h,temp2);
|
||||
a = temp1 + temp2 + indices;
|
||||
|
||||
multiply(flag - 1,h*(w+1),temp1);
|
||||
multiply(upper_idx - 1,h,temp2);
|
||||
b = temp1 + temp2 + indices;
|
||||
|
||||
int p,q,r,rem;
|
||||
int p1,q1,r1,rem1;
|
||||
|
||||
// Calculating indices
|
||||
for(int i=0;i<h;i++)
|
||||
{
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
|
||||
r = (int) b.at<float>(i,j)/(h*(w+1));
|
||||
rem = (int) b.at<float>(i,j) - r*h*(w+1);
|
||||
q = rem/h;
|
||||
p = rem - q*h;
|
||||
if(q==0)
|
||||
{
|
||||
p=h;
|
||||
q=w;
|
||||
r=r-1;
|
||||
}
|
||||
if(p==0)
|
||||
{
|
||||
p=h;
|
||||
q=q-1;
|
||||
}
|
||||
|
||||
r1 = (int) a.at<float>(i,j)/(h*(w+1));
|
||||
rem1 = (int) a.at<float>(i,j) - r1*h*(w+1);
|
||||
q1 = rem1/h;
|
||||
p1 = rem1 - q1*h;
|
||||
if(p1==0)
|
||||
{
|
||||
p1=h;
|
||||
q1=q1-1;
|
||||
}
|
||||
|
||||
final.at<float>(i,j*channel+2-c) = (box_filter.at<float>(p-1,q*channel+(2-r)) - box_filter.at<float>(p1-1,q1*channel+(2-r1)))
|
||||
/(upper_idx.at<float>(i,j) - lower_idx.at<float>(i,j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final.copyTo(output);
|
||||
}
|
||||
void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r)
|
||||
{
|
||||
int h = img.size().height;
|
||||
int w = img.size().width;
|
||||
int channel = img.channels();
|
||||
|
||||
//////////////////////////////////// horizontal and vertical partial derivatives /////////////////////////////////
|
||||
|
||||
Mat derivx = Mat::zeros(h,w-1,CV_32FC3);
|
||||
Mat derivy = Mat::zeros(h-1,w,CV_32FC3);
|
||||
|
||||
diffx(img,derivx);
|
||||
diffy(img,derivy);
|
||||
|
||||
Mat distx = Mat::zeros(h,w,CV_32FC1);
|
||||
Mat disty = Mat::zeros(h,w,CV_32FC1);
|
||||
|
||||
//////////////////////// Compute the l1-norm distance of neighbor pixels ////////////////////////////////////////////////
|
||||
|
||||
for(int i = 0; i < h; i++)
|
||||
for(int j = 0,k=1; j < w-1; j++,k++)
|
||||
for(int c = 0; c < channel; c++)
|
||||
{
|
||||
distx.at<float>(i,k) =
|
||||
distx.at<float>(i,k) + abs(derivx.at<float>(i,j*channel+c));
|
||||
}
|
||||
|
||||
for(int i = 0,k=1; i < h-1; i++,k++)
|
||||
for(int j = 0; j < w; j++)
|
||||
for(int c = 0; c < channel; c++)
|
||||
{
|
||||
disty.at<float>(k,j) =
|
||||
disty.at<float>(k,j) + abs(derivy.at<float>(i,j*channel+c));
|
||||
}
|
||||
|
||||
////////////////////// Compute the derivatives of the horizontal and vertical domain transforms. /////////////////////////////
|
||||
|
||||
horiz = Mat(h,w,CV_32FC1);
|
||||
vert = Mat(h,w,CV_32FC1);
|
||||
|
||||
Mat final = Mat(h,w,CV_32FC3);
|
||||
|
||||
Mat tempx,tempy;
|
||||
multiply(distx,sigma_s/sigma_r,tempx);
|
||||
multiply(disty,sigma_s/sigma_r,tempy);
|
||||
|
||||
horiz = 1.0f + tempx;
|
||||
vert = 1.0f + tempy;
|
||||
|
||||
O = Mat(h,w,CV_32FC3);
|
||||
img.copyTo(O);
|
||||
|
||||
O_t = Mat(w,h,CV_32FC3);
|
||||
|
||||
if(flags == 2)
|
||||
{
|
||||
|
||||
ct_H = Mat(h,w,CV_32FC1);
|
||||
ct_V = Mat(h,w,CV_32FC1);
|
||||
|
||||
for(int i = 0; i < h; i++)
|
||||
{
|
||||
ct_H.at<float>(i,0) = horiz.at<float>(i,0);
|
||||
for(int j = 1; j < w; j++)
|
||||
{
|
||||
ct_H.at<float>(i,j) = horiz.at<float>(i,j) + ct_H.at<float>(i,j-1);
|
||||
}
|
||||
}
|
||||
|
||||
for(int j = 0; j < w; j++)
|
||||
{
|
||||
ct_V.at<float>(0,j) = vert.at<float>(0,j);
|
||||
for(int i = 1; i < h; i++)
|
||||
{
|
||||
ct_V.at<float>(i,j) = vert.at<float>(i,j) + ct_V.at<float>(i-1,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Domain_Filter::filter(const Mat &img, Mat &res, float sigma_s = 60, float sigma_r = 0.4, int flags = 1)
|
||||
{
|
||||
int no_of_iter = 3;
|
||||
int h = img.size().height;
|
||||
int w = img.size().width;
|
||||
float sigma_h = sigma_s;
|
||||
|
||||
init(img,flags,sigma_s,sigma_r);
|
||||
|
||||
if(flags == 1)
|
||||
{
|
||||
Mat vert_t = vert.t();
|
||||
|
||||
for(int i=0;i<no_of_iter;i++)
|
||||
{
|
||||
sigma_h = (float) (sigma_s * sqrt(3.0) * pow(2.0,(no_of_iter - (i+1))) / sqrt(pow(4.0,no_of_iter) -1));
|
||||
|
||||
compute_Rfilter(O, horiz, sigma_h);
|
||||
|
||||
O_t = O.t();
|
||||
|
||||
compute_Rfilter(O_t, vert_t, sigma_h);
|
||||
|
||||
O = O_t.t();
|
||||
|
||||
}
|
||||
}
|
||||
else if(flags == 2)
|
||||
{
|
||||
|
||||
Mat vert_t = ct_V.t();
|
||||
Mat temp = Mat(h,w,CV_32FC1);
|
||||
Mat temp1 = Mat(w,h,CV_32FC1);
|
||||
|
||||
float radius;
|
||||
|
||||
for(int i=0;i<no_of_iter;i++)
|
||||
{
|
||||
sigma_h = (float) (sigma_s * sqrt(3.0) * pow(2.0,(no_of_iter - (i+1))) / sqrt(pow(4.0,no_of_iter) -1));
|
||||
|
||||
radius = (float) sqrt(3.0) * sigma_h;
|
||||
|
||||
compute_NCfilter(O, ct_H, temp,radius);
|
||||
|
||||
O_t = O.t();
|
||||
|
||||
compute_NCfilter(O_t, vert_t, temp1, radius);
|
||||
|
||||
O = O_t.t();
|
||||
}
|
||||
}
|
||||
|
||||
res = O.clone();
|
||||
}
|
||||
|
||||
void Domain_Filter::pencil_sketch(const Mat &img, Mat &sketch, Mat &color_res, float sigma_s, float sigma_r, float shade_factor)
|
||||
{
|
||||
|
||||
int no_of_iter = 3;
|
||||
init(img,2,sigma_s,sigma_r);
|
||||
int h = img.size().height;
|
||||
int w = img.size().width;
|
||||
|
||||
/////////////////////// convert to YCBCR model for color pencil drawing //////////////////////////////////////////////////////
|
||||
|
||||
Mat color_sketch = Mat(h,w,CV_32FC3);
|
||||
|
||||
cvtColor(img,color_sketch,COLOR_BGR2YCrCb);
|
||||
|
||||
vector <Mat> YUV_channel;
|
||||
Mat vert_t = ct_V.t();
|
||||
|
||||
float sigma_h = sigma_s;
|
||||
|
||||
Mat penx = Mat(h,w,CV_32FC1);
|
||||
|
||||
Mat pen_res = Mat::zeros(h,w,CV_32FC1);
|
||||
Mat peny = Mat(w,h,CV_32FC1);
|
||||
|
||||
Mat peny_t;
|
||||
|
||||
float radius;
|
||||
|
||||
for(int i=0;i<no_of_iter;i++)
|
||||
{
|
||||
sigma_h = (float) (sigma_s * sqrt(3.0) * pow(2.0,(no_of_iter - (i+1))) / sqrt(pow(4.0,no_of_iter) -1));
|
||||
|
||||
radius = (float) sqrt(3.0) * sigma_h;
|
||||
|
||||
compute_boxfilter(O, ct_H, penx, radius);
|
||||
|
||||
O_t = O.t();
|
||||
|
||||
compute_boxfilter(O_t, vert_t, peny, radius);
|
||||
|
||||
O = O_t.t();
|
||||
|
||||
peny_t = peny.t();
|
||||
|
||||
for(int k=0;k<h;k++)
|
||||
for(int j=0;j<w;j++)
|
||||
pen_res.at<float>(k,j) = (shade_factor * (penx.at<float>(k,j) + peny_t.at<float>(k,j)));
|
||||
|
||||
if(i==0)
|
||||
{
|
||||
sketch = pen_res.clone();
|
||||
split(color_sketch,YUV_channel);
|
||||
pen_res.copyTo(YUV_channel[0]);
|
||||
merge(YUV_channel,color_sketch);
|
||||
cvtColor(color_sketch,color_res,COLOR_YCrCb2BGR);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
193
modules/photo/src/seamless_cloning.cpp
Normal file
193
modules/photo/src/seamless_cloning.cpp
Normal file
@ -0,0 +1,193 @@
|
||||
/*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) 2013, OpenCV Foundation, 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"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "seamless_cloning.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags)
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
Mat dest = _dst.getMat();
|
||||
Mat mask = _mask.getMat();
|
||||
_blend.create(dest.size(), CV_8UC3);
|
||||
Mat blend = _blend.getMat();
|
||||
|
||||
int minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN;
|
||||
int h = mask.size().height;
|
||||
int w = mask.size().width;
|
||||
|
||||
Mat gray = Mat(mask.size(),CV_8UC1);
|
||||
Mat dst_mask = Mat::zeros(dest.size(),CV_8UC1);
|
||||
Mat cs_mask = Mat::zeros(src.size(),CV_8UC3);
|
||||
Mat cd_mask = Mat::zeros(dest.size(),CV_8UC3);
|
||||
|
||||
if(mask.channels() == 3)
|
||||
cvtColor(mask, gray, COLOR_BGR2GRAY );
|
||||
else
|
||||
gray = mask;
|
||||
|
||||
for(int i=0;i<h;i++)
|
||||
{
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
if(gray.at<uchar>(i,j) == 255)
|
||||
{
|
||||
minx = std::min(minx,i);
|
||||
maxx = std::max(maxx,i);
|
||||
miny = std::min(miny,j);
|
||||
maxy = std::max(maxy,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int lenx = maxx - minx;
|
||||
int leny = maxy - miny;
|
||||
|
||||
int minxd = p.y - lenx/2;
|
||||
int maxxd = p.y + lenx/2;
|
||||
int minyd = p.x - leny/2;
|
||||
int maxyd = p.x + leny/2;
|
||||
|
||||
if(minxd < 0 || minyd < 0 || maxxd > dest.size().height || maxyd > dest.size().width)
|
||||
{
|
||||
cout << "Index out of range" << endl;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
Rect roi_d(minyd,minxd,leny,lenx);
|
||||
Rect roi_s(miny,minx,leny,lenx);
|
||||
|
||||
Mat destinationROI = dst_mask(roi_d);
|
||||
Mat sourceROI = cs_mask(roi_s);
|
||||
|
||||
gray(roi_s).copyTo(destinationROI);
|
||||
src(roi_s).copyTo(sourceROI,gray(roi_s));
|
||||
|
||||
destinationROI = cd_mask(roi_d);
|
||||
cs_mask(roi_s).copyTo(destinationROI);
|
||||
|
||||
Cloning obj;
|
||||
obj.normal_clone(dest,cd_mask,dst_mask,blend,flags);
|
||||
}
|
||||
|
||||
void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float r, float g, float b)
|
||||
{
|
||||
Mat src = _src.getMat();
|
||||
Mat mask = _mask.getMat();
|
||||
_dst.create(src.size(), src.type());
|
||||
Mat blend = _dst.getMat();
|
||||
|
||||
float red = r;
|
||||
float green = g;
|
||||
float blue = b;
|
||||
|
||||
Mat gray = Mat::zeros(mask.size(),CV_8UC1);
|
||||
|
||||
if(mask.channels() == 3)
|
||||
cvtColor(mask, gray, COLOR_BGR2GRAY );
|
||||
else
|
||||
gray = mask;
|
||||
|
||||
Mat cs_mask = Mat::zeros(src.size(),CV_8UC3);
|
||||
|
||||
src.copyTo(cs_mask,gray);
|
||||
|
||||
Cloning obj;
|
||||
obj.local_color_change(src,cs_mask,gray,blend,red,green,blue);
|
||||
}
|
||||
|
||||
|
||||
void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float a, float b)
|
||||
{
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Mat mask = _mask.getMat();
|
||||
_dst.create(src.size(), src.type());
|
||||
Mat blend = _dst.getMat();
|
||||
float alpha = a;
|
||||
float beta = b;
|
||||
|
||||
Mat gray = Mat::zeros(mask.size(),CV_8UC1);
|
||||
|
||||
if(mask.channels() == 3)
|
||||
cvtColor(mask, gray, COLOR_BGR2GRAY );
|
||||
else
|
||||
gray = mask;
|
||||
|
||||
Mat cs_mask = Mat::zeros(src.size(),CV_8UC3);
|
||||
|
||||
src.copyTo(cs_mask,gray);
|
||||
|
||||
Cloning obj;
|
||||
obj.illum_change(src,cs_mask,gray,blend,alpha,beta);
|
||||
|
||||
}
|
||||
|
||||
void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst,
|
||||
double low_threshold, double high_threshold, int kernel_size)
|
||||
{
|
||||
|
||||
Mat src = _src.getMat();
|
||||
Mat mask = _mask.getMat();
|
||||
_dst.create(src.size(), src.type());
|
||||
Mat blend = _dst.getMat();
|
||||
|
||||
Mat gray = Mat::zeros(mask.size(),CV_8UC1);
|
||||
|
||||
if(mask.channels() == 3)
|
||||
cvtColor(mask, gray, COLOR_BGR2GRAY );
|
||||
else
|
||||
gray = mask;
|
||||
|
||||
Mat cs_mask = Mat::zeros(src.size(),CV_8UC3);
|
||||
|
||||
src.copyTo(cs_mask,gray);
|
||||
|
||||
Cloning obj;
|
||||
obj.texture_flatten(src,cs_mask,gray,low_threshold,high_threshold,kernel_size,blend);
|
||||
}
|
594
modules/photo/src/seamless_cloning.hpp
Normal file
594
modules/photo/src/seamless_cloning.hpp
Normal file
@ -0,0 +1,594 @@
|
||||
/*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) 2013, OpenCV Foundation, 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"
|
||||
#include "opencv2/photo.hpp"
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <complex>
|
||||
#include "math.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
|
||||
class Cloning
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
vector <Mat> rgb_channel, rgbx_channel, rgby_channel, output;
|
||||
Mat grx, gry, sgx, sgy, srx32, sry32, grx32, gry32, smask, smask1;
|
||||
void init_var(Mat &I, Mat &wmask);
|
||||
void initialization(Mat &I, Mat &mask, Mat &wmask);
|
||||
void scalar_product(Mat mat, float r, float g, float b);
|
||||
void array_product(Mat mat1, Mat mat2, Mat mat3);
|
||||
void poisson(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy);
|
||||
void evaluate(Mat &I, Mat &wmask, Mat &cloned);
|
||||
void getGradientx(const Mat &img, Mat &gx);
|
||||
void getGradienty(const Mat &img, Mat &gy);
|
||||
void lapx(const Mat &img, Mat &gxx);
|
||||
void lapy(const Mat &img, Mat &gyy);
|
||||
void dst(double *mod_diff, double *sineTransform,int h,int w);
|
||||
void idst(double *mod_diff, double *sineTransform,int h,int w);
|
||||
void transpose(double *mat, double *mat_t,int h,int w);
|
||||
void solve(const Mat &img, double *mod_diff, Mat &result);
|
||||
void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result);
|
||||
void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, int num);
|
||||
void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float red_mul, float green_mul, float blue_mul);
|
||||
void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alpha, float beta);
|
||||
void texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threhold, int kernel_size, Mat &cloned);
|
||||
};
|
||||
|
||||
void Cloning::getGradientx( const Mat &img, Mat &gx)
|
||||
{
|
||||
int w = img.size().width;
|
||||
int h = img.size().height;
|
||||
int channel = img.channels();
|
||||
for(int i=0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
for(int c=0;c<channel;++c)
|
||||
{
|
||||
gx.at<float>(i,j*channel+c) =
|
||||
(float)img.at<uchar>(i,(j+1)*channel+c) - (float)img.at<uchar>(i,j*channel+c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Cloning::getGradienty( const Mat &img, Mat &gy)
|
||||
{
|
||||
int w = img.size().width;
|
||||
int h = img.size().height;
|
||||
int channel = img.channels();
|
||||
for(int i=0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
for(int c=0;c<channel;++c)
|
||||
{
|
||||
gy.at<float>(i,j*channel+c) =
|
||||
(float)img.at<uchar>((i+1),j*channel+c) - (float)img.at<uchar>(i,j*channel+c);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Cloning::lapx( const Mat &img, Mat &gxx)
|
||||
{
|
||||
int w = img.size().width;
|
||||
int h = img.size().height;
|
||||
int channel = img.channels();
|
||||
for(int i=0;i<h;i++)
|
||||
for(int j=0;j<w-1;j++)
|
||||
for(int c=0;c<channel;++c)
|
||||
{
|
||||
gxx.at<float>(i,(j+1)*channel+c) =
|
||||
(float)img.at<float>(i,(j+1)*channel+c) - (float)img.at<float>(i,j*channel+c);
|
||||
}
|
||||
}
|
||||
|
||||
void Cloning::lapy( const Mat &img, Mat &gyy)
|
||||
{
|
||||
int w = img.size().width;
|
||||
int h = img.size().height;
|
||||
int channel = img.channels();
|
||||
for(int i=0;i<h-1;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
for(int c=0;c<channel;++c)
|
||||
{
|
||||
gyy.at<float>(i+1,j*channel+c) =
|
||||
(float)img.at<float>((i+1),j*channel+c) - (float)img.at<float>(i,j*channel+c);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Cloning::dst(double *mod_diff, double *sineTransform,int h,int w)
|
||||
{
|
||||
|
||||
unsigned long int idx;
|
||||
|
||||
Mat temp = Mat(2*h+2,1,CV_32F);
|
||||
Mat res = Mat(h,1,CV_32F);
|
||||
|
||||
Mat planes[] = {Mat_<float>(temp), Mat::zeros(temp.size(), CV_32F)};
|
||||
|
||||
Mat result;
|
||||
int p=0;
|
||||
for(int i=0;i<w;i++)
|
||||
{
|
||||
temp.at<float>(0,0) = 0.0;
|
||||
|
||||
for(int j=0,r=1;j<h;j++,r++)
|
||||
{
|
||||
idx = j*w+i;
|
||||
temp.at<float>(r,0) = (float) mod_diff[idx];
|
||||
}
|
||||
|
||||
temp.at<float>(h+1,0)=0.0;
|
||||
|
||||
for(int j=h-1, r=h+2;j>=0;j--,r++)
|
||||
{
|
||||
idx = j*w+i;
|
||||
temp.at<float>(r,0) = (float) (-1.0 * mod_diff[idx]);
|
||||
}
|
||||
|
||||
merge(planes, 2, result);
|
||||
|
||||
dft(result,result,0,0);
|
||||
|
||||
Mat planes1[] = {Mat::zeros(result.size(), CV_32F), Mat::zeros(result.size(), CV_32F)};
|
||||
|
||||
split(result, planes1);
|
||||
|
||||
std::complex<double> two_i = std::sqrt(std::complex<double>(-1));
|
||||
|
||||
double factor = -2*imag(two_i);
|
||||
|
||||
for(int c=1,z=0;c<h+1;c++,z++)
|
||||
{
|
||||
res.at<float>(z,0) = (float) (planes1[1].at<float>(c,0)/factor);
|
||||
}
|
||||
|
||||
for(int q=0,z=0;q<h;q++,z++)
|
||||
{
|
||||
idx = q*w+p;
|
||||
sineTransform[idx] = res.at<float>(z,0);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
void Cloning::idst(double *mod_diff, double *sineTransform,int h,int w)
|
||||
{
|
||||
int nn = h+1;
|
||||
unsigned long int idx;
|
||||
dst(mod_diff,sineTransform,h,w);
|
||||
for(int i= 0;i<h;i++)
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
idx = i*w + j;
|
||||
sineTransform[idx] = (double) (2*sineTransform[idx])/nn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Cloning::transpose(double *mat, double *mat_t,int h,int w)
|
||||
{
|
||||
|
||||
Mat tmp = Mat(h,w,CV_32FC1);
|
||||
unsigned long int idx;
|
||||
for(int i = 0 ; i < h;i++)
|
||||
{
|
||||
for(int j = 0 ; j < w; j++)
|
||||
{
|
||||
|
||||
idx = i*(w) + j;
|
||||
tmp.at<float>(i,j) = (float) mat[idx];
|
||||
}
|
||||
}
|
||||
Mat tmp_t = tmp.t();
|
||||
|
||||
for(int i = 0;i < tmp_t.size().height; i++)
|
||||
for(int j=0;j<tmp_t.size().width;j++)
|
||||
{
|
||||
idx = i*tmp_t.size().width + j;
|
||||
mat_t[idx] = tmp_t.at<float>(i,j);
|
||||
}
|
||||
}
|
||||
|
||||
void Cloning::solve(const Mat &img, double *mod_diff, Mat &result)
|
||||
{
|
||||
int w = img.size().width;
|
||||
int h = img.size().height;
|
||||
|
||||
unsigned long int idx,idx1;
|
||||
|
||||
double *sineTransform = new double[(h-2)*(w-2)];
|
||||
double *sineTransform_t = new double[(h-2)*(w-2)];
|
||||
double *denom = new double[(h-2)*(w-2)];
|
||||
double *invsineTransform = new double[(h-2)*(w-2)];
|
||||
double *invsineTransform_t = new double[(h-2)*(w-2)];
|
||||
double *img_d = new double[(h)*(w)];
|
||||
|
||||
dst(mod_diff,sineTransform,h-2,w-2);
|
||||
|
||||
transpose(sineTransform,sineTransform_t,h-2,w-2);
|
||||
|
||||
dst(sineTransform_t,sineTransform,w-2,h-2);
|
||||
|
||||
transpose(sineTransform,sineTransform_t,w-2,h-2);
|
||||
|
||||
int cy = 1;
|
||||
|
||||
for(int i = 0 ; i < w-2;i++,cy++)
|
||||
{
|
||||
for(int j = 0,cx = 1; j < h-2; j++,cx++)
|
||||
{
|
||||
idx = j*(w-2) + i;
|
||||
denom[idx] = (float) 2*cos(CV_PI*cy/( (double) (w-1))) - 2 + 2*cos(CV_PI*cx/((double) (h-1))) - 2;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for(idx = 0 ; idx < (unsigned)(w-2)*(h-2) ;idx++)
|
||||
{
|
||||
sineTransform_t[idx] = sineTransform_t[idx]/denom[idx];
|
||||
}
|
||||
|
||||
idst(sineTransform_t,invsineTransform,h-2,w-2);
|
||||
|
||||
transpose(invsineTransform,invsineTransform_t,h-2,w-2);
|
||||
|
||||
idst(invsineTransform_t,invsineTransform,w-2,h-2);
|
||||
|
||||
transpose(invsineTransform,invsineTransform_t,w-2,h-2);
|
||||
|
||||
for(int i = 0 ; i < h;i++)
|
||||
{
|
||||
for(int j = 0 ; j < w; j++)
|
||||
{
|
||||
idx = i*w + j;
|
||||
img_d[idx] = (double)img.at<uchar>(i,j);
|
||||
}
|
||||
}
|
||||
for(int i = 1 ; i < h-1;i++)
|
||||
{
|
||||
for(int j = 1 ; j < w-1; j++)
|
||||
{
|
||||
idx = i*w + j;
|
||||
img_d[idx] = 0.0;
|
||||
}
|
||||
}
|
||||
for(int i = 1,id1=0 ; i < h-1;i++,id1++)
|
||||
{
|
||||
for(int j = 1,id2=0 ; j < w-1; j++,id2++)
|
||||
{
|
||||
idx = i*w + j;
|
||||
idx1= id1*(w-2) + id2;
|
||||
img_d[idx] = invsineTransform_t[idx1];
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0 ; i < h;i++)
|
||||
{
|
||||
for(int j = 0 ; j < w; j++)
|
||||
{
|
||||
idx = i*w + j;
|
||||
if(img_d[idx] < 0.0)
|
||||
result.at<uchar>(i,j) = 0;
|
||||
else if(img_d[idx] > 255.0)
|
||||
result.at<uchar>(i,j) = 255;
|
||||
else
|
||||
result.at<uchar>(i,j) = (uchar) img_d[idx];
|
||||
}
|
||||
}
|
||||
|
||||
delete [] sineTransform;
|
||||
delete [] sineTransform_t;
|
||||
delete [] denom;
|
||||
delete [] invsineTransform;
|
||||
delete [] invsineTransform_t;
|
||||
delete [] img_d;
|
||||
}
|
||||
|
||||
void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result)
|
||||
{
|
||||
|
||||
int w = img.size().width;
|
||||
int h = img.size().height;
|
||||
|
||||
unsigned long int idx;
|
||||
|
||||
Mat lap = Mat(img.size(),CV_32FC1);
|
||||
|
||||
lap = gxx + gyy;
|
||||
|
||||
Mat bound = img.clone();
|
||||
|
||||
rectangle(bound, Point(1, 1), Point(img.cols-2, img.rows-2), Scalar::all(0), -1);
|
||||
|
||||
double *boundary_point = new double[h*w];
|
||||
|
||||
for(int i =1;i<h-1;i++)
|
||||
for(int j=1;j<w-1;j++)
|
||||
{
|
||||
idx=i*w + j;
|
||||
boundary_point[idx] = -4*(int)bound.at<uchar>(i,j) + (int)bound.at<uchar>(i,(j+1)) + (int)bound.at<uchar>(i,(j-1))
|
||||
+ (int)bound.at<uchar>(i-1,j) + (int)bound.at<uchar>(i+1,j);
|
||||
}
|
||||
|
||||
Mat diff = Mat(h,w,CV_32FC1);
|
||||
for(int i =0;i<h;i++)
|
||||
{
|
||||
for(int j=0;j<w;j++)
|
||||
{
|
||||
idx = i*w+j;
|
||||
diff.at<float>(i,j) = (float) (lap.at<float>(i,j) - boundary_point[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
double *mod_diff = new double[(h-2)*(w-2)];
|
||||
for(int i = 0 ; i < h-2;i++)
|
||||
{
|
||||
for(int j = 0 ; j < w-2; j++)
|
||||
{
|
||||
idx = i*(w-2) + j;
|
||||
mod_diff[idx] = diff.at<float>(i+1,j+1);
|
||||
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////// Find DST /////////////////////////////////////////////////////
|
||||
|
||||
solve(img,mod_diff,result);
|
||||
|
||||
delete [] mod_diff;
|
||||
delete [] boundary_point;
|
||||
}
|
||||
|
||||
void Cloning::init_var(Mat &I, Mat &wmask)
|
||||
{
|
||||
grx = Mat(I.size(),CV_32FC3);
|
||||
gry = Mat(I.size(),CV_32FC3);
|
||||
sgx = Mat(I.size(),CV_32FC3);
|
||||
sgy = Mat(I.size(),CV_32FC3);
|
||||
|
||||
split(I,rgb_channel);
|
||||
|
||||
smask = Mat(wmask.size(),CV_32FC1);
|
||||
srx32 = Mat(I.size(),CV_32FC3);
|
||||
sry32 = Mat(I.size(),CV_32FC3);
|
||||
smask1 = Mat(wmask.size(),CV_32FC1);
|
||||
grx32 = Mat(I.size(),CV_32FC3);
|
||||
gry32 = Mat(I.size(),CV_32FC3);
|
||||
}
|
||||
|
||||
void Cloning::initialization(Mat &I, Mat &mask, Mat &wmask)
|
||||
{
|
||||
init_var(I,wmask);
|
||||
|
||||
getGradientx(I,grx);
|
||||
getGradienty(I,gry);
|
||||
|
||||
getGradientx(mask,sgx);
|
||||
getGradienty(mask,sgy);
|
||||
|
||||
Mat Kernel(Size(3, 3), CV_8UC1);
|
||||
Kernel.setTo(Scalar(1));
|
||||
|
||||
erode(wmask, wmask, Kernel, Point(-1,-1), 3);
|
||||
|
||||
wmask.convertTo(smask,CV_32FC1,1.0/255.0);
|
||||
I.convertTo(srx32,CV_32FC3,1.0/255.0);
|
||||
I.convertTo(sry32,CV_32FC3,1.0/255.0);
|
||||
}
|
||||
|
||||
void Cloning::scalar_product(Mat mat, float r, float g, float b)
|
||||
{
|
||||
vector <Mat> channels;
|
||||
split(mat,channels);
|
||||
multiply(channels[2],r,channels[2]);
|
||||
multiply(channels[1],g,channels[1]);
|
||||
multiply(channels[0],b,channels[0]);
|
||||
merge(channels,mat);
|
||||
}
|
||||
|
||||
void Cloning::array_product(Mat mat1, Mat mat2, Mat mat3)
|
||||
{
|
||||
vector <Mat> channels_temp1;
|
||||
vector <Mat> channels_temp2;
|
||||
split(mat1,channels_temp1);
|
||||
split(mat2,channels_temp2);
|
||||
multiply(channels_temp2[2],mat3,channels_temp1[2]);
|
||||
multiply(channels_temp2[1],mat3,channels_temp1[1]);
|
||||
multiply(channels_temp2[0],mat3,channels_temp1[0]);
|
||||
merge(channels_temp1,mat1);
|
||||
}
|
||||
|
||||
void Cloning::poisson(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy)
|
||||
{
|
||||
Mat fx = Mat(I.size(),CV_32FC3);
|
||||
Mat fy = Mat(I.size(),CV_32FC3);
|
||||
|
||||
fx = gx + sx;
|
||||
fy = gy + sy;
|
||||
|
||||
Mat gxx = Mat(I.size(),CV_32FC3);
|
||||
Mat gyy = Mat(I.size(),CV_32FC3);
|
||||
|
||||
lapx(fx,gxx);
|
||||
lapy(fy,gyy);
|
||||
|
||||
split(gxx,rgbx_channel);
|
||||
split(gyy,rgby_channel);
|
||||
|
||||
split(I,output);
|
||||
|
||||
poisson_solver(rgb_channel[2],rgbx_channel[2], rgby_channel[2],output[2]);
|
||||
poisson_solver(rgb_channel[1],rgbx_channel[1], rgby_channel[1],output[1]);
|
||||
poisson_solver(rgb_channel[0],rgbx_channel[0], rgby_channel[0],output[0]);
|
||||
}
|
||||
|
||||
void Cloning::evaluate(Mat &I, Mat &wmask, Mat &cloned)
|
||||
{
|
||||
bitwise_not(wmask,wmask);
|
||||
|
||||
wmask.convertTo(smask1,CV_32FC1,1.0/255.0);
|
||||
I.convertTo(grx32,CV_32FC3,1.0/255.0);
|
||||
I.convertTo(gry32,CV_32FC3,1.0/255.0);
|
||||
|
||||
array_product(grx32,grx,smask1);
|
||||
array_product(gry32,gry,smask1);
|
||||
|
||||
poisson(I,grx32,gry32,srx32,sry32);
|
||||
|
||||
merge(output,cloned);
|
||||
}
|
||||
|
||||
void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, int num)
|
||||
{
|
||||
int w = I.size().width;
|
||||
int h = I.size().height;
|
||||
|
||||
initialization(I,mask,wmask);
|
||||
|
||||
if(num == 1)
|
||||
{
|
||||
array_product(srx32,sgx,smask);
|
||||
array_product(sry32,sgy,smask);
|
||||
|
||||
}
|
||||
else if(num == 2)
|
||||
{
|
||||
for(int i=0;i < h; i++)
|
||||
for(int j=0; j < w; j++)
|
||||
{
|
||||
if(abs(sgx.at<float>(i,j) - sgy.at<float>(i,j)) > abs(grx.at<float>(i,j) - gry.at<float>(i,j)))
|
||||
{
|
||||
srx32.at<float>(i,j) = sgx.at<float>(i,j) * smask.at<float>(i,j);
|
||||
sry32.at<float>(i,j) = sgy.at<float>(i,j) * smask.at<float>(i,j);
|
||||
}
|
||||
else
|
||||
{
|
||||
srx32.at<float>(i,j) = grx.at<float>(i,j) * smask.at<float>(i,j);
|
||||
sry32.at<float>(i,j) = gry.at<float>(i,j) * smask.at<float>(i,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(num == 3)
|
||||
{
|
||||
Mat gray = Mat(mask.size(),CV_8UC1);
|
||||
Mat gray8 = Mat(mask.size(),CV_8UC3);
|
||||
cvtColor(mask, gray, COLOR_BGR2GRAY );
|
||||
vector <Mat> temp;
|
||||
split(I,temp);
|
||||
gray.copyTo(temp[2]);
|
||||
gray.copyTo(temp[1]);
|
||||
gray.copyTo(temp[0]);
|
||||
|
||||
merge(temp,gray8);
|
||||
|
||||
getGradientx(gray8,sgx);
|
||||
getGradienty(gray8,sgy);
|
||||
|
||||
array_product(srx32,sgx,smask);
|
||||
array_product(sry32,sgy,smask);
|
||||
|
||||
}
|
||||
|
||||
evaluate(I,wmask,cloned);
|
||||
}
|
||||
|
||||
void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float red_mul=1.0,
|
||||
float green_mul=1.0, float blue_mul=1.0)
|
||||
{
|
||||
initialization(I,mask,wmask);
|
||||
|
||||
array_product(srx32,sgx,smask);
|
||||
array_product(sry32,sgy,smask);
|
||||
scalar_product(srx32,red_mul,green_mul,blue_mul);
|
||||
scalar_product(sry32,red_mul,green_mul,blue_mul);
|
||||
|
||||
evaluate(I,wmask,cloned);
|
||||
}
|
||||
|
||||
void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &cloned, float alpha, float beta)
|
||||
{
|
||||
initialization(I,mask,wmask);
|
||||
|
||||
array_product(srx32,sgx,smask);
|
||||
array_product(sry32,sgy,smask);
|
||||
|
||||
Mat mag = Mat(I.size(),CV_32FC3);
|
||||
magnitude(srx32,sry32,mag);
|
||||
|
||||
Mat multX, multY, multx_temp, multy_temp;
|
||||
|
||||
multiply(srx32,pow(alpha,beta),multX);
|
||||
pow(mag,-1*beta, multx_temp);
|
||||
multiply(multX,multx_temp,srx32);
|
||||
|
||||
multiply(sry32,pow(alpha,beta),multY);
|
||||
pow(mag,-1*beta, multy_temp);
|
||||
multiply(multY,multy_temp,sry32);
|
||||
|
||||
Mat zeroMask = (srx32 != 0);
|
||||
|
||||
srx32.copyTo(srx32, zeroMask);
|
||||
sry32.copyTo(sry32, zeroMask);
|
||||
|
||||
evaluate(I,wmask,cloned);
|
||||
}
|
||||
|
||||
void Cloning::texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold,
|
||||
double high_threshold, int kernel_size, Mat &cloned)
|
||||
{
|
||||
initialization(I,mask,wmask);
|
||||
|
||||
Mat out = Mat(mask.size(),CV_8UC1);
|
||||
Canny(mask,out,low_threshold,high_threshold,kernel_size);
|
||||
|
||||
Mat zeros(sgx.size(), CV_32FC3);
|
||||
zeros.setTo(0);
|
||||
Mat zerosMask = (out != 255);
|
||||
zeros.copyTo(sgx, zerosMask);
|
||||
zeros.copyTo(sgy, zerosMask);
|
||||
|
||||
array_product(srx32,sgx,smask);
|
||||
array_product(sry32,sgy,smask);
|
||||
|
||||
evaluate(I,wmask,cloned);
|
||||
}
|
181
modules/photo/test/test_cloning.cpp
Normal file
181
modules/photo/test/test_cloning.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
/*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) 2013, OpenCV Foundation, 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/photo.hpp"
|
||||
#include <string>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
|
||||
TEST(Photo_SeamlessClone_normal, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Normal_Cloning/";
|
||||
string original_path1 = folder + "source1.png";
|
||||
string original_path2 = folder + "destination1.png";
|
||||
string original_path3 = folder + "mask.png";
|
||||
|
||||
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||
Mat destination = imread(original_path2, IMREAD_COLOR);
|
||||
Mat mask = imread(original_path3, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||
ASSERT_FALSE(destination.empty()) << "Could not load destination image " << original_path2;
|
||||
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path3;
|
||||
|
||||
Mat result;
|
||||
Point p;
|
||||
p.x = destination.size().width/2;
|
||||
p.y = destination.size().height/2;
|
||||
seamlessClone(source, destination, mask, p, result, 1);
|
||||
|
||||
imwrite(folder + "cloned.png", result);
|
||||
|
||||
}
|
||||
|
||||
TEST(Photo_SeamlessClone_mixed, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Mixed_Cloning/";
|
||||
string original_path1 = folder + "source1.png";
|
||||
string original_path2 = folder + "destination1.png";
|
||||
string original_path3 = folder + "mask.png";
|
||||
|
||||
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||
Mat destination = imread(original_path2, IMREAD_COLOR);
|
||||
Mat mask = imread(original_path3, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||
ASSERT_FALSE(destination.empty()) << "Could not load destination image " << original_path2;
|
||||
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path3;
|
||||
|
||||
Mat result;
|
||||
Point p;
|
||||
p.x = destination.size().width/2;
|
||||
p.y = destination.size().height/2;
|
||||
seamlessClone(source, destination, mask, p, result, 2);
|
||||
|
||||
imwrite(folder + "cloned.png", result);
|
||||
|
||||
}
|
||||
|
||||
TEST(Photo_SeamlessClone_featureExchange, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Monochrome_Transfer/";
|
||||
string original_path1 = folder + "source1.png";
|
||||
string original_path2 = folder + "destination1.png";
|
||||
string original_path3 = folder + "mask.png";
|
||||
|
||||
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||
Mat destination = imread(original_path2, IMREAD_COLOR);
|
||||
Mat mask = imread(original_path3, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||
ASSERT_FALSE(destination.empty()) << "Could not load destination image " << original_path2;
|
||||
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path3;
|
||||
|
||||
Mat result;
|
||||
Point p;
|
||||
p.x = destination.size().width/2;
|
||||
p.y = destination.size().height/2;
|
||||
seamlessClone(source, destination, mask, p, result, 3);
|
||||
|
||||
imwrite(folder + "cloned.png", result);
|
||||
|
||||
}
|
||||
|
||||
TEST(Photo_SeamlessClone_colorChange, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/color_change/";
|
||||
string original_path1 = folder + "source1.png";
|
||||
string original_path2 = folder + "mask.png";
|
||||
|
||||
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||
Mat mask = imread(original_path2, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2;
|
||||
|
||||
Mat result;
|
||||
colorChange(source, mask, result, 1.5, .5, .5);
|
||||
|
||||
imwrite(folder + "cloned.png", result);
|
||||
|
||||
}
|
||||
|
||||
TEST(Photo_SeamlessClone_illuminationChange, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Illumination_Change/";
|
||||
string original_path1 = folder + "source1.png";
|
||||
string original_path2 = folder + "mask.png";
|
||||
|
||||
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||
Mat mask = imread(original_path2, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2;
|
||||
|
||||
Mat result;
|
||||
illuminationChange(source, mask, result, 0.2f, 0.4f);
|
||||
|
||||
imwrite(folder + "cloned.png", result);
|
||||
|
||||
}
|
||||
|
||||
TEST(Photo_SeamlessClone_textureFlattening, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Texture_Flattening/";
|
||||
string original_path1 = folder + "source1.png";
|
||||
string original_path2 = folder + "mask.png";
|
||||
|
||||
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||
Mat mask = imread(original_path2, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2;
|
||||
|
||||
Mat result;
|
||||
textureFlattening(source, mask, result, 30, 45, 3);
|
||||
|
||||
imwrite(folder + "cloned.png", result);
|
||||
|
||||
}
|
67
modules/photo/test/test_decolor.cpp
Normal file
67
modules/photo/test/test_decolor.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/*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) 2013, OpenCV Foundation, 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/photo.hpp"
|
||||
#include <string>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
|
||||
TEST(Photo_Decolor, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "decolor/";
|
||||
string original_path = folder + "color_image_1.png";
|
||||
|
||||
Mat original = imread(original_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(original.empty()) << "Could not load input image " << original_path;
|
||||
ASSERT_FALSE(original.channels()!=3) << "Load color input image " << original_path;
|
||||
|
||||
Mat grayscale, color_boost;
|
||||
decolor(original, grayscale, color_boost);
|
||||
|
||||
imwrite(folder + "grayscale.png",grayscale);
|
||||
imwrite(folder + "color_boost.png",color_boost);
|
||||
|
||||
}
|
130
modules/photo/test/test_npr.cpp
Executable file
130
modules/photo/test/test_npr.cpp
Executable file
@ -0,0 +1,130 @@
|
||||
/*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) 2013, OpenCV Foundation, 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/photo.hpp"
|
||||
#include <string>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
|
||||
TEST(Photo_NPR_EdgePreserveSmoothing_RecursiveFilter, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/";
|
||||
string original_path = folder + "test1.png";
|
||||
|
||||
Mat source = imread(original_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
|
||||
|
||||
Mat result;
|
||||
edgePreservingFilter(source,result,1);
|
||||
|
||||
imwrite(folder + "smoothened_RF.png", result);
|
||||
|
||||
}
|
||||
|
||||
TEST(Photo_NPR_EdgePreserveSmoothing_NormConvFilter, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/";
|
||||
string original_path = folder + "test1.png";
|
||||
|
||||
Mat source = imread(original_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
|
||||
|
||||
Mat result;
|
||||
edgePreservingFilter(source,result,2);
|
||||
|
||||
imwrite(folder + "smoothened_NCF.png", result);
|
||||
|
||||
}
|
||||
|
||||
TEST(Photo_NPR_DetailEnhance, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/";
|
||||
string original_path = folder + "test1.png";
|
||||
|
||||
Mat source = imread(original_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
|
||||
|
||||
Mat result;
|
||||
detailEnhance(source,result);
|
||||
|
||||
imwrite(folder + "detail_enhanced.png", result);
|
||||
|
||||
}
|
||||
|
||||
TEST(Photo_NPR_PencilSketch, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/";
|
||||
string original_path = folder + "test1.png";
|
||||
|
||||
Mat source = imread(original_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
|
||||
|
||||
Mat result,result1;
|
||||
pencilSketch(source,result,result1, 10, 0.1f, 0.03f);
|
||||
|
||||
imwrite(folder + "pencil_sketch.png", result);
|
||||
imwrite(folder + "color_pencil_sketch.png", result1);
|
||||
|
||||
}
|
||||
|
||||
TEST(Photo_NPR_Stylization, regression)
|
||||
{
|
||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/";
|
||||
string original_path = folder + "test1.png";
|
||||
|
||||
Mat source = imread(original_path, IMREAD_COLOR);
|
||||
|
||||
ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
|
||||
|
||||
Mat result;
|
||||
stylization(source,result);
|
||||
|
||||
imwrite(folder + "stylized.png", result);
|
||||
|
||||
}
|
@ -110,6 +110,26 @@ extern int test_loop_times;
|
||||
<< cv::format("Size: %d x %d", mat1.size().width, mat1.size().height) << std::endl; \
|
||||
}
|
||||
|
||||
#define OCL_EXPECT_MATS_NEAR(name, eps) \
|
||||
{ \
|
||||
EXPECT_MAT_NEAR(name ## _roi, u ## name ## _roi, eps); \
|
||||
int nextValue = rng.next(); \
|
||||
RNG dataRng1(nextValue), dataRng2(nextValue); \
|
||||
dataRng1.fill(name ## _roi, RNG::UNIFORM, Scalar::all(-MAX_VALUE), Scalar::all(MAX_VALUE)); \
|
||||
dataRng2.fill(u ## name ## _roi, RNG::UNIFORM, Scalar::all(-MAX_VALUE), Scalar::all(MAX_VALUE)); \
|
||||
EXPECT_MAT_NEAR(name, u ## name, 0/*FLT_EPSILON*/); \
|
||||
}
|
||||
|
||||
#define OCL_EXPECT_MATS_NEAR_RELATIVE(name, eps) \
|
||||
{ \
|
||||
EXPECT_MAT_NEAR_RELATIVE(name ## _roi, u ## name ## _roi, eps); \
|
||||
int nextValue = rng.next(); \
|
||||
RNG dataRng1(nextValue), dataRng2(nextValue); \
|
||||
dataRng1.fill(name ## _roi, RNG::UNIFORM, Scalar::all(-MAX_VALUE), Scalar::all(MAX_VALUE)); \
|
||||
dataRng2.fill(u ## name ## _roi, RNG::UNIFORM, Scalar::all(-MAX_VALUE), Scalar::all(MAX_VALUE)); \
|
||||
EXPECT_MAT_NEAR_RELATIVE(name, u ## name, 0/*FLT_EPSILON*/); \
|
||||
}
|
||||
|
||||
#define EXPECT_MAT_SIMILAR(mat1, mat2, eps) \
|
||||
{ \
|
||||
ASSERT_EQ(mat1.type(), mat2.type()); \
|
||||
@ -302,12 +322,12 @@ IMPLEMENT_PARAM_CLASS(Channels, int)
|
||||
#define OCL_OFF(fn) cv::ocl::setUseOpenCL(false); fn
|
||||
#define OCL_ON(fn) cv::ocl::setUseOpenCL(true); fn
|
||||
|
||||
#define OCL_ALL_DEPTHS Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F)
|
||||
#define OCL_ALL_DEPTHS Values(CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F)
|
||||
#define OCL_ALL_CHANNELS Values(1, 2, 3, 4)
|
||||
|
||||
CV_ENUM(Interpolation, INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_AREA)
|
||||
CV_ENUM(ThreshOp, THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV)
|
||||
CV_ENUM(BorderType, BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, BORDER_REFLECT_101)
|
||||
CV_ENUM(BorderType, BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, BORDER_REFLECT_101)
|
||||
|
||||
#define OCL_INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
|
||||
INSTANTIATE_TEST_CASE_P(OCL_ ## prefix, test_case_name, generator)
|
||||
|
@ -1,57 +1,11 @@
|
||||
macro(find_qvtk)
|
||||
find_library (QVTK_LIBRARY QVTK HINTS ${VTK_DIR} ${VTK_DIR}/bin)
|
||||
find_path (QVTK_INCLUDE_DIR QVTKWidget.h HINT ${VTK_INCLUDE_DIRS})
|
||||
find_package_handle_standard_args(QVTK DEFAULT_MSG QVTK_LIBRARY QVTK_INCLUDE_DIR)
|
||||
|
||||
if(QVTK_FOUND)
|
||||
get_filename_component (QVTK_LIBRARY_DIR ${QVTK_LIBRARY} PATH)
|
||||
list(APPEND VTK_LIBRARY_DIRS ${QVTK_LIBRARY_DIR})
|
||||
list(APPEND VTK_INCLUDE_DIRS ${QVTK_INCLUDE_DIR})
|
||||
set (VTK_USE_QVTK ON)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(find_vtk)
|
||||
find_package(VTK)
|
||||
if(${VTK_MAJOR_VERSION} LESS 5)
|
||||
MESSAGE(FATAL_ERROR "VTK 5 or more required!")
|
||||
endif()
|
||||
if(VTK_FOUND)
|
||||
if (BUILD_SHARED_LIBS OR (NOT BUILD_SHARED_LIBS AND NOT VTK_BUILD_SHARED_LIBS))
|
||||
find_qvtk()
|
||||
message(STATUS "VTK found (include: ${VTK_INCLUDE_DIRS}, lib: ${VTK_LIBRARY_DIRS})")
|
||||
link_directories(${VTK_LIBRARY_DIRS})
|
||||
include_directories(SYSTEM ${VTK_INCLUDE_DIRS})
|
||||
set(HAVE_VTK ON)
|
||||
else ()
|
||||
set(HAVE_VTK OFF)
|
||||
message (FATAL_ERROR "VTK disabled. You are to build OpenCV in STATIC but VTK is SHARED!")
|
||||
endif ()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
if (NOT OPENCV_INITIAL_PASS AND DEFINED BUILD_opencv_viz AND BUILD_opencv_viz)
|
||||
find_vtk()
|
||||
endif()
|
||||
|
||||
if(DEFINED HAVE_VTK AND HAVE_VTK)
|
||||
set(VTK_USE_FILE ${VTK_USE_FILE} CACHE INTERNAL "VTK_USE_FILE")
|
||||
include (${VTK_USE_FILE})
|
||||
add_definitions(-DHAVE_VTK)
|
||||
if(NOT WITH_VTK OR NOT DEFINED HAVE_VTK OR NOT HAVE_VTK)
|
||||
ocv_module_disable(viz)
|
||||
endif()
|
||||
|
||||
include(${VTK_USE_FILE})
|
||||
set(the_description "Viz")
|
||||
set(BUILD_opencv_viz_INIT OFF)
|
||||
include_directories(src)
|
||||
ocv_define_module(viz opencv_core)
|
||||
ocv_define_module(viz opencv_core ${VTK_LIBRARIES})
|
||||
|
||||
if(DEFINED BUILD_opencv_viz AND BUILD_opencv_viz AND DEFINED HAVE_VTK AND HAVE_VTK)
|
||||
if (${VTK_VERSION_MAJOR} EQUAL 5)
|
||||
target_link_libraries(opencv_viz vtkCommon vtkWidgets vtkFiltering vtkRendering)
|
||||
else()
|
||||
target_link_libraries(opencv_viz vtkViewsCore vtkRenderingLOD vtkIOPLY vtkRenderingFreeTypeOpenGL vtkRenderingVolumeOpenGL vtkFiltersTexture)
|
||||
endif()
|
||||
if(APPLE)
|
||||
target_link_libraries(opencv_viz "-framework Cocoa")
|
||||
endif()
|
||||
if(APPLE AND BUILD_opencv_viz)
|
||||
target_link_libraries(opencv_viz "-framework Cocoa")
|
||||
endif()
|
||||
|
@ -76,68 +76,6 @@ Checks **point** for nan
|
||||
|
||||
:param p: return true if **any** of the elements of the point is *nan*.
|
||||
|
||||
viz::VizAccessor
|
||||
----------------
|
||||
.. ocv:class:: VizAccessor
|
||||
|
||||
A singleton class that provides access by name infrastructure for 3D visualization windows. ::
|
||||
|
||||
class CV_EXPORTS VizAccessor
|
||||
{
|
||||
public:
|
||||
static VizAccessor & getInstance();
|
||||
static void release();
|
||||
|
||||
Viz3d get(const String &window_name);
|
||||
|
||||
//! window names automatically have Viz - prefix even though not provided by the users
|
||||
static void generateWindowName(const String &window_name, String &output);
|
||||
|
||||
private:
|
||||
/* hidden */
|
||||
};
|
||||
|
||||
viz::VizAccessor::getInstance
|
||||
-----------------------------
|
||||
Returns the single instance of VizAccessor.
|
||||
|
||||
.. ocv:function:: static VizAccessor & getInstance()
|
||||
|
||||
viz::VizAccessor::release
|
||||
-------------------------
|
||||
Deletes the single instance of VizAccessor.
|
||||
|
||||
.. ocv:function:: static void release()
|
||||
|
||||
viz::VizAccessor::get
|
||||
---------------------
|
||||
Retrieves a window by its name.
|
||||
|
||||
.. ocv:function:: Viz3d get(const String &window_name)
|
||||
|
||||
:param window_name: Name of the window that is to be retrieved.
|
||||
|
||||
This function returns a :ocv:class:`Viz3d` object with the given name.
|
||||
|
||||
.. note:: If the window with that name already exists, that window is returned. Otherwise, new window is created with the given name, and it is returned.
|
||||
|
||||
.. note:: Window names are automatically prefixed by "Viz - " if it is not done by the user.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
/// window and window_2 are the same windows.
|
||||
viz::Viz3d window = viz::get("myWindow");
|
||||
viz::Viz3d window_2 = viz::get("Viz - myWindow");
|
||||
|
||||
viz::VizAccessor::generateWindowName
|
||||
------------------------------------
|
||||
Generates a window name by prefixing "Viz - " if it has not already been prefixed.
|
||||
|
||||
.. ocv:function:: static void generateWindowName(const String &window_name, String &output)
|
||||
|
||||
:param window_name: Window name
|
||||
:param output: Prefixed window name
|
||||
|
||||
viz::Viz3d
|
||||
----------
|
||||
.. ocv:class:: Viz3d
|
||||
|
@ -262,8 +262,8 @@ This 3D Widget defines a finite plane. ::
|
||||
class CV_EXPORTS WPlane : public Widget3D
|
||||
{
|
||||
public:
|
||||
WPlane(const Vec4f& coefs, double size = 1.0, const Color &color = Color::white());
|
||||
WPlane(const Vec4f& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white());
|
||||
WPlane(const Vec4f& coefs, float size = 1.0, const Color &color = Color::white());
|
||||
WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.0, const Color &color = Color::white());
|
||||
private:
|
||||
/* hidden */
|
||||
};
|
||||
@ -272,13 +272,13 @@ viz::WPlane::WPlane
|
||||
-------------------
|
||||
Constructs a WPlane.
|
||||
|
||||
.. ocv:function:: WPlane(const Vec4f& coefs, double size = 1.0, const Color &color = Color::white())
|
||||
.. ocv:function:: WPlane(const Vec4f& coefs, float size = 1.0, const Color &color = Color::white())
|
||||
|
||||
:param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0.
|
||||
:param size: Size of the plane.
|
||||
:param color: :ocv:class:`Color` of the plane.
|
||||
|
||||
.. ocv:function:: WPlane(const Vec4f& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white())
|
||||
.. ocv:function:: WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.0, const Color &color = Color::white())
|
||||
|
||||
:param coefs: Plane coefficients as in (A,B,C,D) where Ax + By + Cz + D = 0.
|
||||
:param pt: Position of the plane.
|
||||
@ -317,14 +317,14 @@ This 3D Widget defines an arrow. ::
|
||||
class CV_EXPORTS WArrow : public Widget3D
|
||||
{
|
||||
public:
|
||||
WArrow(const Point3f& pt1, const Point3f& pt2, double thickness = 0.03, const Color &color = Color::white());
|
||||
WArrow(const Point3f& pt1, const Point3f& pt2, float thickness = 0.03, const Color &color = Color::white());
|
||||
};
|
||||
|
||||
viz::WArrow::WArrow
|
||||
-----------------------------
|
||||
Constructs an WArrow.
|
||||
|
||||
.. ocv:function:: WArrow(const Point3f& pt1, const Point3f& pt2, double thickness = 0.03, const Color &color = Color::white())
|
||||
.. ocv:function:: WArrow(const Point3f& pt1, const Point3f& pt2, float thickness = 0.03, const Color &color = Color::white())
|
||||
|
||||
:param pt1: Start point of the arrow.
|
||||
:param pt2: End point of the arrow.
|
||||
@ -342,14 +342,14 @@ This 3D Widget defines a circle. ::
|
||||
class CV_EXPORTS WCircle : public Widget3D
|
||||
{
|
||||
public:
|
||||
WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white());
|
||||
WCircle(const Point3f& pt, float radius, float thickness = 0.01, const Color &color = Color::white());
|
||||
};
|
||||
|
||||
viz::WCircle::WCircle
|
||||
-------------------------------
|
||||
Constructs a WCircle.
|
||||
|
||||
.. ocv:function:: WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white())
|
||||
.. ocv:function:: WCircle(const Point3f& pt, float radius, float thickness = 0.01, const Color &color = Color::white())
|
||||
|
||||
:param pt: Center of the circle.
|
||||
:param radius: Radius of the circle.
|
||||
@ -365,14 +365,14 @@ This 3D Widget defines a cylinder. ::
|
||||
class CV_EXPORTS WCylinder : public Widget3D
|
||||
{
|
||||
public:
|
||||
WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white());
|
||||
WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white());
|
||||
};
|
||||
|
||||
viz::WCylinder::WCylinder
|
||||
-----------------------------------
|
||||
Constructs a WCylinder.
|
||||
|
||||
.. ocv:function:: WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white())
|
||||
.. ocv:function:: WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white())
|
||||
|
||||
:param pt_on_axis: A point on the axis of the cylinder.
|
||||
:param axis_direction: Direction of the axis of the cylinder.
|
||||
@ -416,14 +416,14 @@ This 3D Widget represents a coordinate system. ::
|
||||
class CV_EXPORTS WCoordinateSystem : public Widget3D
|
||||
{
|
||||
public:
|
||||
WCoordinateSystem(double scale = 1.0);
|
||||
WCoordinateSystem(float scale = 1.0);
|
||||
};
|
||||
|
||||
viz::WCoordinateSystem::WCoordinateSystem
|
||||
---------------------------------------------------
|
||||
Constructs a WCoordinateSystem.
|
||||
|
||||
.. ocv:function:: WCoordinateSystem(double scale = 1.0)
|
||||
.. ocv:function:: WCoordinateSystem(float scale = 1.0)
|
||||
|
||||
:param scale: Determines the size of the axes.
|
||||
|
||||
@ -494,7 +494,7 @@ This 3D Widget represents 3D text. The text always faces the camera. ::
|
||||
class CV_EXPORTS WText3D : public Widget3D
|
||||
{
|
||||
public:
|
||||
WText3D(const String &text, const Point3f &position, double text_scale = 1.0, double face_camera = true, const Color &color = Color::white());
|
||||
WText3D(const String &text, const Point3f &position, float text_scale = 1.0, bool face_camera = true, const Color &color = Color::white());
|
||||
|
||||
void setText(const String &text);
|
||||
String getText() const;
|
||||
@ -504,7 +504,7 @@ viz::WText3D::WText3D
|
||||
-------------------------------
|
||||
Constructs a WText3D.
|
||||
|
||||
.. ocv:function:: WText3D(const String &text, const Point3f &position, double text_scale = 1.0, double face_camera = true, const Color &color = Color::white())
|
||||
.. ocv:function:: WText3D(const String &text, const Point3f &position, float text_scale = 1.0, bool face_camera = true, const Color &color = Color::white())
|
||||
|
||||
:param text: Text content of the widget.
|
||||
:param position: Position of the text.
|
||||
@ -649,15 +649,15 @@ This 3D Widget represents camera position in a scene by its axes or viewing frus
|
||||
{
|
||||
public:
|
||||
//! Creates camera coordinate frame (axes) at the origin
|
||||
WCameraPosition(double scale = 1.0);
|
||||
WCameraPosition(float scale = 1.0);
|
||||
//! Creates frustum based on the intrinsic marix K at the origin
|
||||
WCameraPosition(const Matx33f &K, double scale = 1.0, const Color &color = Color::white());
|
||||
WCameraPosition(const Matx33f &K, float scale = 1.0, const Color &color = Color::white());
|
||||
//! Creates frustum based on the field of view at the origin
|
||||
WCameraPosition(const Vec2f &fov, double scale = 1.0, const Color &color = Color::white());
|
||||
WCameraPosition(const Vec2f &fov, float scale = 1.0, const Color &color = Color::white());
|
||||
//! Creates frustum and display given image at the far plane
|
||||
WCameraPosition(const Matx33f &K, const Mat &img, double scale = 1.0, const Color &color = Color::white());
|
||||
WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.0, const Color &color = Color::white());
|
||||
//! Creates frustum and display given image at the far plane
|
||||
WCameraPosition(const Vec2f &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white());
|
||||
WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.0, const Color &color = Color::white());
|
||||
};
|
||||
|
||||
viz::WCameraPosition::WCameraPosition
|
||||
@ -666,7 +666,7 @@ Constructs a WCameraPosition.
|
||||
|
||||
- **Display camera coordinate frame.**
|
||||
|
||||
.. ocv:function:: WCameraPosition(double scale = 1.0)
|
||||
.. ocv:function:: WCameraPosition(float scale = 1.0)
|
||||
|
||||
Creates camera coordinate frame at the origin.
|
||||
|
||||
@ -676,7 +676,7 @@ Constructs a WCameraPosition.
|
||||
|
||||
- **Display the viewing frustum.**
|
||||
|
||||
.. ocv:function:: WCameraPosition(const Matx33f &K, double scale = 1.0, const Color &color = Color::white())
|
||||
.. ocv:function:: WCameraPosition(const Matx33f &K, float scale = 1.0, const Color &color = Color::white())
|
||||
|
||||
:param K: Intrinsic matrix of the camera.
|
||||
:param scale: Scale of the frustum.
|
||||
@ -684,7 +684,7 @@ Constructs a WCameraPosition.
|
||||
|
||||
Creates viewing frustum of the camera based on its intrinsic matrix K.
|
||||
|
||||
.. ocv:function:: WCameraPosition(const Vec2f &fov, double scale = 1.0, const Color &color = Color::white())
|
||||
.. ocv:function:: WCameraPosition(const Vec2f &fov, float scale = 1.0, const Color &color = Color::white())
|
||||
|
||||
:param fov: Field of view of the camera (horizontal, vertical).
|
||||
:param scale: Scale of the frustum.
|
||||
@ -698,7 +698,7 @@ Constructs a WCameraPosition.
|
||||
|
||||
- **Display image on the far plane of the viewing frustum.**
|
||||
|
||||
.. ocv:function:: WCameraPosition(const Matx33f &K, const Mat &img, double scale = 1.0, const Color &color = Color::white())
|
||||
.. ocv:function:: WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.0, const Color &color = Color::white())
|
||||
|
||||
:param K: Intrinsic matrix of the camera.
|
||||
:param img: BGR or Gray-Scale image that is going to be displayed on the far plane of the frustum.
|
||||
@ -707,7 +707,7 @@ Constructs a WCameraPosition.
|
||||
|
||||
Creates viewing frustum of the camera based on its intrinsic matrix K, and displays image on the far end plane.
|
||||
|
||||
.. ocv:function:: WCameraPosition(const Vec2f &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white())
|
||||
.. ocv:function:: WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.0, const Color &color = Color::white())
|
||||
|
||||
:param fov: Field of view of the camera (horizontal, vertical).
|
||||
:param img: BGR or Gray-Scale image that is going to be displayed on the far plane of the frustum.
|
||||
@ -732,11 +732,11 @@ This 3D Widget represents a trajectory. ::
|
||||
enum {DISPLAY_FRAMES = 1, DISPLAY_PATH = 2};
|
||||
|
||||
//! Displays trajectory of the given path either by coordinate frames or polyline
|
||||
WTrajectory(const std::vector<Affine3f> &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), double scale = 1.0);
|
||||
WTrajectory(const std::vector<Affine3f> &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.0);
|
||||
//! Displays trajectory of the given path by frustums
|
||||
WTrajectory(const std::vector<Affine3f> &path, const Matx33f &K, double scale = 1.0, const Color &color = Color::white());
|
||||
WTrajectory(const std::vector<Affine3f> &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white());
|
||||
//! Displays trajectory of the given path by frustums
|
||||
WTrajectory(const std::vector<Affine3f> &path, const Vec2f &fov, double scale = 1.0, const Color &color = Color::white());
|
||||
WTrajectory(const std::vector<Affine3f> &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white());
|
||||
|
||||
private:
|
||||
/* hidden */
|
||||
@ -746,7 +746,7 @@ viz::WTrajectory::WTrajectory
|
||||
-----------------------------
|
||||
Constructs a WTrajectory.
|
||||
|
||||
.. ocv:function:: WTrajectory(const std::vector<Affine3f> &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), double scale = 1.0)
|
||||
.. ocv:function:: WTrajectory(const std::vector<Affine3f> &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.0)
|
||||
|
||||
:param path: List of poses on a trajectory.
|
||||
:param display_mode: Display mode. This can be DISPLAY_PATH, DISPLAY_FRAMES, DISPLAY_PATH & DISPLAY_FRAMES.
|
||||
@ -759,7 +759,7 @@ Constructs a WTrajectory.
|
||||
* DISPLAY_FRAMES : Displays coordinate frames at each pose.
|
||||
* DISPLAY_PATH & DISPLAY_FRAMES : Displays both poly line and coordinate frames.
|
||||
|
||||
.. ocv:function:: WTrajectory(const std::vector<Affine3f> &path, const Matx33f &K, double scale = 1.0, const Color &color = Color::white())
|
||||
.. ocv:function:: WTrajectory(const std::vector<Affine3f> &path, const Matx33f &K, float scale = 1.0, const Color &color = Color::white())
|
||||
|
||||
:param path: List of poses on a trajectory.
|
||||
:param K: Intrinsic matrix of the camera.
|
||||
@ -768,7 +768,7 @@ Constructs a WTrajectory.
|
||||
|
||||
Displays frustums at each pose of the trajectory.
|
||||
|
||||
.. ocv:function:: WTrajectory(const std::vector<Affine3f> &path, const Vec2f &fov, double scale = 1.0, const Color &color = Color::white())
|
||||
.. ocv:function:: WTrajectory(const std::vector<Affine3f> &path, const Vec2f &fov, float scale = 1.0, const Color &color = Color::white())
|
||||
|
||||
:param path: List of poses on a trajectory.
|
||||
:param fov: Field of view of the camera (horizontal, vertical).
|
||||
@ -788,7 +788,7 @@ represent the direction from previous position to the current. ::
|
||||
{
|
||||
public:
|
||||
WSpheresTrajectory(const std::vector<Affine3f> &path, float line_length = 0.05f,
|
||||
double init_sphere_radius = 0.021, sphere_radius = 0.007,
|
||||
float init_sphere_radius = 0.021, sphere_radius = 0.007,
|
||||
Color &line_color = Color::white(), const Color &sphere_color = Color::white());
|
||||
};
|
||||
|
||||
@ -796,7 +796,7 @@ viz::WSpheresTrajectory::WSpheresTrajectory
|
||||
-------------------------------------------
|
||||
Constructs a WSpheresTrajectory.
|
||||
|
||||
.. ocv:function:: WSpheresTrajectory(const std::vector<Affine3f> &path, float line_length = 0.05f, double init_sphere_radius = 0.021, double sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white())
|
||||
.. ocv:function:: WSpheresTrajectory(const std::vector<Affine3f> &path, float line_length = 0.05f, float init_sphere_radius = 0.021, float sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white())
|
||||
|
||||
:param path: List of poses on a trajectory.
|
||||
:param line_length: Length of the lines.
|
||||
|
@ -63,9 +63,12 @@ namespace cv
|
||||
//! constructs camera pose from position, focal_point and up_vector (see gluLookAt() for more infromation)
|
||||
CV_EXPORTS Affine3f makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& y_dir);
|
||||
|
||||
//! retrieves a window by its name
|
||||
//! retrieves a window by its name. If no window with such name, then it creates new.
|
||||
CV_EXPORTS Viz3d get(const String &window_name);
|
||||
|
||||
//! Unregisters all Viz windows from internal database. After it 'get()' will create new windows instead getting existing from the database.
|
||||
CV_EXPORTS void unregisterAllWindows();
|
||||
|
||||
//! checks float value for Nan
|
||||
inline bool isNan(float x)
|
||||
{
|
||||
@ -88,32 +91,6 @@ namespace cv
|
||||
template<typename _Tp> inline bool isNan(const Point3_<_Tp>& p)
|
||||
{ return isNan(p.x) || isNan(p.y) || isNan(p.z); }
|
||||
|
||||
//! helper class that provides access by name infrastructure
|
||||
class CV_EXPORTS VizAccessor
|
||||
{
|
||||
public:
|
||||
static VizAccessor & getInstance();
|
||||
static void release();
|
||||
|
||||
Viz3d get(const String &window_name);
|
||||
|
||||
//! window names automatically have Viz - prefix even though not provided by the users
|
||||
static void generateWindowName(const String &window_name, String &output);
|
||||
|
||||
private:
|
||||
VizAccessor(); // Singleton
|
||||
~VizAccessor();
|
||||
|
||||
void add(Viz3d window);
|
||||
void remove(const String &window_name);
|
||||
|
||||
static VizAccessor * instance_;
|
||||
|
||||
struct VizAccessorImpl;
|
||||
VizAccessorImpl * impl_;
|
||||
|
||||
friend class Viz3d;
|
||||
};
|
||||
} /* namespace viz */
|
||||
} /* namespace cv */
|
||||
|
||||
|
@ -176,8 +176,8 @@ namespace cv
|
||||
/// cv::viz::Color
|
||||
|
||||
inline cv::viz::Color::Color() : Scalar(0, 0, 0) {}
|
||||
inline cv::viz::Color::Color(double gray) : Scalar(gray, gray, gray) {}
|
||||
inline cv::viz::Color::Color(double blue, double green, double red) : Scalar(blue, green, red) {}
|
||||
inline cv::viz::Color::Color(double _gray) : Scalar(_gray, _gray, _gray) {}
|
||||
inline cv::viz::Color::Color(double _blue, double _green, double _red) : Scalar(_blue, _green, _red) {}
|
||||
inline cv::viz::Color::Color(const Scalar& color) : Scalar(color) {}
|
||||
|
||||
inline cv::viz::Color cv::viz::Color::black() { return Color( 0, 0, 0); }
|
||||
|
@ -49,7 +49,7 @@
|
||||
#ifndef __OPENCV_VIZ_VIZ3D_HPP__
|
||||
#define __OPENCV_VIZ_VIZ3D_HPP__
|
||||
|
||||
#if !defined YES_I_AGREE_THAT_VIZ_API_IS_NOT_STABLE_NOW_AND_BINARY_COMPARTIBILITY_WONT_BE_SUPPORTED
|
||||
#if !defined YES_I_AGREE_THAT_VIZ_API_IS_NOT_STABLE_NOW_AND_BINARY_COMPARTIBILITY_WONT_BE_SUPPORTED && !defined CVAPI_EXPORTS
|
||||
//#error "Viz is in beta state now. Please define macro above to use it"
|
||||
#endif
|
||||
|
||||
@ -64,7 +64,6 @@ namespace cv
|
||||
class CV_EXPORTS Viz3d
|
||||
{
|
||||
public:
|
||||
typedef cv::Ptr<Viz3d> Ptr;
|
||||
typedef void (*KeyboardCallback)(const KeyboardEvent&, void*);
|
||||
typedef void (*MouseCallback)(const MouseEvent&, void*);
|
||||
|
||||
@ -122,6 +121,8 @@ namespace cv
|
||||
|
||||
void create(const String &window_name);
|
||||
void release();
|
||||
|
||||
friend class VizStorage;
|
||||
};
|
||||
|
||||
} /* namespace viz */
|
||||
|
@ -143,8 +143,8 @@ namespace cv
|
||||
class CV_EXPORTS WPlane : public Widget3D
|
||||
{
|
||||
public:
|
||||
WPlane(const Vec4f& coefs, double size = 1.0, const Color &color = Color::white());
|
||||
WPlane(const Vec4f& coefs, const Point3f& pt, double size = 1.0, const Color &color = Color::white());
|
||||
WPlane(const Vec4f& coefs, float size = 1.f, const Color &color = Color::white());
|
||||
WPlane(const Vec4f& coefs, const Point3f& pt, float size = 1.f, const Color &color = Color::white());
|
||||
private:
|
||||
struct SetSizeImpl;
|
||||
};
|
||||
@ -158,19 +158,19 @@ namespace cv
|
||||
class CV_EXPORTS WArrow : public Widget3D
|
||||
{
|
||||
public:
|
||||
WArrow(const Point3f& pt1, const Point3f& pt2, double thickness = 0.03, const Color &color = Color::white());
|
||||
WArrow(const Point3f& pt1, const Point3f& pt2, float thickness = 0.03f, const Color &color = Color::white());
|
||||
};
|
||||
|
||||
class CV_EXPORTS WCircle : public Widget3D
|
||||
{
|
||||
public:
|
||||
WCircle(const Point3f& pt, double radius, double thickness = 0.01, const Color &color = Color::white());
|
||||
WCircle(const Point3f& pt, float radius, float thickness = 0.01f, const Color &color = Color::white());
|
||||
};
|
||||
|
||||
class CV_EXPORTS WCylinder : public Widget3D
|
||||
{
|
||||
public:
|
||||
WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides = 30, const Color &color = Color::white());
|
||||
WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides = 30, const Color &color = Color::white());
|
||||
};
|
||||
|
||||
class CV_EXPORTS WCube : public Widget3D
|
||||
@ -182,7 +182,7 @@ namespace cv
|
||||
class CV_EXPORTS WCoordinateSystem : public Widget3D
|
||||
{
|
||||
public:
|
||||
WCoordinateSystem(double scale = 1.0);
|
||||
WCoordinateSystem(float scale = 1.f);
|
||||
};
|
||||
|
||||
class CV_EXPORTS WPolyLine : public Widget3D
|
||||
@ -210,7 +210,7 @@ namespace cv
|
||||
class CV_EXPORTS WText3D : public Widget3D
|
||||
{
|
||||
public:
|
||||
WText3D(const String &text, const Point3f &position, double text_scale = 1.0, bool face_camera = true, const Color &color = Color::white());
|
||||
WText3D(const String &text, const Point3f &position, float text_scale = 1.f, bool face_camera = true, const Color &color = Color::white());
|
||||
|
||||
void setText(const String &text);
|
||||
String getText() const;
|
||||
@ -248,15 +248,15 @@ namespace cv
|
||||
{
|
||||
public:
|
||||
//! Creates camera coordinate frame (axes) at the origin
|
||||
WCameraPosition(double scale = 1.0);
|
||||
WCameraPosition(float scale = 1.f);
|
||||
//! Creates frustum based on the intrinsic marix K at the origin
|
||||
WCameraPosition(const Matx33f &K, double scale = 1.0, const Color &color = Color::white());
|
||||
WCameraPosition(const Matx33f &K, float scale = 1.f, const Color &color = Color::white());
|
||||
//! Creates frustum based on the field of view at the origin
|
||||
WCameraPosition(const Vec2f &fov, double scale = 1.0, const Color &color = Color::white());
|
||||
WCameraPosition(const Vec2f &fov, float scale = 1.f, const Color &color = Color::white());
|
||||
//! Creates frustum and display given image at the far plane
|
||||
WCameraPosition(const Matx33f &K, const Mat &img, double scale = 1.0, const Color &color = Color::white());
|
||||
WCameraPosition(const Matx33f &K, const Mat &img, float scale = 1.f, const Color &color = Color::white());
|
||||
//! Creates frustum and display given image at the far plane
|
||||
WCameraPosition(const Vec2f &fov, const Mat &img, double scale = 1.0, const Color &color = Color::white());
|
||||
WCameraPosition(const Vec2f &fov, const Mat &img, float scale = 1.f, const Color &color = Color::white());
|
||||
|
||||
private:
|
||||
struct ProjectImage;
|
||||
@ -268,11 +268,11 @@ namespace cv
|
||||
enum {DISPLAY_FRAMES = 1, DISPLAY_PATH = 2};
|
||||
|
||||
//! Displays trajectory of the given path either by coordinate frames or polyline
|
||||
WTrajectory(const std::vector<Affine3f> &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), double scale = 1.0);
|
||||
WTrajectory(const std::vector<Affine3f> &path, int display_mode = WTrajectory::DISPLAY_PATH, const Color &color = Color::white(), float scale = 1.f);
|
||||
//! Displays trajectory of the given path by frustums
|
||||
WTrajectory(const std::vector<Affine3f> &path, const Matx33f &K, double scale = 1.0, const Color &color = Color::white());
|
||||
WTrajectory(const std::vector<Affine3f> &path, const Matx33f &K, float scale = 1.f, const Color &color = Color::white());
|
||||
//! Displays trajectory of the given path by frustums
|
||||
WTrajectory(const std::vector<Affine3f> &path, const Vec2f &fov, double scale = 1.0, const Color &color = Color::white());
|
||||
WTrajectory(const std::vector<Affine3f> &path, const Vec2f &fov, float scale = 1.f, const Color &color = Color::white());
|
||||
|
||||
private:
|
||||
struct ApplyPath;
|
||||
@ -281,8 +281,8 @@ namespace cv
|
||||
class CV_EXPORTS WSpheresTrajectory: public Widget3D
|
||||
{
|
||||
public:
|
||||
WSpheresTrajectory(const std::vector<Affine3f> &path, float line_length = 0.05f, double init_sphere_radius = 0.021,
|
||||
double sphere_radius = 0.007, const Color &line_color = Color::white(), const Color &sphere_color = Color::white());
|
||||
WSpheresTrajectory(const std::vector<Affine3f> &path, float line_length = 0.05f, float init_sphere_radius = 0.021f,
|
||||
float sphere_radius = 0.007f, const Color &line_color = Color::white(), const Color &sphere_color = Color::white());
|
||||
};
|
||||
|
||||
class CV_EXPORTS WCloud: public Widget3D
|
||||
|
@ -54,14 +54,6 @@
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#if defined __GNUC__
|
||||
#pragma GCC system_header
|
||||
#ifdef __DEPRECATED
|
||||
#undef __DEPRECATED
|
||||
#define __DEPRECATED_DISABLED__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <vtkAppendPolyData.h>
|
||||
#include <vtkAssemblyPath.h>
|
||||
#include <vtkCellData.h>
|
||||
@ -70,7 +62,6 @@
|
||||
#include <vtkSmartPointer.h>
|
||||
#include <vtkDataSet.h>
|
||||
#include <vtkPolygon.h>
|
||||
#include <vtkPointPicker.h>
|
||||
#include <vtkUnstructuredGrid.h>
|
||||
#include <vtkDiskSource.h>
|
||||
#include <vtkPlaneSource.h>
|
||||
@ -105,7 +96,6 @@
|
||||
#include <vtkCamera.h>
|
||||
#include <vtkObjectFactory.h>
|
||||
#include <vtkPlanes.h>
|
||||
#include <vtkImageViewer.h>
|
||||
#include <vtkImageFlip.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
#include <vtkTextProperty.h>
|
||||
@ -119,11 +109,7 @@
|
||||
#include <vtkTextureMapToPlane.h>
|
||||
#include <vtkPolyDataNormals.h>
|
||||
#include <vtkAlgorithmOutput.h>
|
||||
|
||||
#if defined __GNUC__ && defined __DEPRECATED_DISABLED__
|
||||
#define __DEPRECATED
|
||||
#undef __DEPRECATED_DISABLED__
|
||||
#endif
|
||||
#include <vtkImageMapper.h>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/viz.hpp>
|
||||
@ -135,20 +121,34 @@ namespace cv
|
||||
namespace viz
|
||||
{
|
||||
typedef std::map<String, vtkSmartPointer<vtkProp> > WidgetActorMap;
|
||||
}
|
||||
}
|
||||
|
||||
#include "interactor_style.h"
|
||||
#include "viz3d_impl.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace viz
|
||||
{
|
||||
typedef std::map<String, Viz3d> VizMap;
|
||||
typedef std::pair<String, Viz3d> VizPair;
|
||||
|
||||
class VizStorage
|
||||
{
|
||||
public:
|
||||
static void unregisterAll();
|
||||
|
||||
//! window names automatically have Viz - prefix even though not provided by the users
|
||||
static String generateWindowName(const String &window_name);
|
||||
|
||||
private:
|
||||
VizStorage(); // Static
|
||||
~VizStorage();
|
||||
|
||||
static void add(const Viz3d& window);
|
||||
static Viz3d& get(const String &window_name);
|
||||
static void remove(const String &window_name);
|
||||
static bool windowExists(const String &window_name);
|
||||
static void removeUnreferenced();
|
||||
|
||||
static VizMap storage;
|
||||
friend class Viz3d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#include "interactor_style.hpp"
|
||||
#include "viz3d_impl.hpp"
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -104,7 +104,7 @@ struct cv::viz::WPlane::SetSizeImpl
|
||||
}
|
||||
};
|
||||
|
||||
cv::viz::WPlane::WPlane(const Vec4f& coefs, double size, const Color &color)
|
||||
cv::viz::WPlane::WPlane(const Vec4f& coefs, float size, const Color &color)
|
||||
{
|
||||
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();
|
||||
plane->SetNormal(coefs[0], coefs[1], coefs[2]);
|
||||
@ -124,7 +124,7 @@ cv::viz::WPlane::WPlane(const Vec4f& coefs, double size, const Color &color)
|
||||
setColor(color);
|
||||
}
|
||||
|
||||
cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, double size, const Color &color)
|
||||
cv::viz::WPlane::WPlane(const Vec4f& coefs, const Point3f& pt, float size, const Color &color)
|
||||
{
|
||||
vtkSmartPointer<vtkPlaneSource> plane = vtkSmartPointer<vtkPlaneSource>::New();
|
||||
Point3f coefs3(coefs[0], coefs[1], coefs[2]);
|
||||
@ -183,7 +183,7 @@ template<> cv::viz::WSphere cv::viz::Widget::cast<cv::viz::WSphere>()
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// arrow widget implementation
|
||||
|
||||
cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, double thickness, const Color &color)
|
||||
cv::viz::WArrow::WArrow(const Point3f& pt1, const Point3f& pt2, float thickness, const Color &color)
|
||||
{
|
||||
vtkSmartPointer<vtkArrowSource> arrowSource = vtkSmartPointer<vtkArrowSource>::New();
|
||||
arrowSource->SetShaftRadius(thickness);
|
||||
@ -256,7 +256,7 @@ template<> cv::viz::WArrow cv::viz::Widget::cast<cv::viz::WArrow>()
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// circle widget implementation
|
||||
|
||||
cv::viz::WCircle::WCircle(const Point3f& pt, double radius, double thickness, const Color& color)
|
||||
cv::viz::WCircle::WCircle(const Point3f& pt, float radius, float thickness, const Color& color)
|
||||
{
|
||||
vtkSmartPointer<vtkDiskSource> disk = vtkSmartPointer<vtkDiskSource>::New();
|
||||
// Maybe the resolution should be lower e.g. 50 or 25
|
||||
@ -292,7 +292,7 @@ template<> cv::viz::WCircle cv::viz::Widget::cast<cv::viz::WCircle>()
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// cylinder widget implementation
|
||||
|
||||
cv::viz::WCylinder::WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, double radius, int numsides, const Color &color)
|
||||
cv::viz::WCylinder::WCylinder(const Point3f& pt_on_axis, const Point3f& axis_direction, float radius, int numsides, const Color &color)
|
||||
{
|
||||
const Point3f pt2 = pt_on_axis + axis_direction;
|
||||
vtkSmartPointer<vtkLineSource> line = vtkSmartPointer<vtkLineSource>::New();
|
||||
@ -355,7 +355,7 @@ template<> cv::viz::WCube cv::viz::Widget::cast<cv::viz::WCube>()
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// coordinate system widget implementation
|
||||
|
||||
cv::viz::WCoordinateSystem::WCoordinateSystem(double scale)
|
||||
cv::viz::WCoordinateSystem::WCoordinateSystem(float scale)
|
||||
{
|
||||
vtkSmartPointer<vtkAxes> axes = vtkSmartPointer<vtkAxes>::New();
|
||||
axes->SetOrigin(0, 0, 0);
|
||||
@ -593,7 +593,7 @@ template<> cv::viz::WGrid cv::viz::Widget::cast<cv::viz::WGrid>()
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// text3D widget implementation
|
||||
|
||||
cv::viz::WText3D::WText3D(const String &text, const Point3f &position, double text_scale, bool face_camera, const Color &color)
|
||||
cv::viz::WText3D::WText3D(const String &text, const Point3f &position, float text_scale, bool face_camera, const Color &color)
|
||||
{
|
||||
vtkSmartPointer<vtkVectorText> textSource = vtkSmartPointer<vtkVectorText>::New();
|
||||
textSource->SetText(text.c_str());
|
||||
@ -1032,7 +1032,7 @@ struct cv::viz::WCameraPosition::ProjectImage
|
||||
}
|
||||
};
|
||||
|
||||
cv::viz::WCameraPosition::WCameraPosition(double scale)
|
||||
cv::viz::WCameraPosition::WCameraPosition(float scale)
|
||||
{
|
||||
vtkSmartPointer<vtkAxes> axes = vtkSmartPointer<vtkAxes>::New();
|
||||
axes->SetOrigin(0, 0, 0);
|
||||
@ -1074,7 +1074,7 @@ cv::viz::WCameraPosition::WCameraPosition(double scale)
|
||||
WidgetAccessor::setProp(*this, actor);
|
||||
}
|
||||
|
||||
cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, double scale, const Color &color)
|
||||
cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, float scale, const Color &color)
|
||||
{
|
||||
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
|
||||
float f_x = K(0,0);
|
||||
@ -1116,7 +1116,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, double scale, const
|
||||
}
|
||||
|
||||
|
||||
cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, double scale, const Color &color)
|
||||
cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, float scale, const Color &color)
|
||||
{
|
||||
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
|
||||
|
||||
@ -1154,7 +1154,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, double scale, const
|
||||
setColor(color);
|
||||
}
|
||||
|
||||
cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, const Mat &image, double scale, const Color &color)
|
||||
cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, const Mat &image, float scale, const Color &color)
|
||||
{
|
||||
CV_Assert(!image.empty() && image.depth() == CV_8U);
|
||||
float f_y = K(1,1);
|
||||
@ -1168,7 +1168,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33f &K, const Mat &image, do
|
||||
WidgetAccessor::setProp(*this, actor);
|
||||
}
|
||||
|
||||
cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, const Mat &image, double scale, const Color &color)
|
||||
cv::viz::WCameraPosition::WCameraPosition(const Vec2f &fov, const Mat &image, float scale, const Color &color)
|
||||
{
|
||||
CV_Assert(!image.empty() && image.depth() == CV_8U);
|
||||
float fovy = fov[1] * 180.0f / CV_PI;
|
||||
@ -1220,7 +1220,7 @@ struct cv::viz::WTrajectory::ApplyPath
|
||||
}
|
||||
};
|
||||
|
||||
cv::viz::WTrajectory::WTrajectory(const std::vector<Affine3f> &path, int display_mode, const Color &color, double scale)
|
||||
cv::viz::WTrajectory::WTrajectory(const std::vector<Affine3f> &path, int display_mode, const Color &color, float scale)
|
||||
{
|
||||
vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();
|
||||
|
||||
@ -1316,7 +1316,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector<Affine3f> &path, int display
|
||||
WidgetAccessor::setProp(*this, actor);
|
||||
}
|
||||
|
||||
cv::viz::WTrajectory::WTrajectory(const std::vector<Affine3f> &path, const Matx33f &K, double scale, const Color &color)
|
||||
cv::viz::WTrajectory::WTrajectory(const std::vector<Affine3f> &path, const Matx33f &K, float scale, const Color &color)
|
||||
{
|
||||
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
|
||||
float f_x = K(0,0);
|
||||
@ -1360,7 +1360,7 @@ cv::viz::WTrajectory::WTrajectory(const std::vector<Affine3f> &path, const Matx3
|
||||
setColor(color);
|
||||
}
|
||||
|
||||
cv::viz::WTrajectory::WTrajectory(const std::vector<Affine3f> &path, const Vec2f &fov, double scale, const Color &color)
|
||||
cv::viz::WTrajectory::WTrajectory(const std::vector<Affine3f> &path, const Vec2f &fov, float scale, const Color &color)
|
||||
{
|
||||
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
|
||||
|
||||
@ -1409,7 +1409,7 @@ template<> cv::viz::WTrajectory cv::viz::Widget::cast<cv::viz::WTrajectory>()
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// spheres trajectory widget implementation
|
||||
|
||||
cv::viz::WSpheresTrajectory::WSpheresTrajectory(const std::vector<Affine3f> &path, float line_length, double init_sphere_radius, double sphere_radius,
|
||||
cv::viz::WSpheresTrajectory::WSpheresTrajectory(const std::vector<Affine3f> &path, float line_length, float init_sphere_radius, float sphere_radius,
|
||||
const Color &line_color, const Color &sphere_color)
|
||||
{
|
||||
vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();
|
||||
|
@ -107,70 +107,48 @@ namespace cv { namespace viz
|
||||
}}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Viz accessor implementation
|
||||
/// VizStorage implementation
|
||||
|
||||
cv::viz::VizAccessor * cv::viz::VizAccessor::instance_ = 0;
|
||||
cv::viz::VizMap cv::viz::VizStorage::storage;
|
||||
void cv::viz::VizStorage::unregisterAll() { storage.clear(); }
|
||||
|
||||
struct cv::viz::VizAccessor::VizAccessorImpl
|
||||
cv::viz::Viz3d& cv::viz::VizStorage::get(const String &window_name)
|
||||
{
|
||||
cv::viz::VizMap viz_map;
|
||||
};
|
||||
|
||||
cv::viz::VizAccessor::VizAccessor() { impl_ = new cv::viz::VizAccessor::VizAccessorImpl;}
|
||||
cv::viz::VizAccessor::~VizAccessor() { delete impl_; }
|
||||
|
||||
cv::viz::VizAccessor & cv::viz::VizAccessor::getInstance()
|
||||
{
|
||||
if (!instance_)
|
||||
instance_ = new VizAccessor();
|
||||
|
||||
return *instance_;
|
||||
String name = generateWindowName(window_name);
|
||||
VizMap::iterator vm_itr = storage.find(name);
|
||||
CV_Assert(vm_itr != storage.end());
|
||||
return vm_itr->second;
|
||||
}
|
||||
|
||||
void cv::viz::VizAccessor::release()
|
||||
{
|
||||
if (instance_)
|
||||
{
|
||||
delete instance_;
|
||||
instance_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cv::viz::Viz3d cv::viz::VizAccessor::get(const String & window_name)
|
||||
{
|
||||
// Add the prefix Viz
|
||||
String name;
|
||||
generateWindowName(window_name, name);
|
||||
|
||||
VizMap::iterator vm_itr = impl_->viz_map.find(name);
|
||||
return vm_itr != impl_->viz_map.end() ? vm_itr->second : Viz3d(window_name);
|
||||
}
|
||||
|
||||
void cv::viz::VizAccessor::add(Viz3d window)
|
||||
void cv::viz::VizStorage::add(const Viz3d& window)
|
||||
{
|
||||
String window_name = window.getWindowName();
|
||||
VizMap::iterator vm_itr = impl_->viz_map.find(window_name);
|
||||
if (vm_itr == impl_->viz_map.end())
|
||||
impl_->viz_map.insert(VizPair(window_name, window));
|
||||
VizMap::iterator vm_itr = storage.find(window_name);
|
||||
CV_Assert(vm_itr == storage.end());
|
||||
storage.insert(std::make_pair(window_name, window));
|
||||
}
|
||||
|
||||
void cv::viz::VizAccessor::remove(const String &window_name)
|
||||
bool cv::viz::VizStorage::windowExists(const String &window_name)
|
||||
{
|
||||
// Add the prefix Viz
|
||||
String name;
|
||||
generateWindowName(window_name, name);
|
||||
|
||||
VizMap::iterator vm_itr = impl_->viz_map.find(name);
|
||||
if (vm_itr != impl_->viz_map.end())
|
||||
impl_->viz_map.erase(vm_itr);
|
||||
String name = generateWindowName(window_name);
|
||||
return storage.find(name) != storage.end();
|
||||
}
|
||||
|
||||
void cv::viz::VizAccessor::generateWindowName(const String &window_name, String &output)
|
||||
void cv::viz::VizStorage::removeUnreferenced()
|
||||
{
|
||||
output = "Viz";
|
||||
for(VizMap::iterator pos = storage.begin(); pos != storage.end();)
|
||||
if(pos->second.impl_->ref_counter == 1)
|
||||
storage.erase(pos++);
|
||||
else
|
||||
++pos;
|
||||
}
|
||||
|
||||
cv::String cv::viz::VizStorage::generateWindowName(const String &window_name)
|
||||
{
|
||||
String output = "Viz";
|
||||
// Already is Viz
|
||||
if (window_name == output)
|
||||
return;
|
||||
return output;
|
||||
|
||||
String prefixed = output + " - ";
|
||||
if (window_name.substr(0, prefixed.length()) == prefixed)
|
||||
@ -179,9 +157,9 @@ void cv::viz::VizAccessor::generateWindowName(const String &window_name, String
|
||||
output = prefixed + window_name; // Doesn't have prefix
|
||||
else
|
||||
output = (window_name == "" ? output : prefixed + window_name);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
cv::viz::Viz3d cv::viz::get(const String &window_name)
|
||||
{
|
||||
return cv::viz::VizAccessor::getInstance().get(window_name);
|
||||
}
|
||||
cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d (window_name); }
|
||||
void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); }
|
||||
|
@ -52,7 +52,8 @@ cv::viz::Viz3d::Viz3d(const String& window_name) : impl_(0) { create(window_name
|
||||
|
||||
cv::viz::Viz3d::Viz3d(const Viz3d& other) : impl_(other.impl_)
|
||||
{
|
||||
if (impl_) CV_XADD(&impl_->ref_counter, 1);
|
||||
if (impl_)
|
||||
CV_XADD(&impl_->ref_counter, 1);
|
||||
}
|
||||
|
||||
cv::viz::Viz3d& cv::viz::Viz3d::operator=(const Viz3d& other)
|
||||
@ -61,7 +62,8 @@ cv::viz::Viz3d& cv::viz::Viz3d::operator=(const Viz3d& other)
|
||||
{
|
||||
release();
|
||||
impl_ = other.impl_;
|
||||
if (impl_) CV_XADD(&impl_->ref_counter, 1);
|
||||
if (impl_)
|
||||
CV_XADD(&impl_->ref_counter, 1);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@ -70,24 +72,33 @@ cv::viz::Viz3d::~Viz3d() { release(); }
|
||||
|
||||
void cv::viz::Viz3d::create(const String &window_name)
|
||||
{
|
||||
if (impl_) release();
|
||||
impl_ = new VizImpl(window_name);
|
||||
impl_->ref_counter = 1;
|
||||
// Register the window
|
||||
cv::viz::VizAccessor::getInstance().add(*this);
|
||||
if (impl_)
|
||||
release();
|
||||
|
||||
if (VizStorage::windowExists(window_name))
|
||||
*this = VizStorage::get(window_name);
|
||||
else
|
||||
{
|
||||
impl_ = new VizImpl(window_name);
|
||||
impl_->ref_counter = 1;
|
||||
|
||||
// Register the window
|
||||
VizStorage::add(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void cv::viz::Viz3d::release()
|
||||
{
|
||||
// If the current referene count is equal to 2, we can delete it
|
||||
// - 2 : because minimum there will be two instances, one of which is in the map
|
||||
if (impl_ && CV_XADD(&impl_->ref_counter, -1) == 2)
|
||||
if (impl_ && CV_XADD(&impl_->ref_counter, -1) == 1)
|
||||
{
|
||||
// Erase the window
|
||||
cv::viz::VizAccessor::getInstance().remove(getWindowName());
|
||||
delete impl_;
|
||||
impl_ = 0;
|
||||
}
|
||||
|
||||
if (impl_ && impl_->ref_counter == 1)
|
||||
VizStorage::removeUnreferenced();
|
||||
|
||||
impl_ = 0;
|
||||
}
|
||||
|
||||
void cv::viz::Viz3d::spin() { impl_->spin(); }
|
||||
|
@ -48,6 +48,8 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew();
|
||||
|
||||
#if 1 || !defined __APPLE__
|
||||
vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew()
|
||||
{
|
||||
@ -57,7 +59,7 @@ vtkRenderWindowInteractor* vtkRenderWindowInteractorFixNew()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
cv::viz::Viz3d::VizImpl::VizImpl(const String &name)
|
||||
: style_(vtkSmartPointer<cv::viz::InteractorStyle>::New()) , widget_actor_map_(new WidgetActorMap), s_lastDone_(0.0)
|
||||
: s_lastDone_(0.0), style_(vtkSmartPointer<cv::viz::InteractorStyle>::New()), widget_actor_map_(new WidgetActorMap)
|
||||
{
|
||||
renderer_ = vtkSmartPointer<vtkRenderer>::New();
|
||||
|
||||
@ -77,7 +79,7 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name)
|
||||
style_->UseTimersOn();
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
interactor_ = vtkSmartPointer <vtkRenderWindowInteractor>::Take(vtkRenderWindowInteractorFixNew());
|
||||
interactor_ = vtkSmartPointer<vtkRenderWindowInteractor>::Take(vtkRenderWindowInteractorFixNew());
|
||||
|
||||
window_->AlphaBitPlanesOff();
|
||||
window_->PointSmoothingOff();
|
||||
@ -95,9 +97,9 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name)
|
||||
timer_id_ = interactor_->CreateRepeatingTimer(5000L);
|
||||
|
||||
// Set a simple PointPicker
|
||||
vtkSmartPointer<vtkPointPicker> pp = vtkSmartPointer<vtkPointPicker>::New();
|
||||
pp->SetTolerance(pp->GetTolerance() * 2);
|
||||
interactor_->SetPicker(pp);
|
||||
//vtkSmartPointer<vtkPointPicker> pp = vtkSmartPointer<vtkPointPicker>::New();
|
||||
//pp->SetTolerance(pp->GetTolerance() * 2);
|
||||
//interactor_->SetPicker(pp);
|
||||
|
||||
exit_main_loop_timer_callback_ = vtkSmartPointer<ExitMainLoopTimerCallback>::New();
|
||||
exit_main_loop_timer_callback_->viz_ = this;
|
||||
@ -112,8 +114,7 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name)
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
String window_name;
|
||||
VizAccessor::generateWindowName(name, window_name);
|
||||
String window_name = VizStorage::generateWindowName(name);
|
||||
window_->SetWindowName(window_name.c_str());
|
||||
}
|
||||
|
||||
@ -314,45 +315,6 @@ bool cv::viz::Viz3d::VizImpl::removeActorFromRenderer(const vtkSmartPointer<vtkP
|
||||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void cv::viz::Viz3d::VizImpl::createActorFromVTKDataSet(const vtkSmartPointer<vtkDataSet> &data, vtkSmartPointer<vtkLODActor> &actor, bool use_scalars)
|
||||
{
|
||||
if (!actor)
|
||||
actor = vtkSmartPointer<vtkLODActor>::New();
|
||||
|
||||
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New();
|
||||
#if VTK_MAJOR_VERSION <= 5
|
||||
mapper->SetInput(data);
|
||||
#else
|
||||
mapper->SetInputData(data);
|
||||
#endif
|
||||
|
||||
if (use_scalars)
|
||||
{
|
||||
vtkSmartPointer<vtkDataArray> scalars = data->GetPointData()->GetScalars();
|
||||
if (scalars)
|
||||
{
|
||||
cv::Vec3d minmax(scalars->GetRange());
|
||||
mapper->SetScalarRange(minmax.val);
|
||||
mapper->SetScalarModeToUsePointData();
|
||||
|
||||
// interpolation OFF, if data is a vtkPolyData that contains only vertices, ON for anything else.
|
||||
vtkPolyData* polyData = vtkPolyData::SafeDownCast(data);
|
||||
bool interpolation = (polyData && polyData->GetNumberOfCells() != polyData->GetNumberOfVerts());
|
||||
|
||||
mapper->SetInterpolateScalarsBeforeMapping(interpolation);
|
||||
mapper->ScalarVisibilityOn();
|
||||
}
|
||||
}
|
||||
mapper->ImmediateModeRenderingOff();
|
||||
|
||||
actor->SetNumberOfCloudPoints(int(std::max<vtkIdType>(1, data->GetNumberOfPoints() / 10)));
|
||||
actor->GetProperty()->SetInterpolationToFlat();
|
||||
actor->GetProperty()->BackfaceCullingOn();
|
||||
|
||||
actor->SetMapper(mapper);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void cv::viz::Viz3d::VizImpl::setBackgroundColor(const Color& color)
|
||||
{
|
||||
@ -542,48 +504,6 @@ void cv::viz::Viz3d::VizImpl::setRepresentation(int representation)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void cv::viz::Viz3d::VizImpl::updateCells(vtkSmartPointer<vtkIdTypeArray> &cells, vtkSmartPointer<vtkIdTypeArray> &initcells, vtkIdType nr_points)
|
||||
{
|
||||
// If no init cells and cells has not been initialized...
|
||||
if (!cells)
|
||||
cells = vtkSmartPointer<vtkIdTypeArray>::New();
|
||||
|
||||
// If we have less values then we need to recreate the array
|
||||
if (cells->GetNumberOfTuples() < nr_points)
|
||||
{
|
||||
cells = vtkSmartPointer<vtkIdTypeArray>::New();
|
||||
|
||||
// If init cells is given, and there's enough data in it, use it
|
||||
if (initcells && initcells->GetNumberOfTuples() >= nr_points)
|
||||
{
|
||||
cells->DeepCopy(initcells);
|
||||
cells->SetNumberOfComponents(2);
|
||||
cells->SetNumberOfTuples(nr_points);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the number of tuples is still too small, we need to recreate the array
|
||||
cells->SetNumberOfComponents(2);
|
||||
cells->SetNumberOfTuples(nr_points);
|
||||
vtkIdType *cell = cells->GetPointer(0);
|
||||
// Fill it with 1s
|
||||
std::fill_n(cell, nr_points * 2, 1);
|
||||
cell++;
|
||||
for (vtkIdType i = 0; i < nr_points; ++i, cell += 2)
|
||||
*cell = i;
|
||||
// Save the results in initcells
|
||||
initcells = vtkSmartPointer<vtkIdTypeArray>::New();
|
||||
initcells->DeepCopy(cells);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The assumption here is that the current set of cells has more data than needed
|
||||
cells->SetNumberOfComponents(2);
|
||||
cells->SetNumberOfTuples(nr_points);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void cv::viz::Viz3d::VizImpl::setFullScreen(bool mode)
|
||||
|
@ -52,7 +52,6 @@
|
||||
struct cv::viz::Viz3d::VizImpl
|
||||
{
|
||||
public:
|
||||
typedef cv::Ptr<VizImpl> Ptr;
|
||||
typedef Viz3d::KeyboardCallback KeyboardCallback;
|
||||
typedef Viz3d::MouseCallback MouseCallback;
|
||||
|
||||
@ -181,9 +180,6 @@ private:
|
||||
bool camera_set_;
|
||||
|
||||
bool removeActorFromRenderer(const vtkSmartPointer<vtkProp> &actor);
|
||||
|
||||
void createActorFromVTKDataSet(const vtkSmartPointer<vtkDataSet> &data, vtkSmartPointer<vtkLODActor> &actor, bool use_scalars = true);
|
||||
void updateCells(vtkSmartPointer<vtkIdTypeArray> &cells, vtkSmartPointer<vtkIdTypeArray> &initcells, vtkIdType nr_points);
|
||||
};
|
||||
|
||||
|
||||
|
54
modules/viz/test/test_tutorial2.cpp
Normal file
54
modules/viz/test/test_tutorial2.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
void tutorial2()
|
||||
{
|
||||
/// Create a window
|
||||
viz::Viz3d myWindow("Coordinate Frame");
|
||||
|
||||
/// Add coordinate axes
|
||||
myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem());
|
||||
|
||||
/// Add line to represent (1,1,1) axis
|
||||
viz::WLine axis(Point3f(-1.0f,-1.0f,-1.0f), Point3f(1.0f,1.0f,1.0f));
|
||||
axis.setRenderingProperty(viz::LINE_WIDTH, 4.0);
|
||||
myWindow.showWidget("Line Widget", axis);
|
||||
|
||||
/// Construct a cube widget
|
||||
viz::WCube cube_widget(Point3f(0.5,0.5,0.0), Point3f(0.0,0.0,-0.5), true, viz::Color::blue());
|
||||
cube_widget.setRenderingProperty(viz::LINE_WIDTH, 4.0);
|
||||
|
||||
/// Display widget (update if already displayed)
|
||||
myWindow.showWidget("Cube Widget", cube_widget);
|
||||
|
||||
/// Rodrigues vector
|
||||
Mat rot_vec = Mat::zeros(1,3,CV_32F);
|
||||
float translation_phase = 0.0, translation = 0.0;
|
||||
while(!myWindow.wasStopped())
|
||||
{
|
||||
/* Rotation using rodrigues */
|
||||
/// Rotate around (1,1,1)
|
||||
rot_vec.at<float>(0,0) += CV_PI * 0.01f;
|
||||
rot_vec.at<float>(0,1) += CV_PI * 0.01f;
|
||||
rot_vec.at<float>(0,2) += CV_PI * 0.01f;
|
||||
|
||||
/// Shift on (1,1,1)
|
||||
translation_phase += CV_PI * 0.01f;
|
||||
translation = sin(translation_phase);
|
||||
|
||||
/// Construct pose
|
||||
Affine3f pose(rot_vec, Vec3f(translation, translation, translation));
|
||||
|
||||
myWindow.setWidgetPose("Cube Widget", pose);
|
||||
|
||||
myWindow.spinOnce(1, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Viz_viz3d, DISABLED_tutorial2_pose_of_widget)
|
||||
{
|
||||
tutorial2();
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.opencv.engine"
|
||||
android:versionCode="214@ANDROID_PLATFORM_VERSION_CODE@"
|
||||
android:versionName="2.14" >
|
||||
android:versionCode="216@ANDROID_PLATFORM_VERSION_CODE@"
|
||||
android:versionName="2.16" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="@ANDROID_NATIVE_API_LEVEL@" />
|
||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
|
||||
|
@ -170,7 +170,7 @@ inline string JoinPlatform(int platform)
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int SplitPlatfrom(const vector<string>& features)
|
||||
inline int SplitPlatform(const vector<string>& features)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
@ -419,7 +419,7 @@ InstallPath(install_path)
|
||||
return;
|
||||
}
|
||||
|
||||
Platform = SplitPlatfrom(features);
|
||||
Platform = SplitPlatform(features);
|
||||
if (PLATFORM_UNKNOWN != Platform)
|
||||
{
|
||||
switch (Platform)
|
||||
|
@ -170,7 +170,7 @@ TEST(CpuID, CheckVFPv3)
|
||||
EXPECT_TRUE(cpu_id & FEATURES_HAS_VFPv3);
|
||||
}
|
||||
|
||||
TEST(PlatfromDetector, CheckTegra)
|
||||
TEST(PlatformDetector, CheckTegra)
|
||||
{
|
||||
EXPECT_NE(PLATFORM_UNKNOWN, DetectKnownPlatforms());
|
||||
}
|
||||
|
@ -90,28 +90,28 @@ public class ManagerActivity extends Activity
|
||||
mInstalledPackageView.setAdapter(mInstalledPacksAdapter);
|
||||
|
||||
TextView HardwarePlatformView = (TextView)findViewById(R.id.HardwareValue);
|
||||
int Platfrom = HardwareDetector.DetectKnownPlatforms();
|
||||
int Platform = HardwareDetector.DetectKnownPlatforms();
|
||||
int CpuId = HardwareDetector.GetCpuID();
|
||||
|
||||
if (HardwareDetector.PLATFORM_UNKNOWN != Platfrom)
|
||||
if (HardwareDetector.PLATFORM_UNKNOWN != Platform)
|
||||
{
|
||||
if (HardwareDetector.PLATFORM_TEGRA == Platfrom)
|
||||
if (HardwareDetector.PLATFORM_TEGRA == Platform)
|
||||
{
|
||||
HardwarePlatformView.setText("Tegra");
|
||||
}
|
||||
else if (HardwareDetector.PLATFORM_TEGRA2 == Platfrom)
|
||||
else if (HardwareDetector.PLATFORM_TEGRA2 == Platform)
|
||||
{
|
||||
HardwarePlatformView.setText("Tegra 2");
|
||||
}
|
||||
else if (HardwareDetector.PLATFORM_TEGRA3 == Platfrom)
|
||||
else if (HardwareDetector.PLATFORM_TEGRA3 == Platform)
|
||||
{
|
||||
HardwarePlatformView.setText("Tegra 3");
|
||||
}
|
||||
else if (HardwareDetector.PLATFORM_TEGRA4i == Platfrom)
|
||||
else if (HardwareDetector.PLATFORM_TEGRA4i == Platform)
|
||||
{
|
||||
HardwarePlatformView.setText("Tegra 4i");
|
||||
}
|
||||
else if (HardwareDetector.PLATFORM_TEGRA4 == Platfrom)
|
||||
else if (HardwareDetector.PLATFORM_TEGRA4 == Platform)
|
||||
{
|
||||
HardwarePlatformView.setText("Tegra 4");
|
||||
}
|
||||
|
@ -14,20 +14,20 @@ manually using adb tool:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
adb install OpenCV-2.4.7-android-sdk/apk/OpenCV_2.4.7_Manager_2.14_<platform>.apk
|
||||
adb install OpenCV-2.4.7.1-android-sdk/apk/OpenCV_2.4.7.1_Manager_2.15_<platform>.apk
|
||||
|
||||
Use the table below to determine proper OpenCV Manager package for your device:
|
||||
|
||||
+------------------------------+--------------+----------------------------------------------------+
|
||||
| Hardware Platform | Android ver. | Package name |
|
||||
+==============================+==============+====================================================+
|
||||
| armeabi-v7a (ARMv7-A + NEON) | >= 2.3 | OpenCV_2.4.7_Manager_2.14_armv7a-neon.apk |
|
||||
+------------------------------+--------------+----------------------------------------------------+
|
||||
| armeabi-v7a (ARMv7-A + NEON) | = 2.2 | OpenCV_2.4.7_Manager_2.14_armv7a-neon-android8.apk |
|
||||
+------------------------------+--------------+----------------------------------------------------+
|
||||
| armeabi (ARMv5, ARMv6) | >= 2.3 | OpenCV_2.4.7_Manager_2.14_armeabi.apk |
|
||||
+------------------------------+--------------+----------------------------------------------------+
|
||||
| Intel x86 | >= 2.3 | OpenCV_2.4.7_Manager_2.14_x86.apk |
|
||||
+------------------------------+--------------+----------------------------------------------------+
|
||||
| MIPS | >= 2.3 | OpenCV_2.4.7_Manager_2.14_mips.apk |
|
||||
+------------------------------+--------------+----------------------------------------------------+
|
||||
+------------------------------+--------------+------------------------------------------------------+
|
||||
| Hardware Platform | Android ver. | Package name |
|
||||
+==============================+==============+======================================================+
|
||||
| armeabi-v7a (ARMv7-A + NEON) | >= 2.3 | OpenCV_2.4.7.1_Manager_2.15_armv7a-neon.apk |
|
||||
+------------------------------+--------------+------------------------------------------------------+
|
||||
| armeabi-v7a (ARMv7-A + NEON) | = 2.2 | OpenCV_2.4.7.1_Manager_2.15_armv7a-neon-android8.apk |
|
||||
+------------------------------+--------------+------------------------------------------------------+
|
||||
| armeabi (ARMv5, ARMv6) | >= 2.3 | OpenCV_2.4.7.1_Manager_2.15_armeabi.apk |
|
||||
+------------------------------+--------------+------------------------------------------------------+
|
||||
| Intel x86 | >= 2.3 | OpenCV_2.4.7.1_Manager_2.15_x86.apk |
|
||||
+------------------------------+--------------+------------------------------------------------------+
|
||||
| MIPS | >= 2.3 | OpenCV_2.4.7.1_Manager_2.15_mips.apk |
|
||||
+------------------------------+--------------+------------------------------------------------------+
|
||||
|
@ -29,6 +29,10 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
|
||||
ocv_include_directories("${OpenCV_SOURCE_DIR}/modules/cudafilters/include")
|
||||
endif()
|
||||
|
||||
if(HAVE_opencv_ocl)
|
||||
ocv_include_directories("${OpenCV_SOURCE_DIR}/modules/ocl/include")
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX AND NOT ENABLE_NOISY_WARNINGS)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function")
|
||||
endif()
|
||||
@ -56,6 +60,10 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
|
||||
target_link_libraries(${the_target} opencv_cudaarithm opencv_cudafilters)
|
||||
endif()
|
||||
|
||||
if(HAVE_opencv_ocl)
|
||||
target_link_libraries(${the_target} opencv_ocl)
|
||||
endif()
|
||||
|
||||
set_target_properties(${the_target} PROPERTIES
|
||||
OUTPUT_NAME "cpp-${sample_kind}-${name}"
|
||||
PROJECT_LABEL "(${sample_KIND}) ${name}")
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user