Conflicts:
	modules/imgproc/src/sumpixels.cpp
This commit is contained in:
sprice 2013-12-11 14:35:51 -08:00
commit 1c15776cf5
107 changed files with 8675 additions and 1054 deletions

View File

@ -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> */

View File

@ -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("")

View File

@ -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;
}

View 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()

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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
{

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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));

View File

@ -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();

View File

@ -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();

View File

@ -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;

View File

@ -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); \

View 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];
}
}

View 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

View File

@ -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_*/

View File

@ -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 ||

View File

@ -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();
}

View File

@ -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

View 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

View File

@ -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:

View File

@ -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));

View File

@ -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, \

View File

@ -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
}

View File

@ -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{

View File

@ -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::

View File

@ -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

View 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));
}
}

View File

@ -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();

View File

@ -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 )

View 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);
}
}

View 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);
}
}
}

View 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
}
}

View 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

View 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

View File

@ -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;

View File

@ -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 );

View File

@ -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, &gt, &lt, 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, &gt2, &lt2, 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, &gt, &lt, 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, &gt2, &lt2, 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 );
}

View 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

View File

@ -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)

View 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

View 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

View File

@ -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(

View File

@ -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)
}
};

View File

@ -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);

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -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));
}

View File

@ -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;

View File

@ -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)

View File

@ -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];
}

View File

@ -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

View 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.

View 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
View 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.

View File

@ -9,4 +9,7 @@ photo. Computational Photography
inpainting
denoising
hdr_imaging
hdr_imaging
decolor
cloning
npr

View File

@ -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

View 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);
}

View 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
View 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
View 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);
}
}
}

View 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);
}

View 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);
}

View 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);
}

View 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
View 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);
}

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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.

View File

@ -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 */

View File

@ -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); }

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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(); }

View File

@ -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(); }

View File

@ -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)

View File

@ -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);
};

View 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();
}

View File

@ -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"/>

View File

@ -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)

View File

@ -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());
}

View File

@ -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");
}

View File

@ -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 |
+------------------------------+--------------+------------------------------------------------------+

View File

@ -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