diff --git a/cmake/OpenCVDetectVTK.cmake b/cmake/OpenCVDetectVTK.cmake index 78d1a73b69..2b55a9c3f1 100644 --- a/cmake/OpenCVDetectVTK.cmake +++ b/cmake/OpenCVDetectVTK.cmake @@ -2,25 +2,52 @@ if(NOT WITH_VTK OR ANDROID OR IOS) return() endif() -if (HAVE_QT5) - message(STATUS "VTK is disabled because OpenCV is linked with Q5. Some VTK disributives are compiled with Q4 and therefore can't be linked together Qt5.") +# VTK 6.x components +find_package(VTK QUIET COMPONENTS vtkRenderingOpenGL vtkInteractionStyle vtkRenderingLOD vtkIOPLY vtkFiltersTexture vtkRenderingFreeType vtkIOExport NO_MODULE) + +# VTK 5.x components +if(NOT VTK_FOUND) + find_package(VTK QUIET COMPONENTS vtkCommon NO_MODULE) +endif() + +if(NOT VTK_FOUND) + set(HAVE_VTK OFF) + message(STATUS "VTK is not found. Please set -DVTK_DIR in CMake to VTK build directory, or to VTK install subdirectory with VTKConfig.cmake file") return() endif() -find_package(VTK 6.0 QUIET COMPONENTS vtkRenderingCore vtkInteractionWidgets vtkInteractionStyle vtkIOLegacy vtkIOPLY vtkRenderingFreeType vtkRenderingLOD vtkFiltersTexture vtkIOExport NO_MODULE) +# Don't support ealier VTKs +if(${VTK_VERSION} VERSION_LESS "5.8.0") + message(STATUS "VTK support is disabled. VTK ver. 5.8.0 is minimum required, but found VTK ver. ${VTK_VERSION}") + return() +endif() -if(NOT DEFINED VTK_FOUND OR NOT VTK_FOUND) - find_package(VTK 5.10 QUIET COMPONENTS vtkCommon vtkFiltering vtkRendering vtkWidgets vtkImaging NO_MODULE) +# Different Qt versions can't be linked together +if(HAVE_QT5 AND ${VTK_VERSION} VERSION_LESS "6.0.0") + if(VTK_USE_QT) + message(STATUS "VTK support is disabled. Incompatible combination: OpenCV + Qt5 and VTK ver.${VTK_VERSION} + Qt4") + endif() endif() -if(NOT DEFINED VTK_FOUND OR NOT VTK_FOUND) - find_package(VTK 5.8 QUIET COMPONENTS vtkCommon vtkFiltering vtkRendering vtkWidgets vtkImaging NO_MODULE) +# Different Qt versions can't be linked together. VTK 6.0.0 doesn't provide a way to get Qt version it was linked with +if(HAVE_QT5 AND ${VTK_VERSION} VERSION_EQUAL "6.0.0" AND NOT DEFINED FORCE_VTK) + message(STATUS "VTK support is disabled. Possible incompatible combination: OpenCV+Qt5, and VTK ver.${VTK_VERSION} with Qt4") + message(STATUS "If it is known that VTK was compiled without Qt4, please define '-DFORCE_VTK=TRUE' flag in CMake") + return() 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)") +# Different Qt versions can't be linked together +if(HAVE_QT AND ${VTK_VERSION} VERSION_GREATER "6.0.0" AND NOT ${VTK_QT_VERSION} STREQUAL "") + if(HAVE_QT5 AND ${VTK_QT_VERSION} EQUAL "4") + message(STATUS "VTK support is disabled. Incompatible combination: OpenCV + Qt5 and VTK ver.${VTK_VERSION} + Qt4") + return() + endif() + + if(NOT HAVE_QT5 AND ${VTK_QT_VERSION} EQUAL "5") + message(STATUS "VTK support is disabled. Incompatible combination: OpenCV + Qt4 and VTK ver.${VTK_VERSION} + Qt5") + return() + endif() endif() + +set(HAVE_VTK ON) +message(STATUS "Found VTK ver. ${VTK_VERSION} (usefile: ${VTK_USE_FILE})") diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 03818018d9..cb425a2cc0 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -484,6 +484,10 @@ macro(ocv_glob_module_sources) file(GLOB_RECURSE lib_int_hdrs "src/*.hpp" "src/*.h") file(GLOB lib_hdrs "include/opencv2/${name}/*.hpp" "include/opencv2/${name}/*.h") file(GLOB lib_hdrs_detail "include/opencv2/${name}/detail/*.hpp" "include/opencv2/${name}/detail/*.h") + file(GLOB_RECURSE lib_srcs_apple "src/*.mm") + if (APPLE) + list(APPEND lib_srcs ${lib_srcs_apple}) + endif() file(GLOB lib_cuda_srcs "src/cuda/*.cu") set(cuda_objs "") @@ -744,8 +748,8 @@ function(ocv_add_accuracy_tests) endif() get_native_precompiled_header(${the_target} test_precomp.hpp) - add_executable(${the_target} ${OPENCV_TEST_${the_module}_SOURCES} ${${the_target}_pch}) + target_link_libraries(${the_target} ${OPENCV_MODULE_${the_module}_DEPS} ${test_deps} ${OPENCV_LINKER_LIBS}) add_dependencies(opencv_tests ${the_target}) diff --git a/cmake/templates/OpenCVConfig.cmake.in b/cmake/templates/OpenCVConfig.cmake.in index 6db61d2112..3222048282 100644 --- a/cmake/templates/OpenCVConfig.cmake.in +++ b/cmake/templates/OpenCVConfig.cmake.in @@ -18,8 +18,8 @@ # This file will define the following variables: # - OpenCV_LIBS : The list of all imported targets for OpenCV modules. # - OpenCV_INCLUDE_DIRS : The OpenCV include directories. -# - OpenCV_COMPUTE_CAPABILITIES : The version of compute capability -# - OpenCV_ANDROID_NATIVE_API_LEVEL : Minimum required level of Android API +# - OpenCV_COMPUTE_CAPABILITIES : The version of compute capability. +# - OpenCV_ANDROID_NATIVE_API_LEVEL : Minimum required level of Android API. # - OpenCV_VERSION : The version of this OpenCV build: "@OPENCV_VERSION@" # - OpenCV_VERSION_MAJOR : Major version part of OpenCV_VERSION: "@OPENCV_VERSION_MAJOR@" # - OpenCV_VERSION_MINOR : Minor version part of OpenCV_VERSION: "@OPENCV_VERSION_MINOR@" @@ -27,22 +27,26 @@ # - OpenCV_VERSION_TWEAK : Tweak version part of OpenCV_VERSION: "@OPENCV_VERSION_TWEAK@" # # Advanced variables: -# - OpenCV_SHARED -# - OpenCV_CONFIG_PATH -# - OpenCV_INSTALL_PATH (not set on Windows) -# - OpenCV_LIB_COMPONENTS -# - OpenCV_USE_MANGLED_PATHS -# - OpenCV_HAVE_ANDROID_CAMERA +# - OpenCV_SHARED : Use OpenCV as shared library +# - OpenCV_CONFIG_PATH : Path to this OpenCVConfig.cmake +# - OpenCV_INSTALL_PATH : OpenCV location (not set on Windows) +# - OpenCV_LIB_COMPONENTS : Present OpenCV modules list +# - OpenCV_USE_MANGLED_PATHS : Mangled OpenCV path flag +# - OpenCV_MODULES_SUFFIX : The suffix for OpenCVModules-XXX.cmake file +# - OpenCV_HAVE_ANDROID_CAMERA : Presence of Android native camera wrappers # # =================================================================================== -set(modules_file_suffix "") -if(ANDROID) - string(REPLACE - _ modules_file_suffix "_${ANDROID_NDK_ABI_NAME}") +if(NOT DEFINED OpenCV_MODULES_SUFFIX) + if(ANDROID) + string(REPLACE - _ OpenCV_MODULES_SUFFIX "_${ANDROID_NDK_ABI_NAME}") + else() + set(OpenCV_MODULES_SUFFIX "") + endif() endif() if(NOT TARGET opencv_core) - include(${CMAKE_CURRENT_LIST_DIR}/OpenCVModules${modules_file_suffix}.cmake) + include(${CMAKE_CURRENT_LIST_DIR}/OpenCVModules${OpenCV_MODULES_SUFFIX}.cmake) endif() # TODO All things below should be reviewed. What is about of moving this code into related modules (special vars/hooks/files) diff --git a/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.rst b/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.rst index 1a5c59de07..f5f636d08b 100644 --- a/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.rst +++ b/doc/tutorials/imgproc/histograms/histogram_comparison/histogram_comparison.rst @@ -84,88 +84,10 @@ Code * **Code at glance:** -.. code-block:: cpp - - #include "opencv2/highgui/highgui.hpp" - #include "opencv2/imgproc/imgproc.hpp" - #include - #include - - using namespace std; - using namespace cv; - - /** @function main */ - int main( int argc, char** argv ) - { - Mat src_base, hsv_base; - Mat src_test1, hsv_test1; - Mat src_test2, hsv_test2; - Mat hsv_half_down; - - /// Load three images with different environment settings - if( argc < 4 ) - { printf("** Error. Usage: ./compareHist_Demo \n"); - return -1; - } - - src_base = imread( argv[1], 1 ); - src_test1 = imread( argv[2], 1 ); - src_test2 = imread( argv[3], 1 ); - - /// Convert to HSV - cvtColor( src_base, hsv_base, CV_BGR2HSV ); - cvtColor( src_test1, hsv_test1, CV_BGR2HSV ); - cvtColor( src_test2, hsv_test2, CV_BGR2HSV ); - - hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) ); - - /// Using 30 bins for hue and 32 for saturation - int h_bins = 50; int s_bins = 60; - int histSize[] = { h_bins, s_bins }; - - // hue varies from 0 to 256, saturation from 0 to 180 - float h_ranges[] = { 0, 256 }; - float s_ranges[] = { 0, 180 }; - - const float* ranges[] = { h_ranges, s_ranges }; - - // Use the o-th and 1-st channels - int channels[] = { 0, 1 }; - - /// Histograms - MatND hist_base; - MatND hist_half_down; - MatND hist_test1; - MatND hist_test2; - - /// Calculate the histograms for the HSV images - calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false ); - normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() ); +.. literalinclude:: ../../../../../samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp + :language: cpp + :tab-width: 4 - calcHist( &hsv_half_down, 1, channels, Mat(), hist_half_down, 2, histSize, ranges, true, false ); - normalize( hist_half_down, hist_half_down, 0, 1, NORM_MINMAX, -1, Mat() ); - - calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false ); - normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() ); - - calcHist( &hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false ); - normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() ); - - /// Apply the histogram comparison methods - for( int i = 0; i < 4; i++ ) - { int compare_method = i; - double base_base = compareHist( hist_base, hist_base, compare_method ); - double base_half = compareHist( hist_base, hist_half_down, compare_method ); - double base_test1 = compareHist( hist_base, hist_test1, compare_method ); - double base_test2 = compareHist( hist_base, hist_test2, compare_method ); - - printf( " Method [%d] Perfect, Base-Half, Base-Test(1), Base-Test(2) : %f, %f, %f, %f \n", i, base_base, base_half , base_test1, base_test2 ); - } - - printf( "Done \n" ); - - return 0; - } Explanation @@ -211,11 +133,11 @@ Explanation .. code-block:: cpp - int h_bins = 50; int s_bins = 32; + int h_bins = 50; int s_bins = 60; int histSize[] = { h_bins, s_bins }; - float h_ranges[] = { 0, 256 }; - float s_ranges[] = { 0, 180 }; + float h_ranges[] = { 0, 180 }; + float s_ranges[] = { 0, 256 }; const float* ranges[] = { h_ranges, s_ranges }; diff --git a/modules/core/doc/basic_structures.rst b/modules/core/doc/basic_structures.rst index 54a1f4261d..95d1b37f11 100644 --- a/modules/core/doc/basic_structures.rst +++ b/modules/core/doc/basic_structures.rst @@ -1350,7 +1350,7 @@ Copies the matrix to another one. The method copies the matrix data to another matrix. Before copying the data, the method invokes :: - m.create(this->size(), this->type); + m.create(this->size(), this->type()); so that the destination matrix is reallocated if needed. While ``m.copyTo(m);`` works flawlessly, the function does not handle the case of a partial overlap between the source and the destination matrices. @@ -1445,7 +1445,7 @@ Transposes a matrix. The method performs matrix transposition by means of matrix expressions. It does not perform the actual transposition but returns a temporary matrix transposition object that can be further used as a part of more complex matrix expressions or can be assigned to a matrix: :: - Mat A1 = A + Mat::eye(A.size(), A.type)*lambda; + Mat A1 = A + Mat::eye(A.size(), A.type())*lambda; Mat C = A1.t()*A1; // compute (A + lambda*I)^t * (A + lamda*I) diff --git a/modules/core/src/persistence.cpp b/modules/core/src/persistence.cpp index 7759f708b6..6847eec34d 100644 --- a/modules/core/src/persistence.cpp +++ b/modules/core/src/persistence.cpp @@ -4855,7 +4855,7 @@ cvRegisterType( const CvTypeInfo* _info ) "Type name should contain only letters, digits, - and _" ); } - info = (CvTypeInfo*)malloc( sizeof(*info) + len + 1 ); + info = (CvTypeInfo*)cvAlloc( sizeof(*info) + len + 1 ); *info = *_info; info->type_name = (char*)(info + 1); @@ -4893,7 +4893,7 @@ cvUnregisterType( const char* type_name ) if( !CvType::first || !CvType::last ) CvType::first = CvType::last = 0; - free( info ); + cvFree( &info ); } } diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h index 3fea956a74..489ed80565 100644 --- a/modules/flann/include/opencv2/flann/kmeans_index.h +++ b/modules/flann/include/opencv2/flann/kmeans_index.h @@ -759,10 +759,13 @@ private: for (int k=0; k OCL_SURF; #define OCL_TEST_CYCLE() for( ; startTimer(), next(); cv::ocl::finish(), stopTimer()) -PERF_TEST_P(OCL_SURF, with_data_transfer, testing::Values(SURF_IMAGES)) +PERF_TEST_P(OCL_SURF, DISABLED_with_data_transfer, testing::Values(SURF_IMAGES)) { string filename = getDataPath(GetParam()); Mat src = imread(filename, IMREAD_GRAYSCALE); @@ -94,7 +94,7 @@ PERF_TEST_P(OCL_SURF, with_data_transfer, testing::Values(SURF_IMAGES)) SANITY_CHECK_NOTHING(); } -PERF_TEST_P(OCL_SURF, without_data_transfer, testing::Values(SURF_IMAGES)) +PERF_TEST_P(OCL_SURF, DISABLED_without_data_transfer, testing::Values(SURF_IMAGES)) { string filename = getDataPath(GetParam()); Mat src = imread(filename, IMREAD_GRAYSCALE); diff --git a/modules/ocl/src/arithm.cpp b/modules/ocl/src/arithm.cpp index 0b316c5ea3..e7638ecc4d 100644 --- a/modules/ocl/src/arithm.cpp +++ b/modules/ocl/src/arithm.cpp @@ -313,32 +313,28 @@ void cv::ocl::compare(const oclMat &src1, const oclMat &src2, oclMat &dst , int enum { SUM = 0, ABS_SUM, SQR_SUM }; -static void arithmetic_sum_buffer_run(const oclMat &src, cl_mem &dst, int groupnum, int type, int ddepth) +static void arithmetic_sum_buffer_run(const oclMat &src, cl_mem &dst, int groupnum, int type, int ddepth, int vlen) { - int ochannels = src.oclchannels(); - int all_cols = src.step / src.elemSize(); - int pre_cols = (src.offset % src.step) / src.elemSize(); - int sec_cols = all_cols - (src.offset % src.step + src.cols * src.elemSize() - 1) / src.elemSize() - 1; - int invalid_cols = pre_cols + sec_cols; - int cols = all_cols - invalid_cols , elemnum = cols * src.rows;; - int offset = src.offset / src.elemSize(); + int vElemSize = vlen * src.elemSize(); + int src_offset = src.offset / vElemSize, src_step = src.step / vElemSize; + int src_cols = src.cols / vlen, total = src.size().area() / vlen; + + vlen *= src.oclchannels(); const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; const char * const funcMap[] = { "FUNC_SUM", "FUNC_ABS_SUM", "FUNC_SQR_SUM" }; - const char * const channelMap[] = { " ", " ", "2", "4", "4" }; + const char * const channelMap[] = { " ", " ", "2", "4", "4", "", "", "", "8" }; string buildOptions = format("-D srcT=%s%s -D dstT=%s%s -D convertToDstT=convert_%s%s -D %s", - typeMap[src.depth()], channelMap[ochannels], - typeMap[ddepth], channelMap[ochannels], - typeMap[ddepth], channelMap[ochannels], - funcMap[type]); + typeMap[src.depth()], channelMap[vlen], typeMap[ddepth], + channelMap[vlen], typeMap[ddepth], channelMap[vlen], funcMap[type]); vector > args; - args.push_back( make_pair( sizeof(cl_int) , (void *)&cols )); - args.push_back( make_pair( sizeof(cl_int) , (void *)&invalid_cols )); - args.push_back( make_pair( sizeof(cl_int) , (void *)&offset)); - args.push_back( make_pair( sizeof(cl_int) , (void *)&elemnum)); - args.push_back( make_pair( sizeof(cl_int) , (void *)&groupnum)); args.push_back( make_pair( sizeof(cl_mem) , (void *)&src.data)); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src_step )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src_offset )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src_cols )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&total )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&groupnum )); args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst )); size_t globalThreads[3] = { groupnum * 256, 1, 1 }; @@ -360,7 +356,11 @@ Scalar arithmetic_sum(const oclMat &src, int type, int ddepth) size_t groupnum = src.clCxt->getDeviceInfo().maxComputeUnits; CV_Assert(groupnum != 0); - int dbsize = groupnum * src.oclchannels(); + int vlen = 8 / src.channels(), vElemSize = vlen * src.elemSize1(); + while (src.offset % vElemSize != 0 || src.step % vElemSize != 0 || src.cols % vlen != 0) + vlen >>= 1, vElemSize >>= 1; + + int dbsize = groupnum * src.oclchannels() * vlen; Context *clCxt = src.clCxt; AutoBuffer _buf(dbsize); @@ -368,12 +368,12 @@ Scalar arithmetic_sum(const oclMat &src, int type, int ddepth) memset(p, 0, dbsize * sizeof(T)); cl_mem dstBuffer = openCLCreateBuffer(clCxt, CL_MEM_WRITE_ONLY, dbsize * sizeof(T)); - arithmetic_sum_buffer_run(src, dstBuffer, groupnum, type, ddepth); + arithmetic_sum_buffer_run(src, dstBuffer, groupnum, type, ddepth, vlen); openCLReadBuffer(clCxt, dstBuffer, (void *)p, dbsize * sizeof(T)); openCLFree(dstBuffer); Scalar s = Scalar::all(0.0); - for (int i = 0; i < dbsize;) + for (int i = 0; i < dbsize; ) for (int j = 0; j < src.oclchannels(); j++, i++) s.val[j] += p[i]; @@ -473,20 +473,13 @@ void cv::ocl::meanStdDev(const oclMat &src, Scalar &mean, Scalar &stddev) ////////////////////////////////////////////////////////////////////////////// template -static void arithmetic_minMax_run(const oclMat &src, const oclMat & mask, cl_mem &dst, int groupnum, string kernelName) +static void arithmetic_minMax_run(const oclMat &src, const oclMat & mask, cl_mem &dst, int vlen, int groupnum) { - int all_cols = src.step / src.elemSize(); - int pre_cols = (src.offset % src.step) / src.elemSize(); - int sec_cols = all_cols - (src.offset % src.step + src.cols * src.elemSize() - 1) / src.elemSize() - 1; - int invalid_cols = pre_cols + sec_cols; - int cols = all_cols - invalid_cols , elemnum = cols * src.rows; - int offset = src.offset / src.elemSize(); - const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char * const channelMap[] = { " ", " ", "2", "4", "4" }; + const char * const channelMap[] = { " ", " ", "2", "4", "4", "", "", "", "8" }; ostringstream stream; - stream << "-D T=" << typeMap[src.depth()] << channelMap[src.channels()]; + stream << "-D T=" << typeMap[src.depth()] << channelMap[vlen]; if (numeric_limits::is_integer) { stream << " -D MAX_VAL=" << (WT)numeric_limits::max(); @@ -494,38 +487,38 @@ static void arithmetic_minMax_run(const oclMat &src, const oclMat & mask, cl_mem } else stream << " -D DEPTH_" << src.depth(); + stream << " -D vlen=" << vlen; std::string buildOptions = stream.str(); + int vElemSize = src.elemSize1() * vlen, src_cols = src.cols / vlen; + int src_step = src.step / vElemSize, src_offset = src.offset / vElemSize; + int mask_step = mask.step / vlen, mask_offset = mask.offset / vlen; + int total = src.size().area() / vlen; + vector > args; args.push_back( make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst )); - args.push_back( make_pair( sizeof(cl_int) , (void *)&cols )); - args.push_back( make_pair( sizeof(cl_int) , (void *)&invalid_cols )); - args.push_back( make_pair( sizeof(cl_int) , (void *)&offset)); - args.push_back( make_pair( sizeof(cl_int) , (void *)&elemnum)); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src_step )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src_offset )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src.rows )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src_cols )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&total)); args.push_back( make_pair( sizeof(cl_int) , (void *)&groupnum)); + args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst)); - int minvalid_cols = 0, moffset = 0; if (!mask.empty()) { - int mall_cols = mask.step / mask.elemSize(); - int mpre_cols = (mask.offset % mask.step) / mask.elemSize(); - int msec_cols = mall_cols - (mask.offset % mask.step + mask.cols * mask.elemSize() - 1) / mask.elemSize() - 1; - minvalid_cols = mpre_cols + msec_cols; - moffset = mask.offset / mask.elemSize(); - args.push_back( make_pair( sizeof(cl_mem) , (void *)&mask.data )); - args.push_back( make_pair( sizeof(cl_int) , (void *)&minvalid_cols )); - args.push_back( make_pair( sizeof(cl_int) , (void *)&moffset )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&mask_step )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&mask_offset )); - kernelName += "_mask"; + buildOptions += " -D WITH_MASK"; } - size_t globalThreads[3] = {groupnum * 256, 1, 1}; - size_t localThreads[3] = {256, 1, 1}; + size_t globalThreads[3] = { groupnum * 256, 1, 1 }; + size_t localThreads[3] = { 256, 1, 1 }; - // kernel use fixed grid size, replace lt on NULL is imposible without kernel changes - openCLExecuteKernel(src.clCxt, &arithm_minMax, kernelName, globalThreads, localThreads, + // kernel use fixed grid size, replace lt on NULL is impossible without kernel changes + openCLExecuteKernel(src.clCxt, &arithm_minMax, "arithm_op_minMax", globalThreads, localThreads, args, -1, -1, buildOptions.c_str()); } @@ -535,25 +528,33 @@ void arithmetic_minMax(const oclMat &src, double *minVal, double *maxVal, const size_t groupnum = src.clCxt->getDeviceInfo().maxComputeUnits; CV_Assert(groupnum != 0); - int dbsize = groupnum * 2 * src.elemSize(); + int vlen = mask.empty() ? 8 : 1, vElemSize = vlen * src.elemSize1(); + while (src.offset % vElemSize != 0 || src.step % vElemSize != 0 || src.cols % vlen != 0) + { + vlen >>= 1; + vElemSize >>= 1; + } + + int dbsize = groupnum * 2 * vElemSize; oclMat buf; ensureSizeIsEnough(1, dbsize, CV_8UC1, buf); cl_mem buf_data = reinterpret_cast(buf.data); - arithmetic_minMax_run(src, mask, buf_data, groupnum, "arithm_op_minMax"); + arithmetic_minMax_run(src, mask, buf_data, vlen, groupnum); Mat matbuf = Mat(buf); T *p = matbuf.ptr(); + if (minVal != NULL) { *minVal = std::numeric_limits::max(); - for (int i = 0, end = src.oclchannels() * (int)groupnum; i < end; i++) + for (int i = 0, end = vlen * (int)groupnum; i < end; i++) *minVal = *minVal < p[i] ? *minVal : p[i]; } if (maxVal != NULL) { *maxVal = -std::numeric_limits::max(); - for (int i = src.oclchannels() * (int)groupnum, end = i << 1; i < end; i++) + for (int i = vlen * (int)groupnum, end = i << 1; i < end; i++) *maxVal = *maxVal > p[i] ? *maxVal : p[i]; } } @@ -564,7 +565,7 @@ void cv::ocl::minMax(const oclMat &src, double *minVal, double *maxVal, const oc { CV_Assert(src.channels() == 1); CV_Assert(src.size() == mask.size() || mask.empty()); - CV_Assert(src.step % src.elemSize() == 0); + CV_Assert(src.step % src.elemSize1() == 0); if (minVal == NULL && maxVal == NULL) return; @@ -1139,7 +1140,7 @@ static void arithmetic_minMaxLoc_run(const oclMat &src, cl_mem &dst, int vlen , sprintf(build_options, "-D DEPTH_%d -D REPEAT_S%d -D REPEAT_E%d", src.depth(), repeat_s, repeat_e); size_t gt[3] = {groupnum * 256, 1, 1}, lt[3] = {256, 1, 1}; - // kernel use fixed grid size, replace lt on NULL is imposible without kernel changes + // kernel use fixed grid size, replace lt on NULL is impossible without kernel changes openCLExecuteKernel(src.clCxt, &arithm_minMaxLoc, "arithm_op_minMaxLoc", gt, lt, args, -1, -1, build_options); } @@ -1169,7 +1170,7 @@ static void arithmetic_minMaxLoc_mask_run(const oclMat &src, const oclMat &mask, args.push_back( make_pair( sizeof(cl_mem) , (void *)&mask.data )); args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst )); - // kernel use fixed grid size, replace lt on NULL is imposible without kernel changes + // kernel use fixed grid size, replace lt on NULL is impossible without kernel changes openCLExecuteKernel(src.clCxt, &arithm_minMaxLoc_mask, "arithm_op_minMaxLoc_mask", gt, lt, args, -1, -1, build_options); } } @@ -1262,38 +1263,35 @@ void cv::ocl::minMaxLoc(const oclMat &src, double *minVal, double *maxVal, ///////////////////////////// countNonZero /////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -static void arithmetic_countNonZero_run(const oclMat &src, cl_mem &dst, int groupnum, string kernelName) +static void arithmetic_countNonZero_run(const oclMat &src, cl_mem &dst, int groupnum, int vlen) { - int ochannels = src.oclchannels(); - int all_cols = src.step / src.elemSize(); - int pre_cols = (src.offset % src.step) / src.elemSize(); - int sec_cols = all_cols - (src.offset % src.step + src.cols * src.elemSize() - 1) / src.elemSize() - 1; - int invalid_cols = pre_cols + sec_cols; - int cols = all_cols - invalid_cols , elemnum = cols * src.rows;; - int offset = src.offset / src.elemSize(); + int vElemSize = vlen * src.elemSize1(); + int src_step = src.step / vElemSize, src_offset = src.offset / vElemSize; + int src_cols = src.cols / vlen, total = src.size().area() / vlen; const char * const typeMap[] = { "uchar", "char", "ushort", "short", "int", "float", "double" }; - const char * const channelMap[] = { " ", " ", "2", "4", "4" }; - string buildOptions = format("-D srcT=%s%s -D dstT=int%s", typeMap[src.depth()], channelMap[ochannels], - channelMap[ochannels]); + const char * const channelMap[] = { "", "", "2", "4", "4", "", "", "", "8" }; + string buildOptions = format("-D srcT=%s%s -D dstT=int%s -D convertToDstT=convert_int%s", + typeMap[src.depth()], channelMap[vlen], + channelMap[vlen], channelMap[vlen]); vector > args; - args.push_back( make_pair( sizeof(cl_int) , (void *)&cols )); - args.push_back( make_pair( sizeof(cl_int) , (void *)&invalid_cols )); - args.push_back( make_pair( sizeof(cl_int) , (void *)&offset)); - args.push_back( make_pair( sizeof(cl_int) , (void *)&elemnum)); - args.push_back( make_pair( sizeof(cl_int) , (void *)&groupnum)); args.push_back( make_pair( sizeof(cl_mem) , (void *)&src.data)); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src_step )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src_offset )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src_cols )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&total )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&groupnum )); args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst )); size_t globalThreads[3] = { groupnum * 256, 1, 1 }; #ifdef ANDROID - openCLExecuteKernel(src.clCxt, &arithm_nonzero, kernelName, globalThreads, NULL, + openCLExecuteKernel(src.clCxt, &arithm_nonzero, "arithm_op_nonzero", globalThreads, NULL, args, -1, -1, buildOptions.c_str()); #else size_t localThreads[3] = { 256, 1, 1 }; - openCLExecuteKernel(src.clCxt, &arithm_nonzero, kernelName, globalThreads, localThreads, + openCLExecuteKernel(src.clCxt, &arithm_nonzero, "arithm_op_nonzero", globalThreads, localThreads, args, -1, -1, buildOptions.c_str()); #endif } @@ -1310,18 +1308,20 @@ int cv::ocl::countNonZero(const oclMat &src) return -1; } + int vlen = 8, vElemSize = src.elemSize1() * vlen; + while (src.offset % vElemSize != 0 || src.step % vElemSize != 0 || src.cols % vlen != 0) + vlen >>= 1, vElemSize >>= 1; + size_t groupnum = src.clCxt->getDeviceInfo().maxComputeUnits; CV_Assert(groupnum != 0); - int dbsize = groupnum; - - string kernelName = "arithm_op_nonzero"; + int dbsize = groupnum * vlen; AutoBuffer _buf(dbsize); int *p = (int*)_buf, nonzero = 0; memset(p, 0, dbsize * sizeof(int)); cl_mem dstBuffer = openCLCreateBuffer(clCxt, CL_MEM_WRITE_ONLY, dbsize * sizeof(int)); - arithmetic_countNonZero_run(src, dstBuffer, groupnum, kernelName); + arithmetic_countNonZero_run(src, dstBuffer, groupnum, vlen); openCLReadBuffer(clCxt, dstBuffer, (void *)p, dbsize * sizeof(int)); for (int i = 0; i < dbsize; i++) @@ -1336,157 +1336,118 @@ int cv::ocl::countNonZero(const oclMat &src) ////////////////////////////////bitwise_op//////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -static void bitwise_unary_run(const oclMat &src1, oclMat &dst, string kernelName, const cv::ocl::ProgramEntry* source) -{ - dst.create(src1.size(), src1.type()); - - int channels = dst.oclchannels(); - int depth = dst.depth(); - - int vector_lengths[4][7] = {{4, 4, 4, 4, 1, 1, 1}, - {4, 4, 4, 4, 1, 1, 1}, - {4, 4, 4, 4, 1, 1, 1}, - {4, 4, 4, 4, 1, 1, 1} - }; - - size_t vector_length = vector_lengths[channels - 1][depth]; - int offset_cols = (dst.offset / dst.elemSize1()) & (vector_length - 1); - int cols = divUp(dst.cols * channels + offset_cols, vector_length); +enum { AND = 0, OR, XOR, NOT }; -#ifdef ANDROID - size_t localThreads[3] = { 64, 2, 1 }; -#else - size_t localThreads[3] = { 64, 4, 1 }; -#endif - size_t globalThreads[3] = { cols, dst.rows, 1 }; - - int dst_step1 = dst.cols * dst.elemSize(); - vector > args; - args.push_back( make_pair( sizeof(cl_mem), (void *)&src1.data )); - args.push_back( make_pair( sizeof(cl_int), (void *)&src1.step )); - args.push_back( make_pair( sizeof(cl_int), (void *)&src1.offset )); - args.push_back( make_pair( sizeof(cl_mem), (void *)&dst.data )); - args.push_back( make_pair( sizeof(cl_int), (void *)&dst.step )); - args.push_back( make_pair( sizeof(cl_int), (void *)&dst.offset )); - args.push_back( make_pair( sizeof(cl_int), (void *)&src1.rows )); - args.push_back( make_pair( sizeof(cl_int), (void *)&cols )); - args.push_back( make_pair( sizeof(cl_int), (void *)&dst_step1 )); - - openCLExecuteKernel(src1.clCxt, source, kernelName, globalThreads, localThreads, args, -1, depth); -} - -enum { AND = 0, OR, XOR }; - -static void bitwise_binary_run(const oclMat &src1, const oclMat &src2, const Scalar& src3, const oclMat &mask, - oclMat &dst, int operationType) +static void bitwise_run(const oclMat & src1, const oclMat & src2, const Scalar & src3, const oclMat & mask, + oclMat & dst, int operationType) { - CV_Assert(operationType >= AND && operationType <= XOR); - CV_Assert(src2.empty() || (!src2.empty() && src1.type() == src2.type() && src1.size() == src2.size())); - CV_Assert(mask.empty() || (!mask.empty() && mask.type() == CV_8UC1 && mask.size() == src1.size())); + CV_Assert(operationType >= AND && operationType <= NOT); + CV_Assert(src2.empty() || (src1.type() == src2.type() && src1.size() == src2.size())); + CV_Assert(mask.empty() || (mask.type() == CV_8UC1 && mask.size() == src1.size())); dst.create(src1.size(), src1.type()); - oclMat m; + double scalar[4]; - const char operationMap[] = { '&', '|', '^' }; - std::string kernelName("arithm_bitwise_binary"); + bool haveScalar = src2.empty() && operationType != NOT, haveMask = !mask.empty(); + int ocn = dst.oclchannels(), depth = dst.depth(); + const char operationMap[] = { '&', '|', '^', '~' }; + const char * const typeMap[] = { "uchar", "uchar", "ushort", "ushort", "int", "int", "ulong" }; + const char * const channelMap[] = { "", "", "2", "4", "4", "", "", "", "8", "", "", "", "", "", "", "", "16" }; + const int preferredVectorWidth[] = { 4, 4, 2, 2, 1, 1, 1 }; + int kercn = haveMask || haveScalar ? ocn : preferredVectorWidth[depth]; - int vlen = std::min(8, src1.elemSize1() * src1.oclchannels()); - std::string vlenstr = vlen > 1 ? format("%d", vlen) : ""; - std::string buildOptions = format("-D Operation=%c -D vloadn=vload%s -D vstoren=vstore%s -D elemSize=%d -D vlen=%d" - " -D ucharv=uchar%s", - operationMap[operationType], vlenstr.c_str(), vlenstr.c_str(), - (int)src1.elemSize(), vlen, vlenstr.c_str()); + if (!haveScalar && !haveMask) + { + int velemsize = dst.elemSize1() * kercn; + while (src1.offset % velemsize != 0 || src1.step % velemsize != 0 || src1.cols * ocn % kercn != 0 || + src2.offset % velemsize != 0 || src2.step % velemsize != 0 || src2.cols * ocn % kercn != 0 || + dst.offset % velemsize != 0 || dst.step % velemsize != 0 || dst.cols * ocn % kercn != 0) + kercn >>= 1, velemsize >>= 1; + } -#ifdef ANDROID - size_t localThreads[3] = { 16, 10, 1 }; -#else - size_t localThreads[3] = { 16, 16, 1 }; -#endif - size_t globalThreads[3] = { dst.cols, dst.rows, 1 }; + int cols = dst.cols * ocn / kercn; + + std::string buildOptions = format("-D Operation=%c -D T=%s%s", operationMap[operationType], + typeMap[depth], channelMap[kercn]); vector > args; args.push_back( make_pair( sizeof(cl_mem), (void *)&src1.data )); args.push_back( make_pair( sizeof(cl_int), (void *)&src1.step )); args.push_back( make_pair( sizeof(cl_int), (void *)&src1.offset )); - if (src2.empty()) + if (haveScalar) { - m.create(1, 1, dst.type()); - m.setTo(src3); + int sctype = CV_MAKE_TYPE(dst.depth(), ocn); + cv::scalarToRawData(src3, scalar, sctype); - args.push_back( make_pair( sizeof(cl_mem), (void *)&m.data )); + args.push_back( make_pair( CV_ELEM_SIZE(sctype), (void *)scalar )); - kernelName += "_scalar"; + buildOptions += " -D HAVE_SCALAR"; } - else + else if (operationType != NOT) { args.push_back( make_pair( sizeof(cl_mem), (void *)&src2.data )); args.push_back( make_pair( sizeof(cl_int), (void *)&src2.step )); args.push_back( make_pair( sizeof(cl_int), (void *)&src2.offset )); + + buildOptions += " -D OP_BINARY"; } - if (!mask.empty()) + if (haveMask) { args.push_back( make_pair( sizeof(cl_mem), (void *)&mask.data )); args.push_back( make_pair( sizeof(cl_int), (void *)&mask.step )); args.push_back( make_pair( sizeof(cl_int), (void *)&mask.offset )); - kernelName += "_mask"; + buildOptions += " -D HAVE_MASK"; } args.push_back( make_pair( sizeof(cl_mem), (void *)&dst.data )); args.push_back( make_pair( sizeof(cl_int), (void *)&dst.step )); args.push_back( make_pair( sizeof(cl_int), (void *)&dst.offset )); - args.push_back( make_pair( sizeof(cl_int), (void *)&src1.cols )); - args.push_back( make_pair( sizeof(cl_int), (void *)&src1.rows )); + args.push_back( make_pair( sizeof(cl_int), (void *)&dst.rows )); + args.push_back( make_pair( sizeof(cl_int), (void *)&cols )); - openCLExecuteKernel(src1.clCxt, mask.empty() ? (!src2.empty() ? &arithm_bitwise_binary : &arithm_bitwise_binary_scalar) : - (!src2.empty() ? &arithm_bitwise_binary_mask : &arithm_bitwise_binary_scalar_mask), - kernelName, globalThreads, localThreads, + size_t globalsize[3] = { dst.cols * ocn / kercn, dst.rows, 1 }; + globalsize[0] = divUp(globalsize[0], 256) * 256; + openCLExecuteKernel(src1.clCxt, &arithm_bitwise, "arithm_bitwise", globalsize, NULL, args, -1, -1, buildOptions.c_str()); } void cv::ocl::bitwise_not(const oclMat &src, oclMat &dst) { - if (!src.clCxt->supportsFeature(FEATURE_CL_DOUBLE) && src.depth() == CV_64F) - { - CV_Error(CV_OpenCLDoubleNotSupported, "Selected device doesn't support double"); - return; - } - - dst.create(src.size(), src.type()); - bitwise_unary_run(src, dst, "arithm_bitwise_not", &arithm_bitwise_not); + bitwise_run(src, oclMat(), Scalar(), oclMat(), dst, NOT); } void cv::ocl::bitwise_or(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask) { - bitwise_binary_run(src1, src2, Scalar(), mask, dst, OR); + bitwise_run(src1, src2, Scalar(), mask, dst, OR); } void cv::ocl::bitwise_or(const oclMat &src1, const Scalar &src2, oclMat &dst, const oclMat &mask) { - bitwise_binary_run(src1, oclMat(), src2, mask, dst, OR); + bitwise_run(src1, oclMat(), src2, mask, dst, OR); } void cv::ocl::bitwise_and(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask) { - bitwise_binary_run(src1, src2, Scalar(), mask, dst, AND); + bitwise_run(src1, src2, Scalar(), mask, dst, AND); } void cv::ocl::bitwise_and(const oclMat &src1, const Scalar &src2, oclMat &dst, const oclMat &mask) { - bitwise_binary_run(src1, oclMat(), src2, mask, dst, AND); + bitwise_run(src1, oclMat(), src2, mask, dst, AND); } void cv::ocl::bitwise_xor(const oclMat &src1, const oclMat &src2, oclMat &dst, const oclMat &mask) { - bitwise_binary_run(src1, src2, Scalar(), mask, dst, XOR); + bitwise_run(src1, src2, Scalar(), mask, dst, XOR); } void cv::ocl::bitwise_xor(const oclMat &src1, const Scalar &src2, oclMat &dst, const oclMat &mask) { - bitwise_binary_run(src1, oclMat(), src2, mask, dst, XOR); + bitwise_run(src1, oclMat(), src2, mask, dst, XOR); } oclMat cv::ocl::operator ~ (const oclMat &src) diff --git a/modules/ocl/src/gftt.cpp b/modules/ocl/src/gftt.cpp index 4f24d13588..57ed12f009 100644 --- a/modules/ocl/src/gftt.cpp +++ b/modules/ocl/src/gftt.cpp @@ -146,34 +146,33 @@ static void minMaxEig_caller(const oclMat &src, oclMat &dst, oclMat & tozero) CV_Assert(groupnum != 0); int dbsize = groupnum * 2 * src.elemSize(); - ensureSizeIsEnough(1, dbsize, CV_8UC1, dst); cl_mem dst_data = reinterpret_cast(dst.data); - int all_cols = src.step / src.elemSize(); - int pre_cols = (src.offset % src.step) / src.elemSize(); - int sec_cols = all_cols - (src.offset % src.step + src.cols * src.elemSize() - 1) / src.elemSize() - 1; - int invalid_cols = pre_cols + sec_cols; - int cols = all_cols - invalid_cols , elemnum = cols * src.rows; - int offset = src.offset / src.elemSize(); + int vElemSize = src.elemSize1(); + int src_step = src.step / vElemSize, src_offset = src.offset / vElemSize; + int total = src.size().area(); - {// first parallel pass + { + // first parallel pass vector > args; args.push_back( make_pair( sizeof(cl_mem) , (void *)&src.data)); - args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst_data )); - args.push_back( make_pair( sizeof(cl_int) , (void *)&cols )); - args.push_back( make_pair( sizeof(cl_int) , (void *)&invalid_cols )); - args.push_back( make_pair( sizeof(cl_int) , (void *)&offset)); - args.push_back( make_pair( sizeof(cl_int) , (void *)&elemnum)); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src_step)); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src_offset)); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src.rows )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&src.cols )); + args.push_back( make_pair( sizeof(cl_int) , (void *)&total)); args.push_back( make_pair( sizeof(cl_int) , (void *)&groupnum)); + args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst_data )); size_t globalThreads[3] = {groupnum * 256, 1, 1}; size_t localThreads[3] = {256, 1, 1}; openCLExecuteKernel(src.clCxt, &arithm_minMax, "arithm_op_minMax", globalThreads, localThreads, - args, -1, -1, "-D T=float -D DEPTH_5"); + args, -1, -1, "-D T=float -D DEPTH_5 -D vlen=1"); } - {// run final "serial" kernel to find accumulate results from threads and reset corner counter + { + // run final "serial" kernel to find accumulate results from threads and reset corner counter vector > args; args.push_back( make_pair( sizeof(cl_mem) , (void *)&dst_data )); args.push_back( make_pair( sizeof(cl_int) , (void *)&groupnum )); diff --git a/modules/ocl/src/opencl/arithm_bitwise_binary.cl b/modules/ocl/src/opencl/arithm_bitwise.cl similarity index 67% rename from modules/ocl/src/opencl/arithm_bitwise_binary.cl rename to modules/ocl/src/opencl/arithm_bitwise.cl index 56cd745d29..899d41970f 100644 --- a/modules/ocl/src/opencl/arithm_bitwise_binary.cl +++ b/modules/ocl/src/opencl/arithm_bitwise.cl @@ -48,35 +48,46 @@ /////////////////////////////////////////// bitwise_binary ////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////// -__kernel void arithm_bitwise_binary(__global uchar * src1, int src1_step, int src1_offset, - __global uchar * src2, int src2_step, int src2_offset, - __global uchar * dst, int dst_step, int dst_offset, - int cols, int rows) +__kernel void arithm_bitwise(__global uchar * src1ptr, int src1_step, int src1_offset, +#ifdef OP_BINARY + __global uchar * src2ptr, int src2_step, int src2_offset, +#elif defined HAVE_SCALAR + T scalar, +#endif +#ifdef HAVE_MASK + __global uchar * mask, int mask_step, int mask_offset, +#endif + __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 < cols && y < rows) + if (x < dst_cols && y < dst_rows) { -#if elemSize > 1 - x *= elemSize; +#ifdef HAVE_MASK + mask += mad24(y, mask_step, x + mask_offset); + if (mask[0]) #endif - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); - -#if elemSize > 1 - #pragma unroll - for (int i = 0; i < elemSize; i += vlen) { - ucharv t0 = vloadn(0, src1 + src1_index + i); - ucharv t1 = vloadn(0, src2 + src2_index + i); - ucharv t2 = t0 Operation t1; + int src1_index = mad24(y, src1_step, mad24(x, (int)sizeof(T), src1_offset)); +#ifdef OP_BINARY + int src2_index = mad24(y, src2_step, mad24(x, (int)sizeof(T), src2_offset)); +#endif + int dst_index = mad24(y, dst_step, mad24(x, (int)sizeof(T), dst_offset)); - vstoren(t2, 0, dst + dst_index + i); - } + __global const T * src1 = (__global const T *)(src1ptr + src1_index); +#ifdef OP_BINARY + __global const T * src2 = (__global const T *)(src2ptr + src2_index); +#endif + __global T * dst = (__global T *)(dstptr + dst_index); + +#ifdef OP_BINARY + dst[0] = src1[0] Operation src2[0]; +#elif defined HAVE_SCALAR + dst[0] = src1[0] Operation scalar; #else - dst[dst_index] = src1[src1_index] Operation src2[src2_index]; + dst[0] = Operation src1[0]; #endif + } } } diff --git a/modules/ocl/src/opencl/arithm_bitwise_binary_mask.cl b/modules/ocl/src/opencl/arithm_bitwise_binary_mask.cl deleted file mode 100644 index 328ccd91ae..0000000000 --- a/modules/ocl/src/opencl/arithm_bitwise_binary_mask.cl +++ /dev/null @@ -1,88 +0,0 @@ -/*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 -// Jiang Liyuan, jlyuan001.good@163.com -// Peng Xiao, pengxiao@outlook.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*/ - -////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////bitwise_binary//////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_bitwise_binary_mask(__global uchar * src1, int src1_step, int src1_offset, - __global uchar * src2, int src2_step, int src2_offset, - __global uchar * mask, int mask_step, int mask_offset, - __global uchar * dst, int dst_step, int dst_offset, - int cols1, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols1 && y < rows) - { - int mask_index = mad24(y, mask_step, mask_offset + x); - - if (mask[mask_index]) - { -#if elemSize > 1 - x *= elemSize; -#endif - int src1_index = mad24(y, src1_step, x + src1_offset); - int src2_index = mad24(y, src2_step, x + src2_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); - -#if elemSize > 1 - #pragma unroll - for (int i = 0; i < elemSize; i += vlen) - { - ucharv t0 = vloadn(0, src1 + src1_index + i); - ucharv t1 = vloadn(0, src2 + src2_index + i); - ucharv t2 = t0 Operation t1; - - vstoren(t2, 0, dst + dst_index + i); - } -#else - dst[dst_index] = src1[src1_index] Operation src2[src2_index]; -#endif - } - } -} diff --git a/modules/ocl/src/opencl/arithm_bitwise_not.cl b/modules/ocl/src/opencl/arithm_bitwise_not.cl deleted file mode 100644 index b6f76d6065..0000000000 --- a/modules/ocl/src/opencl/arithm_bitwise_not.cl +++ /dev/null @@ -1,253 +0,0 @@ -/*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 -// Jiang Liyuan, jlyuan001.good@163.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 - -/////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////BITWISE_NOT//////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////// - -__kernel void arithm_bitwise_not_D0 (__global uchar *src1, int src1_step, int src1_offset, - __global uchar *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - x = x << 2; - int src1_index = mad24(y, src1_step, x + src1_offset); - - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + x); - - uchar4 src1_data = vload4(0, src1 + src1_index); - uchar4 dst_data = vload4(0, dst + dst_index); - uchar4 tmp_data = ~src1_data; - - dst_data.x = dst_index + 0 < dst_end ? tmp_data.x : dst_data.x; - dst_data.y = dst_index + 1 < dst_end ? tmp_data.y : dst_data.y; - dst_data.z = dst_index + 2 < dst_end ? tmp_data.z : dst_data.z; - dst_data.w = dst_index + 3 < dst_end ? tmp_data.w : dst_data.w; - - vstore4(dst_data, 0, dst + dst_index); - } -} - - -__kernel void arithm_bitwise_not_D1 (__global char *src1, int src1_step, int src1_offset, - __global char *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - x = x << 2; - int src1_index = mad24(y, src1_step, x + src1_offset); - - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + x); - - char4 src1_data = vload4(0, src1 + src1_index); - char4 dst_data = vload4(0, dst + dst_index); - char4 tmp_data = ~src1_data; - - dst_data.x = dst_index + 0 < dst_end ? tmp_data.x : dst_data.x; - dst_data.y = dst_index + 1 < dst_end ? tmp_data.y : dst_data.y; - dst_data.z = dst_index + 2 < dst_end ? tmp_data.z : dst_data.z; - dst_data.w = dst_index + 3 < dst_end ? tmp_data.w : dst_data.w; - - vstore4(dst_data, 0, dst + dst_index); - } -} - - -__kernel void arithm_bitwise_not_D2 (__global ushort *src1, int src1_step, int src1_offset, - __global ushort *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) - -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - x = x << 2; - -#ifdef dst_align -#undef dst_align -#endif -#define dst_align ((dst_offset >> 1) & 3) - int src1_index = mad24(y, src1_step, (x << 1) + src1_offset - (dst_align << 1)); - - int dst_start = mad24(y, dst_step, dst_offset); - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + (x << 1) & (int)0xfffffff8); - - ushort4 src1_data = vload4(0, (__global ushort *)((__global char *)src1 + src1_index)); - - ushort4 dst_data = *((__global ushort4 *)((__global char *)dst + dst_index)); - ushort4 tmp_data = ~ src1_data; - - dst_data.x = ((dst_index + 0 >= dst_start) && (dst_index + 0 < dst_end)) ? tmp_data.x : dst_data.x; - dst_data.y = ((dst_index + 2 >= dst_start) && (dst_index + 2 < dst_end)) ? tmp_data.y : dst_data.y; - dst_data.z = ((dst_index + 4 >= dst_start) && (dst_index + 4 < dst_end)) ? tmp_data.z : dst_data.z; - dst_data.w = ((dst_index + 6 >= dst_start) && (dst_index + 6 < dst_end)) ? tmp_data.w : dst_data.w; - - *((__global ushort4 *)((__global char *)dst + dst_index)) = dst_data; - } -} - - - -__kernel void arithm_bitwise_not_D3 (__global short *src1, int src1_step, int src1_offset, - __global short *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) - -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - x = x << 2; - -#ifdef dst_align -#undef dst_align -#endif -#define dst_align ((dst_offset >> 1) & 3) - int src1_index = mad24(y, src1_step, (x << 1) + src1_offset - (dst_align << 1)); - - int dst_start = mad24(y, dst_step, dst_offset); - int dst_end = mad24(y, dst_step, dst_offset + dst_step1); - int dst_index = mad24(y, dst_step, dst_offset + (x << 1) & (int)0xfffffff8); - - short4 src1_data = vload4(0, (__global short *)((__global char *)src1 + src1_index)); - - short4 dst_data = *((__global short4 *)((__global char *)dst + dst_index)); - short4 tmp_data = ~ src1_data; - - dst_data.x = ((dst_index + 0 >= dst_start) && (dst_index + 0 < dst_end)) ? tmp_data.x : dst_data.x; - dst_data.y = ((dst_index + 2 >= dst_start) && (dst_index + 2 < dst_end)) ? tmp_data.y : dst_data.y; - dst_data.z = ((dst_index + 4 >= dst_start) && (dst_index + 4 < dst_end)) ? tmp_data.z : dst_data.z; - dst_data.w = ((dst_index + 6 >= dst_start) && (dst_index + 6 < dst_end)) ? tmp_data.w : dst_data.w; - - *((__global short4 *)((__global char *)dst + dst_index)) = dst_data; - } -} - - - -__kernel void arithm_bitwise_not_D4 (__global int *src1, int src1_step, int src1_offset, - __global int *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src1_index = mad24(y, src1_step, (x << 2) + src1_offset); - int dst_index = mad24(y, dst_step, (x << 2) + dst_offset); - - int data1 = *((__global int *)((__global char *)src1 + src1_index)); - int tmp = ~ data1; - - *((__global int *)((__global char *)dst + dst_index)) = tmp; - } -} - -__kernel void arithm_bitwise_not_D5 (__global char *src, int src_step, int src_offset, - __global char *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src_index = mad24(y, src_step, (x << 2) + src_offset); - int dst_index = mad24(y, dst_step, (x << 2) + dst_offset); - - char4 data; - - data = *((__global char4 *)((__global char *)src + src_index)); - data = ~ data; - - *((__global char4 *)((__global char *)dst + dst_index)) = data; - } -} - -#if defined (DOUBLE_SUPPORT) -__kernel void arithm_bitwise_not_D6 (__global char *src, int src_step, int src_offset, - __global char *dst, int dst_step, int dst_offset, - int rows, int cols, int dst_step1) -{ - int x = get_global_id(0); - int y = get_global_id(1); - - if (x < cols && y < rows) - { - int src_index = mad24(y, src_step, (x << 3) + src_offset); - int dst_index = mad24(y, dst_step, (x << 3) + dst_offset); - - char8 data; - - data = *((__global char8 *)((__global char *)src + src_index)); - data = ~ data; - - *((__global char8 *)((__global char *)dst + dst_index)) = data; - } -} -#endif diff --git a/modules/ocl/src/opencl/arithm_minMax.cl b/modules/ocl/src/opencl/arithm_minMax.cl index 01db7d0646..b0cd1c8b68 100644 --- a/modules/ocl/src/opencl/arithm_minMax.cl +++ b/modules/ocl/src/opencl/arithm_minMax.cl @@ -63,81 +63,31 @@ /**************************************Array minMax**************************************/ -__kernel void arithm_op_minMax(__global const T * src, __global T * dst, - int cols, int invalid_cols, int offset, int elemnum, int groupnum) -{ - int lid = get_local_id(0); - int gid = get_group_id(0); - int id = get_global_id(0); - - int idx = offset + id + (id / cols) * invalid_cols; - - __local T localmem_max[128], localmem_min[128]; - T minval = (T)(MAX_VAL), maxval = (T)(MIN_VAL), temp; - - for (int grainSize = groupnum << 8; id < elemnum; id += grainSize) - { - idx = offset + id + (id / cols) * invalid_cols; - temp = src[idx]; - minval = min(minval, temp); - maxval = max(maxval, temp); - } - - if (lid > 127) - { - localmem_min[lid - 128] = minval; - localmem_max[lid - 128] = maxval; - } - barrier(CLK_LOCAL_MEM_FENCE); - - if (lid < 128) - { - localmem_min[lid] = min(minval, localmem_min[lid]); - localmem_max[lid] = max(maxval, localmem_max[lid]); - } - barrier(CLK_LOCAL_MEM_FENCE); - - for (int lsize = 64; lsize > 0; lsize >>= 1) - { - if (lid < lsize) - { - int lid2 = lsize + lid; - localmem_min[lid] = min(localmem_min[lid], localmem_min[lid2]); - localmem_max[lid] = max(localmem_max[lid], localmem_max[lid2]); - } - barrier(CLK_LOCAL_MEM_FENCE); - } - - if (lid == 0) - { - dst[gid] = localmem_min[0]; - dst[gid + groupnum] = localmem_max[0]; - } -} - -__kernel void arithm_op_minMax_mask(__global const T * src, __global T * dst, - int cols, int invalid_cols, int offset, - int elemnum, int groupnum, - const __global uchar * mask, int minvalid_cols, int moffset) +__kernel void arithm_op_minMax(__global const T * src, int src_step, int src_offset, int src_rows, int src_cols, + int total, int groupnum, __global T * dst +#ifdef WITH_MASK + , __global const uchar * mask, int mask_step, int mask_offset +#endif +) { int lid = get_local_id(0); int gid = get_group_id(0); int id = get_global_id(0); - int idx = offset + id + (id / cols) * invalid_cols; - int midx = moffset + id + (id / cols) * minvalid_cols; - __local T localmem_max[128], localmem_min[128]; T minval = (T)(MAX_VAL), maxval = (T)(MIN_VAL), temp; + int y, x; - for (int grainSize = groupnum << 8; id < elemnum; id += grainSize) + for (int grainSize = groupnum << 8; id < total; id += grainSize) { - idx = offset + id + (id / cols) * invalid_cols; - midx = moffset + id + (id / cols) * minvalid_cols; + y = id / src_cols; + x = id % src_cols; - if (mask[midx]) +#ifdef WITH_MASK + if (mask[mad24(y, mask_step, x + mask_offset)]) +#endif { - temp = src[idx]; + temp = src[mad24(y, src_step, x + src_offset)]; minval = min(minval, temp); maxval = max(maxval, temp); } diff --git a/modules/ocl/src/opencl/arithm_nonzero.cl b/modules/ocl/src/opencl/arithm_nonzero.cl index 3180c26e86..6a21f27e0e 100644 --- a/modules/ocl/src/opencl/arithm_nonzero.cl +++ b/modules/ocl/src/opencl/arithm_nonzero.cl @@ -52,23 +52,18 @@ /**************************************Count NonZero**************************************/ -__kernel void arithm_op_nonzero(int cols, int invalid_cols, int offset, int elemnum, int groupnum, - __global srcT *src, __global dstT *dst) +__kernel void arithm_op_nonzero(__global srcT * src, int src_step, int src_offset, int src_cols, + int total, int groupnum, __global dstT * dst) { int lid = get_local_id(0); int gid = get_group_id(0); int id = get_global_id(0); - int idx = offset + id + (id / cols) * invalid_cols; __local dstT localmem_nonzero[128]; dstT nonzero = (dstT)(0); - srcT zero = (srcT)(0), one = (srcT)(1); - for (int grain = groupnum << 8; id < elemnum; id += grain) - { - idx = offset + id + (id / cols) * invalid_cols; - nonzero += src[idx] == zero ? zero : one; - } + for (int grain = groupnum << 8; id < total; id += grain) + nonzero += convertToDstT(src[mad24(id / src_cols, src_step, id % src_cols + src_offset)] == (srcT)(0)) ? (dstT)(0) : (dstT)(1); if (lid > 127) localmem_nonzero[lid - 128] = nonzero; diff --git a/modules/ocl/src/opencl/arithm_sum.cl b/modules/ocl/src/opencl/arithm_sum.cl index 514cf2a7f1..86015cfe93 100644 --- a/modules/ocl/src/opencl/arithm_sum.cl +++ b/modules/ocl/src/opencl/arithm_sum.cl @@ -63,21 +63,19 @@ /**************************************Array buffer SUM**************************************/ -__kernel void arithm_op_sum(int cols,int invalid_cols,int offset,int elemnum,int groupnum, - __global srcT *src, __global dstT *dst) +__kernel void arithm_op_sum(__global srcT * src, int src_step, int src_offset, int src_cols, + int total, int groupnum, __global dstT * dst) { int lid = get_local_id(0); int gid = get_group_id(0); int id = get_global_id(0); - int idx = offset + id + (id / cols) * invalid_cols; __local dstT localmem_sum[128]; dstT sum = (dstT)(0), temp; - for (int grainSize = groupnum << 8; id < elemnum; id += grainSize) + for (int grainSize = groupnum << 8; id < total; id += grainSize) { - idx = offset + id + (id / cols) * invalid_cols; - temp = convertToDstT(src[idx]); + temp = convertToDstT(src[mad24(id / src_cols, src_step, id % src_cols + src_offset)]); FUNC(temp, sum); } diff --git a/modules/ocl/test/test_arithm.cpp b/modules/ocl/test/test_arithm.cpp index 17260580de..29976b6e4e 100644 --- a/modules/ocl/test/test_arithm.cpp +++ b/modules/ocl/test/test_arithm.cpp @@ -198,7 +198,7 @@ PARAM_TEST_CASE(ArithmTestBase, MatDepth, Channels, bool) Size roiSize = randomSize(1, MAX_VALUE); Border src1Border = randomBorder(0, use_roi ? MAX_VALUE : 0); - randomSubMat(src1, src1_roi, roiSize, src1Border, type, 2, 11); + randomSubMat(src1, src1_roi, roiSize, src1Border, type, -11, 11); Border src2Border = randomBorder(0, use_roi ? MAX_VALUE : 0); randomSubMat(src2, src2_roi, roiSize, src2Border, type, -1540, 1740); @@ -1163,7 +1163,7 @@ OCL_TEST_P(CountNonZero, MAT) int cpures = cv::countNonZero(src1_roi); int gpures = cv::ocl::countNonZero(gsrc1_roi); - EXPECT_DOUBLE_EQ((double)cpures, (double)gpures); + EXPECT_EQ(cpures, gpures); } } diff --git a/modules/viz/CMakeLists.txt b/modules/viz/CMakeLists.txt index 7ccd079216..d839491c1b 100644 --- a/modules/viz/CMakeLists.txt +++ b/modules/viz/CMakeLists.txt @@ -9,3 +9,7 @@ ocv_define_module(viz opencv_core ${VTK_LIBRARIES}) if(APPLE AND BUILD_opencv_viz) target_link_libraries(opencv_viz "-framework Cocoa") endif() + +if(TARGET opencv_test_viz) + set_target_properties(opencv_test_viz PROPERTIES MACOSX_BUNDLE TRUE) +endif() diff --git a/modules/viz/doc/widget.rst b/modules/viz/doc/widget.rst index 7f8926d3f9..0601ba1b72 100644 --- a/modules/viz/doc/widget.rst +++ b/modules/viz/doc/widget.rst @@ -934,6 +934,8 @@ This 3D Widget defines a collection of clouds. :: void addCloud(InputArray cloud, InputArray colors, const Affine3d &pose = Affine3d::Identity()); //! All points in cloud have the same color void addCloud(InputArray cloud, const Color &color = Color::white(), Affine3d &pose = Affine3d::Identity()); + //! Repacks internal structure to single cloud + void finalize(); }; viz::WCloudCollection::WCloudCollection @@ -964,6 +966,12 @@ Adds a cloud to the collection. .. note:: In case there are four channels in the cloud, fourth channel is ignored. +viz::WCloudCollection::finalize +------------------------------- +Finalizes cloud data by repacking to single cloud. Useful for large cloud collections to reduce memory usage + +.. ocv:function:: void finalize() + viz::WCloudNormals ------------------ .. ocv:class:: WCloudNormals @@ -1017,3 +1025,43 @@ Constructs a WMesh. :param polygons: Points of the mesh object. :param colors: Point colors. :param normals: Point normals. + +viz::WWidgetMerger +--------------------- +.. ocv:class:: WWidgetMerger + +This class allows to merge several widgets to single one. It has quite limited functionality and can't merge widgets with different attributes. For instance, +if widgetA has color array and widgetB has only global color defined, then result of merge won't have color at all. The class is suitable for merging large amount of similar widgets. :: + + class CV_EXPORTS WWidgetMerger : public Widget3D + { + public: + WWidgetMerger(); + + //! Add widget to merge with optional position change + void addWidget(const Widget3D& widget, const Affine3d &pose = Affine3d::Identity()); + + //! Repacks internal structure to single widget + void finalize(); + }; + +viz::WWidgetMerger::WWidgetMerger +--------------------------------------- +Constructs a WWidgetMerger. + +.. ocv:function:: WWidgetMerger() + +viz::WWidgetMerger::addCloud +------------------------------- +Adds a cloud to the collection. + +.. ocv:function:: void addWidget(const Widget3D& widget, const Affine3d &pose = Affine3d::Identity()) + + :param widget: Widget to merge. + :param pose: Pose of the widget. + +viz::WWidgetMerger::finalize +------------------------------- +Finalizes merger data and constructs final merged widget + +.. ocv:function:: void finalize() diff --git a/modules/viz/include/opencv2/viz/types.hpp b/modules/viz/include/opencv2/viz/types.hpp index acbece2edf..3e8e87c65e 100644 --- a/modules/viz/include/opencv2/viz/types.hpp +++ b/modules/viz/include/opencv2/viz/types.hpp @@ -63,6 +63,8 @@ namespace cv Color(const Scalar& color); + operator Vec3b() const; + static Color black(); static Color blue(); static Color green(); @@ -193,6 +195,8 @@ 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::operator cv::Vec3b() const { return cv::Vec3d(val); } + inline cv::viz::Color cv::viz::Color::black() { return Color( 0, 0, 0); } inline cv::viz::Color cv::viz::Color::green() { return Color( 0, 255, 0); } inline cv::viz::Color cv::viz::Color::blue() { return Color(255, 0, 0); } diff --git a/modules/viz/include/opencv2/viz/viz3d.hpp b/modules/viz/include/opencv2/viz/viz3d.hpp index 1a137bcfb3..1be748c8cd 100644 --- a/modules/viz/include/opencv2/viz/viz3d.hpp +++ b/modules/viz/include/opencv2/viz/viz3d.hpp @@ -114,6 +114,8 @@ namespace cv double getRenderingProperty(const String &id, int property); void setRepresentation(int representation); + + void setGlobalWarnings(bool enabled = false); private: struct VizImpl; diff --git a/modules/viz/include/opencv2/viz/widgets.hpp b/modules/viz/include/opencv2/viz/widgets.hpp index 2c49b9d0e2..2949598c54 100644 --- a/modules/viz/include/opencv2/viz/widgets.hpp +++ b/modules/viz/include/opencv2/viz/widgets.hpp @@ -201,6 +201,7 @@ namespace cv class CV_EXPORTS WPolyLine : public Widget3D { public: + WPolyLine(InputArray points, InputArray colors); WPolyLine(InputArray points, const Color &color = Color::white()); }; @@ -345,6 +346,8 @@ namespace cv void addCloud(InputArray cloud, InputArray colors, const Affine3d &pose = Affine3d::Identity()); //! All points in cloud have the same color void addCloud(InputArray cloud, const Color &color = Color::white(), const Affine3d &pose = Affine3d::Identity()); + //! Repacks internal structure to single cloud + void finalize(); }; class CV_EXPORTS WCloudNormals : public Widget3D @@ -360,6 +363,18 @@ namespace cv WMesh(InputArray cloud, InputArray polygons, InputArray colors = noArray(), InputArray normals = noArray()); }; + class CV_EXPORTS WWidgetMerger : public Widget3D + { + public: + WWidgetMerger(); + + //! Add widget to merge with optional position change + void addWidget(const Widget3D& widget, const Affine3d &pose = Affine3d::Identity()); + + //! Repacks internal structure to single widget + void finalize(); + }; + ///////////////////////////////////////////////////////////////////////////// /// Utility exports @@ -389,6 +404,7 @@ namespace cv template<> CV_EXPORTS WCloudCollection Widget::cast(); template<> CV_EXPORTS WCloudNormals Widget::cast(); template<> CV_EXPORTS WMesh Widget::cast(); + template<> CV_EXPORTS WWidgetMerger Widget::cast(); } /* namespace viz */ } /* namespace cv */ diff --git a/modules/viz/src/clouds.cpp b/modules/viz/src/clouds.cpp index 4b84e8e9e1..eec02639e5 100644 --- a/modules/viz/src/clouds.cpp +++ b/modules/viz/src/clouds.cpp @@ -193,8 +193,21 @@ template<> cv::viz::WPaintedCloud cv::viz::Widget::cast( cv::viz::WCloudCollection::WCloudCollection() { - // Just create the actor + vtkSmartPointer append_filter = vtkSmartPointer::New(); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + mapper->SetInputConnection(append_filter->GetOutputPort()); + mapper->SetScalarModeToUsePointData(); + mapper->ImmediateModeRenderingOff(); + mapper->SetScalarRange(0, 255); + mapper->ScalarVisibilityOn(); + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->SetNumberOfCloudPoints(1); + actor->GetProperty()->SetInterpolationToFlat(); + actor->GetProperty()->BackfaceCullingOn(); + actor->SetMapper(mapper); + WidgetAccessor::setProp(*this, actor); } @@ -206,35 +219,11 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, co vtkSmartPointer polydata = VtkUtils::TransformPolydata(source->GetOutputPort(), pose); vtkSmartPointer actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); - CV_Assert("Incompatible widget type." && actor); + CV_Assert("Correctness check." && actor); - vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); - if (!mapper) - { - // This is the first cloud - mapper = vtkSmartPointer::New(); - mapper->SetScalarRange(0, 255); - mapper->SetScalarModeToUsePointData(); - mapper->ScalarVisibilityOn(); - mapper->ImmediateModeRenderingOff(); - VtkUtils::SetInputData(mapper, polydata); - - actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints()/10)); - actor->GetProperty()->SetInterpolationToFlat(); - actor->GetProperty()->BackfaceCullingOn(); - actor->SetMapper(mapper); - return; - } - - vtkPolyData *currdata = vtkPolyData::SafeDownCast(mapper->GetInput()); - CV_Assert("Cloud Widget without data" && currdata); - - vtkSmartPointer append_filter = vtkSmartPointer::New(); - VtkUtils::AddInputData(append_filter, currdata); + vtkSmartPointer producer = actor->GetMapper()->GetInputConnection(0, 0)->GetProducer(); + vtkSmartPointer append_filter = vtkAppendPolyData::SafeDownCast(producer); VtkUtils::AddInputData(append_filter, polydata); - append_filter->Update(); - - VtkUtils::SetInputData(mapper, append_filter->GetOutput()); actor->SetNumberOfCloudPoints(std::max(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10)); } @@ -244,6 +233,23 @@ void cv::viz::WCloudCollection::addCloud(InputArray cloud, const Color &color, c addCloud(cloud, Mat(cloud.size(), CV_8UC3, color), pose); } +void cv::viz::WCloudCollection::finalize() +{ + vtkSmartPointer actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); + CV_Assert("Incompatible widget type." && actor); + + vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); + CV_Assert("Need to add at least one cloud." && mapper); + + vtkSmartPointer producer = mapper->GetInputConnection(0, 0)->GetProducer(); + vtkSmartPointer append_filter = vtkAppendPolyData::SafeDownCast(producer); + append_filter->Update(); + + vtkSmartPointer polydata = append_filter->GetOutput(); + mapper->RemoveInputConnection(0, 0); + VtkUtils::SetInputData(mapper, polydata); +} + template<> cv::viz::WCloudCollection cv::viz::Widget::cast() { Widget3D widget = this->cast(); @@ -316,20 +322,18 @@ cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, in } } - vtkSmartPointer polyData = vtkSmartPointer::New(); - polyData->SetPoints(points); - polyData->SetLines(lines); + vtkSmartPointer polydata = vtkSmartPointer::New(); + polydata->SetPoints(points); + polydata->SetLines(lines); + VtkUtils::FillScalars(polydata, color); vtkSmartPointer mapper = vtkSmartPointer::New(); - mapper->SetColorModeToMapScalars(); - mapper->SetScalarModeToUsePointData(); - VtkUtils::SetInputData(mapper, polyData); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } template<> cv::viz::WCloudNormals cv::viz::Widget::cast() @@ -349,7 +353,7 @@ cv::viz::WMesh::WMesh(const Mesh &mesh) source->SetColorCloudNormalsTCoords(mesh.cloud, mesh.colors, mesh.normals, mesh.tcoords); source->Update(); - Mat lookup_buffer(1, mesh.cloud.total(), CV_32SC1); + Mat lookup_buffer(1, (int)mesh.cloud.total(), CV_32SC1); int *lookup = lookup_buffer.ptr(); for(int y = 0, index = 0; y < mesh.cloud.rows; ++y) { @@ -439,3 +443,63 @@ template<> CV_EXPORTS cv::viz::WMesh cv::viz::Widget::cast() Widget3D widget = this->cast(); return static_cast(widget); } + + +/////////////////////////////////////////////////////////////////////////////////////////////// +/// Widget Merger implementation + +cv::viz::WWidgetMerger::WWidgetMerger() +{ + vtkSmartPointer append_filter = vtkSmartPointer::New(); + + vtkSmartPointer mapper = vtkSmartPointer::New(); + mapper->SetInputConnection(append_filter->GetOutputPort()); + mapper->SetScalarModeToUsePointData(); + mapper->ImmediateModeRenderingOff(); + mapper->SetScalarRange(0, 255); + mapper->ScalarVisibilityOn(); + + vtkSmartPointer actor = vtkSmartPointer::New(); + actor->GetProperty()->SetInterpolationToFlat(); + actor->GetProperty()->BackfaceCullingOn(); + actor->SetMapper(mapper); + + WidgetAccessor::setProp(*this, actor); +} + +void cv::viz::WWidgetMerger::addWidget(const Widget3D& widget, const Affine3d &pose) +{ + vtkActor *widget_actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(widget)); + CV_Assert("Widget is not 3D actor." && widget_actor); + + vtkSmartPointer widget_mapper = vtkPolyDataMapper::SafeDownCast(widget_actor->GetMapper()); + CV_Assert("Widget doesn't have a polydata mapper" && widget_mapper); + widget_mapper->Update(); + + vtkSmartPointer actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this)); + vtkSmartPointer producer = actor->GetMapper()->GetInputConnection(0, 0)->GetProducer(); + vtkSmartPointer append_filter = vtkAppendPolyData::SafeDownCast(producer); + CV_Assert("Correctness check" && append_filter); + + VtkUtils::AddInputData(append_filter, VtkUtils::TransformPolydata(widget_mapper->GetInput(), pose)); +} + +void cv::viz::WWidgetMerger::finalize() +{ + vtkSmartPointer actor = vtkActor::SafeDownCast(WidgetAccessor::getProp(*this)); + vtkSmartPointer producer = actor->GetMapper()->GetInputConnection(0, 0)->GetProducer(); + vtkSmartPointer append_filter = vtkAppendPolyData::SafeDownCast(producer); + CV_Assert("Correctness check" && append_filter); + append_filter->Update(); + + vtkSmartPointer mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); + mapper->RemoveInputConnection(0, 0); + VtkUtils::SetInputData(mapper, append_filter->GetOutput()); + mapper->Modified(); +} + +template<> CV_EXPORTS cv::viz::WWidgetMerger cv::viz::Widget::cast() +{ + Widget3D widget = this->cast(); + return static_cast(widget); +} diff --git a/modules/viz/src/interactor_style.cpp b/modules/viz/src/interactor_style.cpp deleted file mode 100644 index 75003a2b66..0000000000 --- a/modules/viz/src/interactor_style.cpp +++ /dev/null @@ -1,639 +0,0 @@ -/*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. -// -// Authors: -// * Ozan Tonkal, ozantonkal@gmail.com -// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com -// -// OpenCV Viz module is complete rewrite of -// PCL visualization module (www.pointclouds.org) -// -//M*/ - -#include "precomp.hpp" - - -namespace cv { namespace viz -{ - vtkStandardNewMacro(InteractorStyle) -}} - - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::Initialize() -{ - // Set windows size (width, height) to unknown (-1) - win_size_ = Vec2i(-1, -1); - win_pos_ = Vec2i(0, 0); - max_win_size_ = Vec2i(-1, -1); - - init_ = true; - stereo_anaglyph_mask_default_ = true; - - // Initialize the keyboard event callback as none - keyboardCallback_ = 0; - keyboard_callback_cookie_ = 0; - - // Initialize the mouse event callback as none - mouseCallback_ = 0; - mouse_callback_cookie_ = 0; -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::saveScreenshot(const String &file) -{ - FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); - - vtkSmartPointer wif = vtkSmartPointer::New(); - wif->SetInput(Interactor->GetRenderWindow()); - - vtkSmartPointer snapshot_writer = vtkSmartPointer::New(); - snapshot_writer->SetInputConnection(wif->GetOutputPort()); - snapshot_writer->SetFileName(file.c_str()); - snapshot_writer->Write(); - - cout << "Screenshot successfully captured (" << file.c_str() << ")" << endl; -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::exportScene(const String &file) -{ - vtkSmartPointer exporter; - if (file.size() > 5 && file.substr(file.size() - 5) == ".vrml") - { - exporter = vtkSmartPointer::New(); - vtkVRMLExporter::SafeDownCast(exporter)->SetFileName(file.c_str()); - } - else - { - exporter = vtkSmartPointer::New(); - vtkOBJExporter::SafeDownCast(exporter)->SetFilePrefix(file.c_str()); - } - - exporter->SetInput(Interactor->GetRenderWindow()); - exporter->Write(); - - cout << "Scene successfully exported (" << file.c_str() << ")" << endl; -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::zoomIn() -{ - FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); - // Zoom in - StartDolly(); - double factor = 10.0 * 0.2 * .5; - Dolly(std::pow(1.1, factor)); - EndDolly(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::zoomOut() -{ - FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); - // Zoom out - StartDolly(); - double factor = 10.0 * -0.2 * .5; - Dolly(std::pow(1.1, factor)); - EndDolly(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnChar() -{ - // Make sure we ignore the same events we handle in OnKeyDown to avoid calling things twice - FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); - if (Interactor->GetKeyCode() >= '0' && Interactor->GetKeyCode() <= '9') - return; - - String key(Interactor->GetKeySym()); - if (key.find("XF86ZoomIn") != String::npos) - zoomIn(); - else if (key.find("XF86ZoomOut") != String::npos) - zoomOut(); - - int keymod = Interactor->GetAltKey(); - - switch (Interactor->GetKeyCode()) - { - // All of the options below simply exit - case 'h': case 'H': - case 'l': case 'L': - case 'p': case 'P': - case 'j': case 'J': - case 'c': case 'C': - case 43: // KEY_PLUS - case 45: // KEY_MINUS - case 'f': case 'F': - case 'g': case 'G': - case 'o': case 'O': - case 'u': case 'U': - case 'q': case 'Q': - { - break; - } - // S and R have a special !ALT case - case 'r': case 'R': - case 's': case 'S': - { - if (!keymod) - Superclass::OnChar(); - break; - } - default: - { - Superclass::OnChar(); - break; - } - } -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::registerMouseCallback(void (*callback)(const MouseEvent&, void*), void* cookie) -{ - // Register the callback function and store the user data - mouseCallback_ = callback; - mouse_callback_cookie_ = cookie; -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void *cookie) -{ - // Register the callback function and store the user data - keyboardCallback_ = callback; - keyboard_callback_cookie_ = cookie; -} - -////////////////////////////////////////////////////////////////////////////////////////////// -int cv::viz::InteractorStyle::getModifiers() -{ - int modifiers = KeyboardEvent::NONE; - - if (Interactor->GetAltKey()) - modifiers |= KeyboardEvent::ALT; - - if (Interactor->GetControlKey()) - modifiers |= KeyboardEvent::CTRL; - - if (Interactor->GetShiftKey()) - modifiers |= KeyboardEvent::SHIFT; - return modifiers; -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnKeyDown() -{ - CV_Assert("Interactor style not initialized. Please call Initialize() before continuing" && init_); - FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); - - // Save the initial windows width/height - if (win_size_[0] == -1 || win_size_[1] == -1) - win_size_ = Vec2i(Interactor->GetRenderWindow()->GetSize()); - - bool alt = Interactor->GetAltKey() != 0; - - std::string key(Interactor->GetKeySym()); - if (key.find("XF86ZoomIn") != std::string::npos) - zoomIn(); - else if (key.find("XF86ZoomOut") != std::string::npos) - zoomOut(); - - switch (Interactor->GetKeyCode()) - { - case 'h': case 'H': - { - std::cout << "| Help:\n" - "-------\n" - " p, P : switch to a point-based representation\n" - " w, W : switch to a wireframe-based representation (where available)\n" - " s, S : switch to a surface-based representation (where available)\n" - "\n" - " j, J : take a .PNG snapshot of the current window view\n" - " k, K : export scene to Wavefront .obj format\n" - " ALT + k, K : export scene to VRML format\n" - " c, C : display current camera/window parameters\n" - " f, F : fly to point mode, hold the key and move mouse where to fly\n" - "\n" - " e, E : exit the interactor\n" - " q, Q : stop and call VTK's TerminateApp\n" - "\n" - " +/- : increment/decrement overall point size\n" - " +/- [+ ALT] : zoom in/out \n" - "\n" - " r, R [+ ALT] : reset camera [to viewpoint = {0, 0, 0} -> center_{x, y, z}]\n" - "\n" - " ALT + s, S : turn stereo mode on/off\n" - " ALT + f, F : switch between maximized window mode and original size\n" - "\n" - << std::endl; - break; - } - - // Switch representation to points - case 'p': case 'P': - { - vtkSmartPointer ac = CurrentRenderer->GetActors(); - vtkCollectionSimpleIterator ait; - for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) - for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) - { - vtkActor* apart = vtkActor::SafeDownCast(path->GetLastNode()->GetViewProp()); - apart->GetProperty()->SetRepresentationToPoints(); - } - break; - } - - // Save a PNG snapshot - case 'j': case 'J': - saveScreenshot(cv::format("screenshot-%d.png", (unsigned int)time(0))); break; - - // Export scene as in obj or vrml format - case 'k': case 'K': - { - String format = alt ? "scene-%d.vrml" : "scene-%d"; - exportScene(cv::format(format.c_str(), (unsigned int)time(0))); - break; - } - - // display current camera settings/parameters - case 'c': case 'C': - { - vtkSmartPointer cam = Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera(); - - Vec2d clip(cam->GetClippingRange()); - Vec3d focal(cam->GetFocalPoint()), pos(cam->GetPosition()), view(cam->GetViewUp()); - Vec2i win_pos(Interactor->GetRenderWindow()->GetPosition()); - Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); - double angle = cam->GetViewAngle () / 180.0 * CV_PI; - - String data = cv::format("clip(%f,%f) focal(%f,%f,%f) pos(%f,%f,%f) view(%f,%f,%f) angle(%f) winsz(%d,%d) winpos(%d,%d)", - clip[0], clip[1], focal[0], focal[1], focal[2], pos[0], pos[1], pos[2], view[0], view[1], view[2], - angle, win_size[0], win_size[1], win_pos[0], win_pos[1]); - - std::cout << data.c_str() << std::endl; - - break; - } - case '=': - { - zoomIn(); - break; - } - case 43: // KEY_PLUS - { - if (alt) - zoomIn(); - else - { - vtkSmartPointer ac = CurrentRenderer->GetActors(); - vtkCollectionSimpleIterator ait; - for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) - for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) - { - vtkActor* apart = vtkActor::SafeDownCast(path->GetLastNode()->GetViewProp()); - float psize = apart->GetProperty()->GetPointSize(); - if (psize < 63.0f) - apart->GetProperty()->SetPointSize(psize + 1.0f); - } - } - break; - } - case 45: // KEY_MINUS - { - if (alt) - zoomOut(); - else - { - vtkSmartPointer ac = CurrentRenderer->GetActors(); - vtkCollectionSimpleIterator ait; - for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) - for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) - { - vtkActor* apart = vtkActor::SafeDownCast(path->GetLastNode()->GetViewProp()); - float psize = apart->GetProperty()->GetPointSize(); - if (psize > 1.0f) - apart->GetProperty()->SetPointSize(psize - 1.0f); - } - } - break; - } - // Switch between maximize and original window size - case 'f': case 'F': - { - if (alt) - { - Vec2i screen_size(Interactor->GetRenderWindow()->GetScreenSize()); - Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); - - // Is window size = max? - if (win_size == max_win_size_) - { - Interactor->GetRenderWindow()->SetSize(win_size_.val); - Interactor->GetRenderWindow()->SetPosition(win_pos_.val); - Interactor->GetRenderWindow()->Render(); - Interactor->Render(); - } - // Set to max - else - { - win_pos_ = Vec2i(Interactor->GetRenderWindow()->GetPosition()); - win_size_ = win_size; - - Interactor->GetRenderWindow()->SetSize(screen_size.val); - Interactor->GetRenderWindow()->Render(); - Interactor->Render(); - max_win_size_ = Vec2i(Interactor->GetRenderWindow()->GetSize()); - } - } - else - { - AnimState = VTKIS_ANIM_ON; - Interactor->GetPicker()->Pick(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1], 0.0, CurrentRenderer); - vtkSmartPointer picker = vtkAbstractPropPicker::SafeDownCast(Interactor->GetPicker()); - if (picker) - if (picker->GetPath()) - Interactor->FlyTo(CurrentRenderer, picker->GetPickPosition()); - AnimState = VTKIS_ANIM_OFF; - } - break; - } - // 's'/'S' w/out ALT - case 's': case 'S': - { - if (alt) - { - vtkSmartPointer window = Interactor->GetRenderWindow(); - if (!window->GetStereoRender()) - { - static Vec2i red_blue(4, 3), magenta_green(2, 5); - window->SetAnaglyphColorMask (stereo_anaglyph_mask_default_ ? red_blue.val : magenta_green.val); - stereo_anaglyph_mask_default_ = !stereo_anaglyph_mask_default_; - } - window->SetStereoRender(!window->GetStereoRender()); - Interactor->Render(); - } - else - Superclass::OnKeyDown(); - break; - } - - case 'o': case 'O': - { - vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); - cam->SetParallelProjection(!cam->GetParallelProjection()); - CurrentRenderer->Render(); - break; - } - - // Overwrite the camera reset - case 'r': case 'R': - { - if (!alt) - { - Superclass::OnKeyDown(); - break; - } - - WidgetActorMap::iterator it = widget_actor_map_->begin(); - // it might be that some actors don't have a valid transformation set -> we skip them to avoid a seg fault. - for (; it != widget_actor_map_->end(); ++it) - { - vtkProp3D * actor = vtkProp3D::SafeDownCast(it->second); - if (actor && actor->GetUserMatrix()) - break; - } - - vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); - - // if a valid transformation was found, use it otherwise fall back to default view point. - if (it != widget_actor_map_->end()) - { - vtkMatrix4x4* m = vtkProp3D::SafeDownCast(it->second)->GetUserMatrix(); - - cam->SetFocalPoint(m->GetElement(0, 3) - m->GetElement(0, 2), - m->GetElement(1, 3) - m->GetElement(1, 2), - m->GetElement(2, 3) - m->GetElement(2, 2)); - - cam->SetViewUp (m->GetElement(0, 1), m->GetElement(1, 1), m->GetElement(2, 1)); - cam->SetPosition(m->GetElement(0, 3), m->GetElement(1, 3), m->GetElement(2, 3)); - } - else - { - cam->SetPosition(0, 0, 0); - cam->SetFocalPoint(0, 0, 1); - cam->SetViewUp(0, -1, 0); - } - - // go to the next actor for the next key-press event. - if (it != widget_actor_map_->end()) - ++it; - else - it = widget_actor_map_->begin(); - - CurrentRenderer->SetActiveCamera(cam); - CurrentRenderer->ResetCameraClippingRange(); - CurrentRenderer->Render(); - break; - } - - case 'q': case 'Q': - { - Interactor->ExitCallback(); - return; - } - default: - { - Superclass::OnKeyDown(); - break; - } - } - - KeyboardEvent event(KeyboardEvent::KEY_DOWN, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); - if (keyboardCallback_) - keyboardCallback_(event, keyboard_callback_cookie_); - Interactor->Render(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnKeyUp() -{ - KeyboardEvent event(KeyboardEvent::KEY_UP, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); - if (keyboardCallback_) - keyboardCallback_(event, keyboard_callback_cookie_); - Superclass::OnKeyUp(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnMouseMove() -{ - Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseMove, MouseEvent::NoButton, p, getModifiers()); - if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); - Superclass::OnMouseMove(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnLeftButtonDown() -{ - Vec2i p(Interactor->GetEventPosition()); - MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; - MouseEvent event(type, MouseEvent::LeftButton, p, getModifiers()); - if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); - Superclass::OnLeftButtonDown(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnLeftButtonUp() -{ - Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::LeftButton, p, getModifiers()); - if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); - Superclass::OnLeftButtonUp(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnMiddleButtonDown() -{ - Vec2i p(Interactor->GetEventPosition()); - MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; - MouseEvent event(type, MouseEvent::MiddleButton, p, getModifiers()); - if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); - Superclass::OnMiddleButtonDown(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnMiddleButtonUp() -{ - Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::MiddleButton, p, getModifiers()); - if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); - Superclass::OnMiddleButtonUp(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnRightButtonDown() -{ - Vec2i p(Interactor->GetEventPosition()); - MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; - MouseEvent event(type, MouseEvent::RightButton, p, getModifiers()); - if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); - Superclass::OnRightButtonDown(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnRightButtonUp() -{ - Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::RightButton, p, getModifiers()); - if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); - Superclass::OnRightButtonUp(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnMouseWheelForward() -{ - Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getModifiers()); - if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); - if (Interactor->GetRepeatCount() && mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); - - if (Interactor->GetAltKey()) - { - // zoom - vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); - double opening_angle = cam->GetViewAngle(); - if (opening_angle > 15.0) - opening_angle -= 1.0; - - cam->SetViewAngle(opening_angle); - cam->Modified(); - CurrentRenderer->ResetCameraClippingRange(); - CurrentRenderer->Modified(); - CurrentRenderer->Render(); - Interactor->Render(); - } - else - Superclass::OnMouseWheelForward(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnMouseWheelBackward() -{ - Vec2i p(Interactor->GetEventPosition()); - MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getModifiers()); - if (mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); - - if (Interactor->GetRepeatCount() && mouseCallback_) - mouseCallback_(event, mouse_callback_cookie_); - - if (Interactor->GetAltKey()) - { - // zoom - vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); - double opening_angle = cam->GetViewAngle(); - if (opening_angle < 170.0) - opening_angle += 1.0; - - cam->SetViewAngle(opening_angle); - cam->Modified(); - CurrentRenderer->ResetCameraClippingRange(); - CurrentRenderer->Modified(); - CurrentRenderer->Render(); - Interactor->Render(); - } - else - Superclass::OnMouseWheelBackward(); -} - -////////////////////////////////////////////////////////////////////////////////////////////// -void cv::viz::InteractorStyle::OnTimer() -{ - CV_Assert("Interactor style not initialized." && init_); - Interactor->Render(); -} diff --git a/modules/viz/src/precomp.hpp b/modules/viz/src/precomp.hpp index d9681ce83b..feaca852e3 100644 --- a/modules/viz/src/precomp.hpp +++ b/modules/viz/src/precomp.hpp @@ -76,7 +76,6 @@ #include #include #include -#include #include #include #include @@ -115,11 +114,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -133,6 +130,7 @@ #include #include #include +#include "vtkCallbackCommand.h" #if !defined(_WIN32) || defined(__CYGWIN__) # include /* unlink */ @@ -142,11 +140,13 @@ #include #include +#include #include #include #include #include + #include #include #include @@ -157,7 +157,16 @@ namespace cv namespace viz { typedef std::map > WidgetActorMap; - typedef std::map VizMap; + + struct VizMap + { + typedef std::map type; + typedef type::iterator iterator; + + type m; + ~VizMap(); + void replace_clear(); + }; class VizStorage { @@ -169,7 +178,6 @@ namespace cv private: VizStorage(); // Static - ~VizStorage(); static void add(const Viz3d& window); static Viz3d& get(const String &window_name); @@ -179,6 +187,8 @@ namespace cv static VizMap storage; friend class Viz3d; + + static VizStorage init; }; template inline _Tp normalized(const _Tp& v) { return v * 1/norm(v); } @@ -269,11 +279,16 @@ namespace cv vtkSmartPointer scalars = vtkSmartPointer::New(); scalars->SetName("Colors"); scalars->SetNumberOfComponents(3); - scalars->SetNumberOfTuples(size); - scalars->SetArray(color_data->val, size * 3, 0); + scalars->SetNumberOfTuples((vtkIdType)size); + scalars->SetArray(color_data->val, (vtkIdType)(size * 3), 0); return scalars; } + static vtkSmartPointer FillScalars(vtkSmartPointer polydata, const Color& color) + { + return polydata->GetPointData()->SetScalars(FillScalars(polydata->GetNumberOfPoints(), color)), polydata; + } + static vtkSmartPointer ComputeNormals(vtkSmartPointer polydata) { vtkSmartPointer normals_generator = vtkSmartPointer::New(); @@ -314,11 +329,12 @@ namespace cv return transform_filter->GetOutput(); } }; + + vtkSmartPointer vtkCocoaRenderWindowInteractorNew(); } } -#include "interactor_style.hpp" +#include "vtk/vtkVizInteractorStyle.hpp" #include "vizimpl.hpp" - #endif diff --git a/modules/viz/src/shapes.cpp b/modules/viz/src/shapes.cpp index f3d24f757c..4dd77038ec 100644 --- a/modules/viz/src/shapes.cpp +++ b/modules/viz/src/shapes.cpp @@ -54,14 +54,16 @@ cv::viz::WLine::WLine(const Point3d &pt1, const Point3d &pt2, const Color &color line->SetPoint2(pt2.x, pt2.y, pt2.z); line->Update(); + vtkSmartPointer polydata = line->GetOutput(); + VtkUtils::FillScalars(polydata, color); + vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, line->GetOutput()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } template<> cv::viz::WLine cv::viz::Widget::cast() @@ -83,14 +85,16 @@ cv::viz::WSphere::WSphere(const Point3d ¢er, double radius, int sphere_resol sphere->LatLongTessellationOff(); sphere->Update(); + vtkSmartPointer polydata = sphere->GetOutput(); + VtkUtils::FillScalars(polydata, color); + vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, sphere->GetOutput()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } template<> cv::viz::WSphere cv::viz::Widget::cast() @@ -110,15 +114,17 @@ cv::viz::WPlane::WPlane(const Size2d& size, const Color &color) plane->SetPoint2(-0.5 * size.width, 0.5 * size.height, 0.0); plane->Update(); + vtkSmartPointer polydata = plane->GetOutput(); + VtkUtils::FillScalars(polydata, color); + vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, plane->GetOutput()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); actor->GetProperty()->LightingOff(); WidgetAccessor::setProp(*this, actor); - setColor(color); } cv::viz::WPlane::WPlane(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, const Size2d& size, const Color &color) @@ -161,6 +167,7 @@ cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness Affine3d transform_with_scale(R * length, start_point); vtkSmartPointer polydata = VtkUtils::TransformPolydata(arrow_source->GetOutputPort(), transform_with_scale); + VtkUtils::FillScalars(polydata, color); vtkSmartPointer mapper = vtkSmartPointer::New(); VtkUtils::SetInputData(mapper, polydata); @@ -169,7 +176,6 @@ cv::viz::WArrow::WArrow(const Point3d& pt1, const Point3d& pt2, double thickness actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } template<> cv::viz::WArrow cv::viz::Widget::cast() @@ -189,16 +195,17 @@ cv::viz::WCircle::WCircle(double radius, double thickness, const Color &color) disk->SetOuterRadius(radius + thickness); disk->Update(); + vtkSmartPointer polydata = disk->GetOutput(); + VtkUtils::FillScalars(polydata, color); + vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, disk->GetOutput()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->GetProperty()->LightingOff(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); - } cv::viz::WCircle::WCircle(double radius, const Point3d& center, const Vec3d& normal, double thickness, const Color &color) @@ -231,14 +238,16 @@ cv::viz::WCone::WCone(double length, double radius, int resolution, const Color cone_source->SetResolution(resolution); cone_source->Update(); + vtkSmartPointer polydata = cone_source->GetOutput(); + VtkUtils::FillScalars(polydata, color); + vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, cone_source->GetOutput()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } cv::viz::WCone::WCone(double radius, const Point3d& center, const Point3d& tip, int resolution, const Color &color) @@ -274,14 +283,16 @@ cv::viz::WCylinder::WCylinder(const Point3d& axis_point1, const Point3d& axis_po tuber->SetRadius(radius); tuber->Update(); + vtkSmartPointer polydata = tuber->GetOutput(); + VtkUtils::FillScalars(polydata, color); + vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, tuber->GetOutput()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } template<> cv::viz::WCylinder cv::viz::Widget::cast() @@ -315,15 +326,16 @@ cv::viz::WCube::WCube(const Point3d& min_point, const Point3d& max_point, bool w vtkCubeSource::SafeDownCast(cube)->SetBounds(bounds); } cube->Update(); + vtkSmartPointer polydata =cube->GetOutput(); + VtkUtils::FillScalars(polydata, color); vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, cube->GetOutput()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } template<> cv::viz::WCube cv::viz::Widget::cast() @@ -379,40 +391,21 @@ template<> cv::viz::WCoordinateSystem cv::viz::Widget::cast(); - const double *dpoints = _points.getMat().ptr(); - size_t total = _points.total(); - int s_chs = _points.channels(); - - vtkSmartPointer points = vtkSmartPointer::New(); - points->SetDataType(_points.depth() == CV_32F ? VTK_FLOAT : VTK_DOUBLE); - points->SetNumberOfPoints(total); + vtkSmartPointer cloud_source = vtkSmartPointer::New(); + cloud_source->SetColorCloud(points, colors); + cloud_source->Update(); - if (_points.depth() == CV_32F) - for(size_t i = 0; i < total; ++i, fpoints += s_chs) - points->SetPoint(i, fpoints); - - if (_points.depth() == CV_64F) - for(size_t i = 0; i < total; ++i, dpoints += s_chs) - points->SetPoint(i, dpoints); + vtkSmartPointer polydata = cloud_source->GetOutput(); vtkSmartPointer cell_array = vtkSmartPointer::New(); - cell_array->Allocate(cell_array->EstimateSize(1, total)); - cell_array->InsertNextCell(total); - for(size_t i = 0; i < total; ++i) + cell_array->Allocate(cell_array->EstimateSize(1, polydata->GetNumberOfPoints())); + cell_array->InsertNextCell(polydata->GetNumberOfPoints()); + for(vtkIdType i = 0; i < polydata->GetNumberOfPoints(); ++i) cell_array->InsertCellPoint(i); - vtkSmartPointer scalars = VtkUtils::FillScalars(total, color); - - vtkSmartPointer polydata = vtkSmartPointer::New(); - polydata->SetPoints(points); polydata->SetLines(cell_array); - polydata->GetPointData()->SetScalars(scalars); - vtkSmartPointer mapper = vtkSmartPointer::New(); VtkUtils::SetInputData(mapper, polydata); mapper->SetScalarRange(0, 255); @@ -423,6 +416,12 @@ cv::viz::WPolyLine::WPolyLine(InputArray _points, const Color &color) WidgetAccessor::setProp(*this, actor); } +cv::viz::WPolyLine::WPolyLine(InputArray points, const Color &color) +{ + WPolyLine polyline(points, Mat(points.size(), CV_8UC3, color)); + *this = polyline; +} + template<> cv::viz::WPolyLine cv::viz::Widget::cast() { Widget3D widget = this->cast(); @@ -450,14 +449,16 @@ cv::viz::WGrid::WGrid(const Vec2i &cells, const Vec2d &cells_spacing, const Colo VtkUtils::SetInputData(extract_edges, grid_data); extract_edges->Update(); + vtkSmartPointer polydata = extract_edges->GetOutput(); + VtkUtils::FillScalars(polydata, color); + vtkSmartPointer mapper = vtkSmartPointer::New(); - VtkUtils::SetInputData(mapper, extract_edges->GetOutput()); + VtkUtils::SetInputData(mapper, polydata); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } cv::viz::WGrid::WGrid(const Point3d& center, const Vec3d& normal, const Vec3d& new_yaxis, const Vec2i &cells, const Vec2d &cells_spacing, const Color &color) @@ -807,6 +808,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const double aspect_ratio = f_y / f_x; vtkSmartPointer polydata = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); + VtkUtils::FillScalars(polydata, color); vtkSmartPointer mapper = vtkSmartPointer::New(); VtkUtils::SetInputData(mapper, polydata); @@ -815,7 +817,6 @@ cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, double scale, const actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const Color &color) @@ -824,6 +825,7 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const double fovy = fov[1] * 180 / CV_PI; vtkSmartPointer polydata = CameraPositionUtils::createFrustum(aspect_ratio, fovy, scale); + VtkUtils::FillScalars(polydata, color); vtkSmartPointer mapper = vtkSmartPointer::New(); VtkUtils::SetInputData(mapper, polydata); @@ -832,7 +834,6 @@ cv::viz::WCameraPosition::WCameraPosition(const Vec2d &fov, double scale, const actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } cv::viz::WCameraPosition::WCameraPosition(const Matx33d &K, InputArray _image, double scale, const Color &color) @@ -967,6 +968,7 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Matx33 source->SetTrajectory(_path); vtkSmartPointer glyph = getPolyData(WCameraPosition(K, scale)); + VtkUtils::FillScalars(glyph, color); vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); tensor_glyph->SetInputConnection(source->GetOutputPort()); @@ -984,7 +986,6 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Matx33 actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d &fov, double scale, const Color &color) @@ -993,6 +994,7 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d source->SetTrajectory(_path); vtkSmartPointer glyph = getPolyData(WCameraPosition(fov, scale)); + VtkUtils::FillScalars(glyph, color); vtkSmartPointer tensor_glyph = vtkSmartPointer::New(); tensor_glyph->SetInputConnection(source->GetOutputPort()); @@ -1010,7 +1012,6 @@ cv::viz::WTrajectoryFrustums::WTrajectoryFrustums(InputArray _path, const Vec2d actor->SetMapper(mapper); WidgetAccessor::setProp(*this, actor); - setColor(color); } template<> cv::viz::WTrajectoryFrustums cv::viz::Widget::cast() diff --git a/modules/viz/src/viz3d.cpp b/modules/viz/src/viz3d.cpp index 56f978c0ea..6e7dfcae78 100644 --- a/modules/viz/src/viz3d.cpp +++ b/modules/viz/src/viz3d.cpp @@ -146,3 +146,5 @@ void cv::viz::Viz3d::setRenderingProperty(const String &id, int property, double double cv::viz::Viz3d::getRenderingProperty(const String &id, int property) { return getWidget(id).getRenderingProperty(property); } void cv::viz::Viz3d::setRepresentation(int representation) { impl_->setRepresentation(representation); } + +void cv::viz::Viz3d::setGlobalWarnings(bool enabled) { vtkObject::SetGlobalWarningDisplay(enabled ? 1 : 0); } diff --git a/modules/viz/src/vizcore.cpp b/modules/viz/src/vizcore.cpp index b4ec83bd44..a33a192c6c 100644 --- a/modules/viz/src/vizcore.cpp +++ b/modules/viz/src/vizcore.cpp @@ -67,36 +67,71 @@ cv::Affine3d cv::viz::makeCameraPose(const Vec3d& position, const Vec3d& focal_p /////////////////////////////////////////////////////////////////////////////////////////////// /// VizStorage implementation +#if defined(_WIN32) && !defined(__CYGWIN__) + + #include + + static BOOL WINAPI ConsoleHandlerRoutine(DWORD /*dwCtrlType*/) + { + vtkObject::GlobalWarningDisplayOff(); + return FALSE; + } + + static void register_console_handler() + { + HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO hOutInfo; + if (GetConsoleScreenBufferInfo(hOut, &hOutInfo)) + SetConsoleCtrlHandler(ConsoleHandlerRoutine, TRUE); + } + +#else + + void register_console_handler(); + void register_console_handler() {} + +#endif + + +cv::viz::VizStorage cv::viz::VizStorage::init; cv::viz::VizMap cv::viz::VizStorage::storage; -void cv::viz::VizStorage::unregisterAll() { storage.clear(); } + +void cv::viz::VizMap::replace_clear() { type().swap(m); } +cv::viz::VizMap::~VizMap() { replace_clear(); } + +cv::viz::VizStorage::VizStorage() +{ + register_console_handler(); +} +void cv::viz::VizStorage::unregisterAll() { storage.replace_clear(); } cv::viz::Viz3d& cv::viz::VizStorage::get(const String &window_name) { String name = generateWindowName(window_name); - VizMap::iterator vm_itr = storage.find(name); - CV_Assert(vm_itr != storage.end()); + VizMap::iterator vm_itr = storage.m.find(name); + CV_Assert(vm_itr != storage.m.end()); return vm_itr->second; } void cv::viz::VizStorage::add(const Viz3d& window) { String window_name = window.getWindowName(); - VizMap::iterator vm_itr = storage.find(window_name); - CV_Assert(vm_itr == storage.end()); - storage.insert(std::make_pair(window_name, window)); + VizMap::iterator vm_itr = storage.m.find(window_name); + CV_Assert(vm_itr == storage.m.end()); + storage.m.insert(std::make_pair(window_name, window)); } bool cv::viz::VizStorage::windowExists(const String &window_name) { String name = generateWindowName(window_name); - return storage.find(name) != storage.end(); + return storage.m.find(name) != storage.m.end(); } void cv::viz::VizStorage::removeUnreferenced() { - for(VizMap::iterator pos = storage.begin(); pos != storage.end();) + for(VizMap::iterator pos = storage.m.begin(); pos != storage.m.end();) if(pos->second.impl_->ref_counter == 1) - storage.erase(pos++); + storage.m.erase(pos++); else ++pos; } @@ -173,8 +208,8 @@ cv::Mat cv::viz::readCloud(const String& file, OutputArray colors, OutputArray n vtkSmartPointer reader; if (extention == ".xyz") { - reader = vtkSmartPointer::New(); - vtkSimplePointsReader::SafeDownCast(reader)->SetFileName(file.c_str()); + reader = vtkSmartPointer::New(); + vtkXYZReader::SafeDownCast(reader)->SetFileName(file.c_str()); } else if (extention == ".ply") { @@ -257,7 +292,11 @@ void cv::viz::writeTrajectory(InputArray _traj, const String& files_format, int { if (_traj.kind() == _InputArray::STD_VECTOR_MAT) { +#if CV_MAJOR_VERSION < 3 std::vector& v = *(std::vector*)_traj.obj; +#else + std::vector& v = *(std::vector*)_traj.getObj(); +#endif for(size_t i = 0, index = max(0, start); i < v.size(); ++i, ++index) { @@ -278,11 +317,12 @@ void cv::viz::writeTrajectory(InputArray _traj, const String& files_format, int if (traj.depth() == CV_32F) for(size_t i = 0, index = max(0, start); i < traj.total(); ++i, ++index) - writePose(cv::format(files_format.c_str(), index), traj.at(i), tag); + writePose(cv::format(files_format.c_str(), index), traj.at((int)i), tag); if (traj.depth() == CV_64F) for(size_t i = 0, index = max(0, start); i < traj.total(); ++i, ++index) - writePose(cv::format(files_format.c_str(), index), traj.at(i), tag); + writePose(cv::format(files_format.c_str(), index), traj.at((int)i), tag); + return; } CV_Assert(!"Unsupported array kind"); diff --git a/modules/viz/src/vizimpl.cpp b/modules/viz/src/vizimpl.cpp index 5fa49e2f96..ab621ad16d 100644 --- a/modules/viz/src/vizimpl.cpp +++ b/modules/viz/src/vizimpl.cpp @@ -60,16 +60,19 @@ cv::viz::Viz3d::VizImpl::VizImpl(const String &name) : spin_once_state_(false), window_->AddRenderer(renderer_); // Create the interactor style - style_ = vtkSmartPointer::New(); + style_ = vtkSmartPointer::New(); style_->setWidgetActorMap(widget_actor_map_); style_->UseTimersOn(); - style_->Initialize(); timer_callback_ = vtkSmartPointer::New(); exit_callback_ = vtkSmartPointer::New(); exit_callback_->viz = this; + + setBackgroundMeshLab(); } +cv::viz::Viz3d::VizImpl::~VizImpl() { close(); } + ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::TimerCallback::Execute(vtkObject* caller, unsigned long event_id, void* cookie) { @@ -109,11 +112,12 @@ void cv::viz::Viz3d::VizImpl::close() void cv::viz::Viz3d::VizImpl::recreateRenderWindow() { -#if !defined _MSC_VER +#if !defined _MSC_VER && !defined __APPLE__ //recreating is workaround for Ubuntu -- a crash in x-server Vec2i window_size(window_->GetSize()); int fullscreen = window_->GetFullScreen(); + window_->Finalize(); window_ = vtkSmartPointer::New(); if (window_position_[0] != std::numeric_limits::min()) //also workaround window_->SetPosition(window_position_.val); @@ -124,12 +128,15 @@ void cv::viz::Viz3d::VizImpl::recreateRenderWindow() #endif } - ///////////////////////////////////////////////////////////////////////////////////////////// void cv::viz::Viz3d::VizImpl::spin() { recreateRenderWindow(); +#if defined __APPLE__ + interactor_ = vtkCocoaRenderWindowInteractorNew(); +#else interactor_ = vtkSmartPointer::New(); +#endif interactor_->SetRenderWindow(window_); interactor_->SetInteractorStyle(style_); window_->AlphaBitPlanesOff(); @@ -151,7 +158,11 @@ void cv::viz::Viz3d::VizImpl::spinOnce(int time, bool force_redraw) { spin_once_state_ = true; recreateRenderWindow(); +#if defined __APPLE__ + interactor_ = vtkCocoaRenderWindowInteractorNew(); +#else interactor_ = vtkSmartPointer::New(); +#endif interactor_->SetRenderWindow(window_); interactor_->SetInteractorStyle(style_); interactor_->AddObserver(vtkCommand::TimerEvent, timer_callback_); @@ -416,12 +427,12 @@ void cv::viz::Viz3d::VizImpl::setViewerPose(const Affine3d &pose) // Rotate the view vector cv::Matx33d rotation = pose.rotation(); - cv::Vec3d y_axis(0.0, 1.0, 0.0); + cv::Vec3d y_axis(0.0, -1.0, 0.0); // In Computer Vision Camera Y-axis is oriented down cv::Vec3d up_vec(rotation * y_axis); // Compute the new focal point cv::Vec3d z_axis(0.0, 0.0, 1.0); - cv::Vec3d focal_vec = pos_vec + rotation * z_axis; + cv::Vec3d focal_vec = pose * z_axis; camera.SetPosition(pos_vec.val); camera.SetFocalPoint(focal_vec.val); @@ -439,7 +450,7 @@ cv::Affine3d cv::viz::Viz3d::VizImpl::getViewerPose() Vec3d view_up(camera.GetViewUp()); Vec3d focal(camera.GetFocalPoint()); - Vec3d y_axis = normalized(view_up); + Vec3d y_axis = normalized(-view_up); // In Computer Vision Camera Y-axis is oriented down Vec3d z_axis = normalized(focal - pos); Vec3d x_axis = normalized(y_axis.cross(z_axis)); diff --git a/modules/viz/src/vizimpl.hpp b/modules/viz/src/vizimpl.hpp index 02675e0a5c..92113afa02 100644 --- a/modules/viz/src/vizimpl.hpp +++ b/modules/viz/src/vizimpl.hpp @@ -55,7 +55,7 @@ public: int ref_counter; VizImpl(const String &name); - virtual ~VizImpl() {} + virtual ~VizImpl(); bool wasStopped() const; void close(); @@ -128,7 +128,7 @@ private: vtkSmartPointer exit_callback_; vtkSmartPointer renderer_; - vtkSmartPointer style_; + vtkSmartPointer style_; Ptr widget_actor_map_; bool removeActorFromRenderer(vtkSmartPointer actor); diff --git a/modules/viz/src/vtk/vtkCloudMatSink.cpp b/modules/viz/src/vtk/vtkCloudMatSink.cpp index 09ef0cca99..8bd1011323 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSink.cpp @@ -79,11 +79,11 @@ void cv::viz::vtkCloudMatSink::WriteData() if (cloud.depth() == CV_32F) for(size_t i = 0; i < cloud.total(); ++i) - *fdata++ = Vec3d(points_Data->GetPoint(i)); + *fdata++ = Vec3d(points_Data->GetPoint((vtkIdType)i)); if (cloud.depth() == CV_64F) for(size_t i = 0; i < cloud.total(); ++i) - *ddata++ = Vec3d(points_Data->GetPoint(i)); + *ddata++ = Vec3d(points_Data->GetPoint((vtkIdType)i)); } else cloud.release(); @@ -101,7 +101,7 @@ void cv::viz::vtkCloudMatSink::WriteData() Mat buffer(cloud.size(), CV_64FC(channels)); Vec3d *cptr = buffer.ptr(); for(size_t i = 0; i < buffer.total(); ++i) - *cptr++ = Vec3d(scalars_data->GetTuple(i)); + *cptr++ = Vec3d(scalars_data->GetTuple((vtkIdType)i)); buffer.convertTo(colors, CV_8U, vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE ? 255.0 : 1.0); } @@ -121,7 +121,7 @@ void cv::viz::vtkCloudMatSink::WriteData() Mat buffer(cloud.size(), CV_64FC(channels)); Vec3d *cptr = buffer.ptr(); for(size_t i = 0; i < buffer.total(); ++i) - *cptr++ = Vec3d(normals_data->GetTuple(i)); + *cptr++ = Vec3d(normals_data->GetTuple((vtkIdType)i)); buffer.convertTo(normals, vtktype == VTK_FLOAT ? CV_32F : CV_64F); } @@ -140,7 +140,7 @@ void cv::viz::vtkCloudMatSink::WriteData() Mat buffer(cloud.size(), CV_64FC2); Vec2d *cptr = buffer.ptr(); for(size_t i = 0; i < buffer.total(); ++i) - *cptr++ = Vec2d(coords_data->GetTuple(i)); + *cptr++ = Vec2d(coords_data->GetTuple((vtkIdType)i)); buffer.convertTo(tcoords, vtktype == VTK_FLOAT ? CV_32F : CV_64F); @@ -156,3 +156,19 @@ void cv::viz::vtkCloudMatSink::PrintSelf(ostream& os, vtkIndent indent) os << indent << "Colors: " << colors.needed() << "\n"; os << indent << "Normals: " << normals.needed() << "\n"; } + +int cv::viz::vtkCloudMatSink::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; +} + +vtkPolyData* cv::viz::vtkCloudMatSink::GetInput() +{ + return vtkPolyData::SafeDownCast(this->Superclass::GetInput()); +} + +vtkPolyData* cv::viz::vtkCloudMatSink::GetInput(int port) +{ + return vtkPolyData::SafeDownCast(this->Superclass::GetInput(port)); +} diff --git a/modules/viz/src/vtk/vtkCloudMatSink.h b/modules/viz/src/vtk/vtkCloudMatSink.h index 44d7e52a5a..b3fd3eb719 100644 --- a/modules/viz/src/vtk/vtkCloudMatSink.h +++ b/modules/viz/src/vtk/vtkCloudMatSink.h @@ -46,26 +46,32 @@ #define __vtkCloudMatSink_h #include -#include +#include namespace cv { namespace viz { - class vtkCloudMatSink : public vtkPolyDataWriter + class vtkCloudMatSink : public vtkWriter { public: static vtkCloudMatSink *New(); - vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter) + vtkTypeMacro(vtkCloudMatSink,vtkWriter) void PrintSelf(ostream& os, vtkIndent indent); void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray(), OutputArray tcoords = noArray()); + // Description: + // Get the input to this writer. + vtkPolyData* GetInput(); + vtkPolyData* GetInput(int port); + protected: vtkCloudMatSink(); ~vtkCloudMatSink(); void WriteData(); + int FillInputPortInformation(int port, vtkInformation *info); _OutputArray cloud, colors, normals, tcoords; diff --git a/modules/viz/src/vtk/vtkCloudMatSource.cpp b/modules/viz/src/vtk/vtkCloudMatSource.cpp index 74d01bbd01..1d8ab7894c 100644 --- a/modules/viz/src/vtk/vtkCloudMatSource.cpp +++ b/modules/viz/src/vtk/vtkCloudMatSource.cpp @@ -185,8 +185,8 @@ int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& cloud) CV_DbgAssert(DataType<_Tp>::depth == cloud.depth()); points = vtkSmartPointer::New(); points->SetDataType(VtkDepthTraits<_Tp>::data_type); - points->Allocate(cloud.total()); - points->SetNumberOfPoints(cloud.total()); + points->Allocate((vtkIdType)cloud.total()); + points->SetNumberOfPoints((vtkIdType)cloud.total()); int s_chs = cloud.channels(); int total = 0; diff --git a/modules/viz/src/vtk/vtkCocoaInteractorFix.mm b/modules/viz/src/vtk/vtkCocoaInteractorFix.mm new file mode 100644 index 0000000000..dad41b073e --- /dev/null +++ b/modules/viz/src/vtk/vtkCocoaInteractorFix.mm @@ -0,0 +1,211 @@ +/*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. +// +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +// This workaround code was taken from PCL library(www.pointclouds.org) +// +//M*/ + +#import +#include +#include +#include +#include + +//---------------------------------------------------------------------------- +@interface vtkCocoaServerFix : NSObject +{ + vtkCocoaRenderWindow* renWin; +} + ++ (id)cocoaServerWithRenderWindow:(vtkCocoaRenderWindow*)inRenderWindow; + +- (void)start; +- (void)stop; +- (void)breakEventLoop; + +@end + +//---------------------------------------------------------------------------- +@implementation vtkCocoaServerFix + +//---------------------------------------------------------------------------- +- (id)initWithRenderWindow:(vtkCocoaRenderWindow *)inRenderWindow +{ + self = [super init]; + if (self) + renWin = inRenderWindow; + return self; +} + +//---------------------------------------------------------------------------- ++ (id)cocoaServerWithRenderWindow:(vtkCocoaRenderWindow *)inRenderWindow +{ + vtkCocoaServerFix *server = [[[vtkCocoaServerFix alloc] initWithRenderWindow:inRenderWindow] autorelease]; + return server; +} + +//---------------------------------------------------------------------------- +- (void)start +{ + // Retrieve the NSWindow. + NSWindow *win = nil; + if (renWin) + { + win = reinterpret_cast (renWin->GetRootWindow ()); + + // We don't want to be informed of every window closing, so check for nil. + if (win != nil) + { + // Register for the windowWillClose notification in order to stop the run loop if the window closes. + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:win]; + } + } + // Start the NSApplication's run loop + NSApplication* application = [NSApplication sharedApplication]; + [application run]; +} + +//---------------------------------------------------------------------------- +- (void)stop +{ + [self breakEventLoop]; +} + +//---------------------------------------------------------------------------- +- (void)breakEventLoop +{ + NSApplication* application = [NSApplication sharedApplication]; + [application stop:application]; + + NSEvent *event = [NSEvent otherEventWithType:NSApplicationDefined + location:NSMakePoint(0.0,0.0) + modifierFlags:0 + timestamp:0 + windowNumber:-1 + context:nil + subtype:0 + data1:0 + data2:0]; + [application postEvent:event atStart:YES]; +} + +//---------------------------------------------------------------------------- +- (void)windowWillClose:(NSNotification*)aNotification +{ + (void)aNotification; + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc removeObserver:self name:NSWindowWillCloseNotification object:nil]; + + if (renWin) + { + int windowCreated = renWin->GetWindowCreated (); + if (windowCreated) + { + [self breakEventLoop]; + + // The NSWindow is closing, so prevent anyone from accidently using it + renWin->SetRootWindow(NULL); + } + } +} + +@end + +//---------------------------------------------------------------------------- + +namespace cv { namespace viz +{ + class vtkCocoaRenderWindowInteractorFix : public vtkCocoaRenderWindowInteractor + { + public: + static vtkCocoaRenderWindowInteractorFix *New (); + vtkTypeMacro (vtkCocoaRenderWindowInteractorFix, vtkCocoaRenderWindowInteractor) + + virtual void Start (); + virtual void TerminateApp (); + + protected: + vtkCocoaRenderWindowInteractorFix () {} + ~vtkCocoaRenderWindowInteractorFix () {} + + private: + vtkCocoaRenderWindowInteractorFix (const vtkCocoaRenderWindowInteractorFix&); // Not implemented. + void operator = (const vtkCocoaRenderWindowInteractorFix&); // Not implemented. + }; + + vtkStandardNewMacro (vtkCocoaRenderWindowInteractorFix) + + vtkSmartPointer vtkCocoaRenderWindowInteractorNew(); +}} + +void cv::viz::vtkCocoaRenderWindowInteractorFix::Start () +{ + vtkCocoaRenderWindow* renWin = vtkCocoaRenderWindow::SafeDownCast(this->GetRenderWindow ()); + if (renWin != NULL) + { + vtkCocoaServerFix *server = reinterpret_cast (this->GetCocoaServer ()); + if (!this->GetCocoaServer ()) + { + server = [vtkCocoaServerFix cocoaServerWithRenderWindow:renWin]; + this->SetCocoaServer (reinterpret_cast (server)); + } + + [server start]; + } +} + +void cv::viz::vtkCocoaRenderWindowInteractorFix::TerminateApp () +{ + vtkCocoaRenderWindow *renWin = vtkCocoaRenderWindow::SafeDownCast (this->RenderWindow); + if (renWin) + { + vtkCocoaServerFix *server = reinterpret_cast (this->GetCocoaServer ()); + [server stop]; + } +} + +vtkSmartPointer cv::viz::vtkCocoaRenderWindowInteractorNew() +{ + return vtkSmartPointer::New(); +} diff --git a/modules/viz/src/vtk/vtkOBJWriter.cpp b/modules/viz/src/vtk/vtkOBJWriter.cpp index 452ad19a7a..7480b11ac2 100644 --- a/modules/viz/src/vtk/vtkOBJWriter.cpp +++ b/modules/viz/src/vtk/vtkOBJWriter.cpp @@ -54,7 +54,6 @@ cv::viz::vtkOBJWriter::vtkOBJWriter() std::ofstream fout; // only used to extract the default precision this->DecimalPrecision = fout.precision(); this->FileName = NULL; - this->FileType = VTK_ASCII; } cv::viz::vtkOBJWriter::~vtkOBJWriter(){} @@ -65,14 +64,27 @@ void cv::viz::vtkOBJWriter::WriteData() if (!input) return; - std::ostream *outfilep = this->OpenVTKFile(); - if (!outfilep) + if (!this->FileName ) + { + vtkErrorMacro(<< "No FileName specified! Can't write!"); + this->SetErrorCode(vtkErrorCode::NoFileNameError); + return; + } + + vtkDebugMacro(<<"Opening vtk file for writing..."); + ostream *outfilep = new ofstream(this->FileName, ios::out); + if (outfilep->fail()) + { + vtkErrorMacro(<< "Unable to open file: "<< this->FileName); + this->SetErrorCode(vtkErrorCode::CannotOpenFileError); + delete outfilep; return; + } std::ostream& outfile = *outfilep; //write header - outfile << "# wavefront obj file written by the visualization toolkit" << std::endl << std::endl; + outfile << "# wavefront obj file written by opencv viz module" << std::endl << std::endl; outfile << "mtllib NONE" << std::endl << std::endl; // write out the points @@ -224,7 +236,8 @@ void cv::viz::vtkOBJWriter::WriteData() } } /* if (input->GetNumberOfStrips() > 0) */ - this->CloseVTKFile(outfilep); + vtkDebugMacro(<<"Closing vtk file\n"); + delete outfilep; // Delete the file if an error occurred if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) @@ -239,3 +252,19 @@ void cv::viz::vtkOBJWriter::PrintSelf(ostream& os, vtkIndent indent) Superclass::PrintSelf(os, indent); os << indent << "DecimalPrecision: " << DecimalPrecision << "\n"; } + +int cv::viz::vtkOBJWriter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; +} + +vtkPolyData* cv::viz::vtkOBJWriter::GetInput() +{ + return vtkPolyData::SafeDownCast(this->Superclass::GetInput()); +} + +vtkPolyData* cv::viz::vtkOBJWriter::GetInput(int port) +{ + return vtkPolyData::SafeDownCast(this->Superclass::GetInput(port)); +} diff --git a/modules/viz/src/vtk/vtkOBJWriter.h b/modules/viz/src/vtk/vtkOBJWriter.h index f8889884d7..7ad0f17b15 100644 --- a/modules/viz/src/vtk/vtkOBJWriter.h +++ b/modules/viz/src/vtk/vtkOBJWriter.h @@ -45,29 +45,41 @@ #ifndef __vtkOBJWriter_h #define __vtkOBJWriter_h -#include +#include namespace cv { namespace viz { - class vtkOBJWriter : public vtkPolyDataWriter + class vtkOBJWriter : public vtkWriter { public: static vtkOBJWriter *New(); - vtkTypeMacro(vtkOBJWriter,vtkPolyDataWriter) + vtkTypeMacro(vtkOBJWriter,vtkWriter) void PrintSelf(ostream& os, vtkIndent indent); - vtkGetMacro(DecimalPrecision, int); - vtkSetMacro(DecimalPrecision, int); + vtkGetMacro(DecimalPrecision, int) + vtkSetMacro(DecimalPrecision, int) + + // Description: + // Specify file name of data file to write. + vtkSetStringMacro(FileName) + vtkGetStringMacro(FileName) + + // Description: + // Get the input to this writer. + vtkPolyData* GetInput(); + vtkPolyData* GetInput(int port); protected: vtkOBJWriter(); ~vtkOBJWriter(); void WriteData(); + int FillInputPortInformation(int port, vtkInformation *info); int DecimalPrecision; + char *FileName; private: vtkOBJWriter(const vtkOBJWriter&); // Not implemented. diff --git a/modules/viz/src/vtk/vtkTrajectorySource.cpp b/modules/viz/src/vtk/vtkTrajectorySource.cpp index e098a1d553..2036e09af3 100644 --- a/modules/viz/src/vtk/vtkTrajectorySource.cpp +++ b/modules/viz/src/vtk/vtkTrajectorySource.cpp @@ -64,19 +64,19 @@ void cv::viz::vtkTrajectorySource::SetTrajectory(InputArray _traj) points = vtkSmartPointer::New(); points->SetDataType(VTK_DOUBLE); - points->SetNumberOfPoints(total); + points->SetNumberOfPoints((vtkIdType)total); tensors = vtkSmartPointer::New(); tensors->SetNumberOfComponents(9); - tensors->SetNumberOfTuples(total); + tensors->SetNumberOfTuples((vtkIdType)total); for(size_t i = 0; i < total; ++i, ++dpath) { Matx33d R = dpath->rotation().t(); // transposed because of - tensors->SetTuple(i, R.val); // column major order + tensors->SetTuple((vtkIdType)i, R.val); // column major order Vec3d p = dpath->translation(); - points->SetPoint(i, p.val); + points->SetPoint((vtkIdType)i, p.val); } } @@ -85,7 +85,7 @@ cv::Mat cv::viz::vtkTrajectorySource::ExtractPoints(InputArray _traj) CV_Assert(_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT); CV_Assert(_traj.type() == CV_32FC(16) || _traj.type() == CV_64FC(16)); - Mat points(1, _traj.total(), CV_MAKETYPE(_traj.depth(), 3)); + Mat points(1, (int)_traj.total(), CV_MAKETYPE(_traj.depth(), 3)); const Affine3d* dpath = _traj.getMat().ptr(); const Affine3f* fpath = _traj.getMat().ptr(); diff --git a/modules/viz/src/vtk/vtkVizInteractorStyle.cpp b/modules/viz/src/vtk/vtkVizInteractorStyle.cpp new file mode 100644 index 0000000000..9b5eca2b0e --- /dev/null +++ b/modules/viz/src/vtk/vtkVizInteractorStyle.cpp @@ -0,0 +1,1076 @@ +/*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. +// +// Authors: +// * Ozan Tonkal, ozantonkal@gmail.com +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// +//M*/ + +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkVizInteractorStyle) +}} + +////////////////////////////////////////////////////////////////////////////////////////////// + +cv::viz::vtkVizInteractorStyle::vtkVizInteractorStyle() +{ + FlyMode = false; + MotionFactor = 10.0; + + keyboardCallback_ = 0; + keyboard_callback_cookie_ = 0; + + mouseCallback_ = 0; + mouse_callback_cookie_ = 0; + + // Set windows size (width, height) to unknown (-1) + win_size_ = Vec2i(-1, -1); + win_pos_ = Vec2i(0, 0); + max_win_size_ = Vec2i(-1, -1); + + stereo_anaglyph_redblue_ = true; + + //from fly + KeysDown = 0; + UseTimers = 1; + + DiagonalLength = 1.0; + MotionStepSize = 1.0/100.0; + MotionUserScale = 1.0; // +/- key adjustment + MotionAccelerationFactor = 10.0; + AngleStepSize = 1.0; +} + +cv::viz::vtkVizInteractorStyle::~vtkVizInteractorStyle() {} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::saveScreenshot(const String &file) +{ + FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); + + vtkSmartPointer wif = vtkSmartPointer::New(); + wif->SetInput(Interactor->GetRenderWindow()); + + vtkSmartPointer snapshot_writer = vtkSmartPointer::New(); + snapshot_writer->SetInputConnection(wif->GetOutputPort()); + snapshot_writer->SetFileName(file.c_str()); + snapshot_writer->Write(); + + cout << "Screenshot successfully captured (" << file.c_str() << ")" << endl; +} + +////////////////////////////////////////////////////////////////////////////////////////////// + +void cv::viz::vtkVizInteractorStyle::exportScene(const String &file) +{ + vtkSmartPointer exporter; + if (file.size() > 5 && file.substr(file.size() - 5) == ".vrml") + { + exporter = vtkSmartPointer::New(); + vtkVRMLExporter::SafeDownCast(exporter)->SetFileName(file.c_str()); + } + else + { + exporter = vtkSmartPointer::New(); + vtkOBJExporter::SafeDownCast(exporter)->SetFilePrefix(file.c_str()); + } + + exporter->SetInput(Interactor->GetRenderWindow()); + exporter->Write(); + + cout << "Scene successfully exported (" << file.c_str() << ")" << endl; +} + +void cv::viz::vtkVizInteractorStyle::exportScene() +{ + // Export scene as in obj or vrml format + String format = Interactor->GetAltKey() ? "scene-%d.vrml" : "scene-%d"; + exportScene(cv::format(format.c_str(), (unsigned int)time(0))); +} + +////////////////////////////////////////////////////////////////////////////////////////////// + +void cv::viz::vtkVizInteractorStyle::changePointsSize(float delta) +{ + vtkSmartPointer ac = CurrentRenderer->GetActors(); + vtkCollectionSimpleIterator ait; + + for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) + for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) + { + vtkActor* apart = vtkActor::SafeDownCast(path->GetLastNode()->GetViewProp()); + float psize = apart->GetProperty()->GetPointSize() + delta; + psize = std::max(1.f, std::min(63.f, psize)); + apart->GetProperty()->SetPointSize(psize); + } +} + +void cv::viz::vtkVizInteractorStyle::setRepresentationToPoints() +{ + vtkSmartPointer ac = CurrentRenderer->GetActors(); + vtkCollectionSimpleIterator ait; + for (ac->InitTraversal(ait); vtkActor* actor = ac->GetNextActor(ait); ) + for (actor->InitPathTraversal(); vtkAssemblyPath* path = actor->GetNextPath(); ) + { + vtkActor* apart = vtkActor::SafeDownCast(path->GetLastNode()->GetViewProp()); + apart->GetProperty()->SetRepresentationToPoints(); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////// + +void cv::viz::vtkVizInteractorStyle::printCameraParams() +{ + vtkSmartPointer cam = Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetActiveCamera(); + + Vec2d clip(cam->GetClippingRange()); + Vec3d focal(cam->GetFocalPoint()), pos(cam->GetPosition()), view(cam->GetViewUp()); + Vec2i win_pos(Interactor->GetRenderWindow()->GetPosition()); + Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); + double angle = cam->GetViewAngle () / 180.0 * CV_PI; + + String data = cv::format("clip(%f,%f) focal(%f,%f,%f) pos(%f,%f,%f) view(%f,%f,%f) angle(%f) winsz(%d,%d) winpos(%d,%d)", + clip[0], clip[1], focal[0], focal[1], focal[2], pos[0], pos[1], pos[2], view[0], view[1], view[2], + angle, win_size[0], win_size[1], win_pos[0], win_pos[1]); + + std::cout << data.c_str() << std::endl; +} + +////////////////////////////////////////////////////////////////////////////////////////////// + +void cv::viz::vtkVizInteractorStyle::toggleFullScreen() +{ + Vec2i screen_size(Interactor->GetRenderWindow()->GetScreenSize()); + Vec2i win_size(Interactor->GetRenderWindow()->GetSize()); + + // Is window size = max? + if (win_size == max_win_size_) + { + Interactor->GetRenderWindow()->SetSize(win_size_.val); + Interactor->GetRenderWindow()->SetPosition(win_pos_.val); + Interactor->Render(); + } + // Set to max + else + { + win_pos_ = Vec2i(Interactor->GetRenderWindow()->GetPosition()); + win_size_ = win_size; + + Interactor->GetRenderWindow()->SetSize(screen_size.val); + Interactor->Render(); + max_win_size_ = Vec2i(Interactor->GetRenderWindow()->GetSize()); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////// + +void cv::viz::vtkVizInteractorStyle::resetViewerPose() +{ + WidgetActorMap::iterator it = widget_actor_map_->begin(); + // it might be that some actors don't have a valid transformation set -> we skip them to avoid a seg fault. + for (; it != widget_actor_map_->end(); ++it) + { + vtkProp3D * actor = vtkProp3D::SafeDownCast(it->second); + if (actor && actor->GetUserMatrix()) + break; + } + + vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); + + // if a valid transformation was found, use it otherwise fall back to default view point. + if (it != widget_actor_map_->end()) + { + vtkMatrix4x4* m = vtkProp3D::SafeDownCast(it->second)->GetUserMatrix(); + + cam->SetFocalPoint(m->GetElement(0, 3) - m->GetElement(0, 2), + m->GetElement(1, 3) - m->GetElement(1, 2), + m->GetElement(2, 3) - m->GetElement(2, 2)); + + cam->SetViewUp (m->GetElement(0, 1), m->GetElement(1, 1), m->GetElement(2, 1)); + cam->SetPosition(m->GetElement(0, 3), m->GetElement(1, 3), m->GetElement(2, 3)); + } + else + { + cam->SetPosition(0, 0, 0); + cam->SetFocalPoint(0, 0, 1); + cam->SetViewUp(0, -1, 0); + } + + // go to the next actor for the next key-press event. + if (it != widget_actor_map_->end()) + ++it; + else + it = widget_actor_map_->begin(); + + CurrentRenderer->SetActiveCamera(cam); + CurrentRenderer->ResetCameraClippingRange(); + Interactor->Render(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// + +void cv::viz::vtkVizInteractorStyle::toggleStereo() +{ + vtkSmartPointer window = Interactor->GetRenderWindow(); + if (!window->GetStereoRender()) + { + static Vec2i red_blue(4, 3), magenta_green(2, 5); + window->SetAnaglyphColorMask (stereo_anaglyph_redblue_ ? red_blue.val : magenta_green.val); + stereo_anaglyph_redblue_ = !stereo_anaglyph_redblue_; + } + window->SetStereoRender(!window->GetStereoRender()); + Interactor->Render(); + +} + +////////////////////////////////////////////////////////////////////////////////////////////// + +void cv::viz::vtkVizInteractorStyle::printHelp() +{ + std::cout << "| Help:\n" + "-------\n" + " p, P : switch to a point-based representation\n" + " w, W : switch to a wireframe-based representation (where available)\n" + " s, S : switch to a surface-based representation (where available)\n" + "\n" + " j, J : take a .PNG snapshot of the current window view\n" + " k, K : export scene to Wavefront .obj format\n" + " ALT + k, K : export scene to VRML format\n" + " c, C : display current camera/window parameters\n" + " F5 : enable/disable fly mode (changes control style)\n" + "\n" + " e, E : exit the interactor\n" + " q, Q : stop and call VTK's TerminateApp\n" + "\n" + " +/- : increment/decrement overall point size\n" + " +/- [+ ALT] : zoom in/out \n" + "\n" + " r, R [+ ALT] : reset camera [to viewpoint = {0, 0, 0} -> center_{x, y, z}]\n" + "\n" + " ALT + s, S : turn stereo mode on/off\n" + " ALT + f, F : switch between maximized window mode and original size\n" + "\n" + << std::endl; +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::zoomIn() +{ + FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); + // Zoom in + StartDolly(); + double factor = 10.0 * 0.2 * .5; + Dolly(std::pow(1.1, factor)); + EndDolly(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::zoomOut() +{ + FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); + // Zoom out + StartDolly(); + double factor = 10.0 * -0.2 * .5; + Dolly(std::pow(1.1, factor)); + EndDolly(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnChar() +{ + FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); + + String key(Interactor->GetKeySym()); + if (key.find("XF86ZoomIn") != String::npos) + zoomIn(); + else if (key.find("XF86ZoomOut") != String::npos) + zoomOut(); + + switch (Interactor->GetKeyCode()) + { +// // All of the options below simply exit +// case 'l': case 'L': case 'j': case 'J': case 'c': case 'C': case 'q': case 'Q': +// case 'f': case 'F': case 'g': case 'G': case 'o': case 'O': case 'u': case 'U': + case 'p': case 'P': + break; + + case '+': + if (FlyMode) + MotionUserScale = std::min(16.0, MotionUserScale*2.0); + break; + case '-': + if (FlyMode) + MotionUserScale = std::max(MotionUserScale * 0.5, 0.0625); + break; + + case 'r': case 'R': case 's': case 'S': + if (!Interactor->GetAltKey()) + Superclass::OnChar(); + break; + default: + Superclass::OnChar(); + break; + } +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::registerMouseCallback(void (*callback)(const MouseEvent&, void*), void* cookie) +{ + mouseCallback_ = callback; + mouse_callback_cookie_ = cookie; +} + +void cv::viz::vtkVizInteractorStyle::registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void *cookie) +{ + keyboardCallback_ = callback; + keyboard_callback_cookie_ = cookie; +} + +////////////////////////////////////////////////////////////////////////////////////////////// +int cv::viz::vtkVizInteractorStyle::getModifiers() +{ + int modifiers = KeyboardEvent::NONE; + + if (Interactor->GetAltKey()) + modifiers |= KeyboardEvent::ALT; + + if (Interactor->GetControlKey()) + modifiers |= KeyboardEvent::CTRL; + + if (Interactor->GetShiftKey()) + modifiers |= KeyboardEvent::SHIFT; + return modifiers; +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnKeyDown() +{ + FindPokedRenderer(Interactor->GetEventPosition()[0], Interactor->GetEventPosition()[1]); + + String key(Interactor->GetKeySym()); + if (key.find("XF86ZoomIn") != String::npos) + zoomIn(); + else if (key.find("XF86ZoomOut") != String::npos) + zoomOut(); + else if (key.find("F5") != String::npos) + { + FlyMode = !FlyMode; + std::cout << (FlyMode ? "Fly mode: on" : "Fly mode: off") << std::endl; + } + + // Save the initial windows width/height + if (win_size_[0] == -1 || win_size_[1] == -1) + win_size_ = Vec2i(Interactor->GetRenderWindow()->GetSize()); + + switch (Interactor->GetKeyCode()) + { + case 'a': case 'A' : KeysDown |=16; break; + case 'z': case 'Z' : KeysDown |=32; break; + case 'h': case 'H' : printHelp(); break; + case 'p': case 'P' : setRepresentationToPoints(); break; + case 'k': case 'K' : exportScene(); break; + case 'j': case 'J' : saveScreenshot(cv::format("screenshot-%d.png", (unsigned int)time(0))); break; + case 'c': case 'C' : printCameraParams(); break; + case '=': zoomIn(); break; + case 43: // KEY_PLUS + { + if (FlyMode) + break; + if (Interactor->GetAltKey()) + zoomIn(); + else + changePointsSize(+1.f); + break; + } + case 45: // KEY_MINUS + { + if (FlyMode) + break; + if (Interactor->GetAltKey()) + zoomOut(); + else + changePointsSize(-1.f); + break; + } + // Switch between maximize and original window size + case 'f': case 'F': + { + if (Interactor->GetAltKey()) + toggleFullScreen(); + break; + } + // 's'/'S' w/out ALT + case 's': case 'S': + { + if (Interactor->GetAltKey()) + toggleStereo(); + break; + } + + case 'o': case 'O': + { + vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); + cam->SetParallelProjection(!cam->GetParallelProjection()); + Interactor->Render(); + break; + } + + // Overwrite the camera reset + case 'r': case 'R': + { + if (Interactor->GetAltKey()) + resetViewerPose(); + break; + } + case 'q': case 'Q': + Interactor->ExitCallback(); return; + default: + Superclass::OnKeyDown(); break; + } + + KeyboardEvent event(KeyboardEvent::KEY_DOWN, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); + if (keyboardCallback_) + keyboardCallback_(event, keyboard_callback_cookie_); + + if (FlyMode && (KeysDown & (32+16)) == (32+16)) + { + if (State == VTKIS_FORWARDFLY || State == VTKIS_REVERSEFLY) + StopState(); + } + else if (FlyMode && (KeysDown & 32) == 32) + { + if (State == VTKIS_FORWARDFLY) + StopState(); + + if (State == VTKIS_NONE) + StartState(VTKIS_REVERSEFLY); + } + else if (FlyMode && (KeysDown & 16) == 16) + { + if (State == VTKIS_REVERSEFLY) + StopState(); + + if (State == VTKIS_NONE) + StartState(VTKIS_FORWARDFLY); + } + + Interactor->Render(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnKeyUp() +{ + KeyboardEvent event(KeyboardEvent::KEY_UP, Interactor->GetKeySym(), Interactor->GetKeyCode(), getModifiers()); + if (keyboardCallback_) + keyboardCallback_(event, keyboard_callback_cookie_); + + switch (Interactor->GetKeyCode()) + { + case 'a': case 'A' : KeysDown &= ~16; break; + case 'z': case 'Z' : KeysDown &= ~32; break; + } + + if (State == VTKIS_FORWARDFLY && (KeysDown & 16) == 0) + StopState(); + + if (State == VTKIS_REVERSEFLY && (KeysDown & 32) == 0) + StopState(); + + Superclass::OnKeyUp(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnMouseMove() +{ + Vec2i p(Interactor->GetEventPosition()); + MouseEvent event(MouseEvent::MouseMove, MouseEvent::NoButton, p, getModifiers()); + if (mouseCallback_) + mouseCallback_(event, mouse_callback_cookie_); + + FindPokedRenderer(p[0], p[1]); + + if (State == VTKIS_ROTATE || State == VTKIS_PAN || State == VTKIS_DOLLY || State == VTKIS_SPIN) + { + switch (State) + { + case VTKIS_ROTATE: Rotate(); break; + case VTKIS_PAN: Pan(); break; + case VTKIS_DOLLY: Dolly(); break; + case VTKIS_SPIN: Spin(); break; + } + + InvokeEvent(vtkCommand::InteractionEvent, NULL); + } + + if (State == VTKIS_FORWARDFLY || State == VTKIS_REVERSEFLY) + { + vtkCamera *cam = CurrentRenderer->GetActiveCamera(); + Vec2i thispos(Interactor->GetEventPosition()); + Vec2i lastpos(Interactor->GetLastEventPosition()); + + // we want to steer by an amount proportional to window viewangle and size + // compute dx and dy increments relative to last mouse click + Vec2i size(Interactor->GetSize()); + double scalefactor = 5*cam->GetViewAngle()/size[0]; + + double dx = - (thispos[0] - lastpos[0])*scalefactor*AngleStepSize; + double dy = (thispos[1] - lastpos[1])*scalefactor*AngleStepSize; + + // Temporary until I get smooth flight working + DeltaPitch = dy; + DeltaYaw = dx; + + InvokeEvent(vtkCommand::InteractionEvent, NULL); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnLeftButtonDown() +{ + Vec2i p(Interactor->GetEventPosition()); + MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; + MouseEvent event(type, MouseEvent::LeftButton, p, getModifiers()); + if (mouseCallback_) + mouseCallback_(event, mouse_callback_cookie_); + + FindPokedRenderer(p[0], p[1]); + if (!CurrentRenderer) + return; + + GrabFocus(EventCallbackCommand); + + if (FlyMode) + { + if(State == VTKIS_REVERSEFLY) + State = VTKIS_FORWARDFLY; + else + { + SetupMotionVars(); + if (State == VTKIS_NONE) + StartState(VTKIS_FORWARDFLY); + } + } + else + { + if (Interactor->GetShiftKey()) + { + if (Interactor->GetControlKey()) + StartDolly(); + else + StartPan(); + } + else + { + if (Interactor->GetControlKey()) + StartSpin(); + else + StartRotate(); + } + } +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnLeftButtonUp() +{ + Vec2i p(Interactor->GetEventPosition()); + MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::LeftButton, p, getModifiers()); + if (mouseCallback_) + mouseCallback_(event, mouse_callback_cookie_); + + switch (State) + { + case VTKIS_DOLLY: EndDolly(); break; + case VTKIS_PAN: EndPan(); break; + case VTKIS_SPIN: EndSpin(); break; + case VTKIS_ROTATE: EndRotate(); break; + case VTKIS_FORWARDFLY: StopState(); break; + } + + if (Interactor ) + ReleaseFocus(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnMiddleButtonDown() +{ + Vec2i p(Interactor->GetEventPosition()); + MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; + MouseEvent event(type, MouseEvent::MiddleButton, p, getModifiers()); + if (mouseCallback_) + mouseCallback_(event, mouse_callback_cookie_); + + FindPokedRenderer(p[0], p[1]); + if (!CurrentRenderer) + return; + + GrabFocus(EventCallbackCommand); + StartPan(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnMiddleButtonUp() +{ + Vec2i p(Interactor->GetEventPosition()); + MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::MiddleButton, p, getModifiers()); + if (mouseCallback_) + mouseCallback_(event, mouse_callback_cookie_); + + if (State == VTKIS_PAN) + { + EndPan(); + if (Interactor) + ReleaseFocus(); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnRightButtonDown() +{ + Vec2i p(Interactor->GetEventPosition()); + MouseEvent::Type type = (Interactor->GetRepeatCount() == 0) ? MouseEvent::MouseButtonPress : MouseEvent::MouseDblClick; + MouseEvent event(type, MouseEvent::RightButton, p, getModifiers()); + if (mouseCallback_) + mouseCallback_(event, mouse_callback_cookie_); + + FindPokedRenderer(p[0], p[1]); + if (!CurrentRenderer) + return; + + GrabFocus(EventCallbackCommand); + + if (FlyMode) + { + if (State == VTKIS_FORWARDFLY) + State = VTKIS_REVERSEFLY; + else + { + SetupMotionVars(); + if (State == VTKIS_NONE) + StartState(VTKIS_REVERSEFLY); + } + + } + else + StartDolly(); +} + + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnRightButtonUp() +{ + Vec2i p(Interactor->GetEventPosition()); + MouseEvent event(MouseEvent::MouseButtonRelease, MouseEvent::RightButton, p, getModifiers()); + if (mouseCallback_) + mouseCallback_(event, mouse_callback_cookie_); + + if(State == VTKIS_DOLLY) + { + EndDolly(); + if (Interactor) + ReleaseFocus(); + } + + if (State == VTKIS_REVERSEFLY) + { + StopState(); + if (Interactor) + ReleaseFocus(); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnMouseWheelForward() +{ + Vec2i p(Interactor->GetEventPosition()); + MouseEvent event(MouseEvent::MouseScrollUp, MouseEvent::VScroll, p, getModifiers()); + if (mouseCallback_) + mouseCallback_(event, mouse_callback_cookie_); + if (Interactor->GetRepeatCount() && mouseCallback_) + mouseCallback_(event, mouse_callback_cookie_); + + if (Interactor->GetAltKey()) + { + // zoom + vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); + double opening_angle = cam->GetViewAngle(); + if (opening_angle > 15.0) + opening_angle -= 1.0; + + cam->SetViewAngle(opening_angle); + cam->Modified(); + CurrentRenderer->ResetCameraClippingRange(); + CurrentRenderer->Modified(); + Interactor->Render(); + } + else + { + FindPokedRenderer(p[0], p[1]); + if (!CurrentRenderer) + return; + + GrabFocus(EventCallbackCommand); + StartDolly(); + Dolly(pow(1.1, MotionFactor * 0.2 * MouseWheelMotionFactor)); + EndDolly(); + ReleaseFocus(); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnMouseWheelBackward() +{ + Vec2i p(Interactor->GetEventPosition()); + MouseEvent event(MouseEvent::MouseScrollDown, MouseEvent::VScroll, p, getModifiers()); + if (mouseCallback_) + mouseCallback_(event, mouse_callback_cookie_); + + if (Interactor->GetRepeatCount() && mouseCallback_) + mouseCallback_(event, mouse_callback_cookie_); + + if (Interactor->GetAltKey()) + { + // zoom + vtkSmartPointer cam = CurrentRenderer->GetActiveCamera(); + double opening_angle = cam->GetViewAngle(); + if (opening_angle < 170.0) + opening_angle += 1.0; + + cam->SetViewAngle(opening_angle); + cam->Modified(); + CurrentRenderer->ResetCameraClippingRange(); + CurrentRenderer->Modified(); + Interactor->Render(); + } + else + { + FindPokedRenderer(p[0], p[1]); + if (!CurrentRenderer) + return; + + GrabFocus(EventCallbackCommand); + StartDolly(); + Dolly(pow(1.1, MotionFactor * -0.2 * MouseWheelMotionFactor)); + EndDolly(); + ReleaseFocus(); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::OnTimer() +{ + if (State == VTKIS_FORWARDFLY || State == VTKIS_REVERSEFLY) + Fly(); + + Interactor->Render(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// + +void cv::viz::vtkVizInteractorStyle::Rotate() +{ + if (!CurrentRenderer) + return; + + Vec2i dxy = Vec2i(Interactor->GetEventPosition()) - Vec2i(Interactor->GetLastEventPosition()); + Vec2i size(CurrentRenderer->GetRenderWindow()->GetSize()); + + double delta_elevation = -20.0 / size[1]; + double delta_azimuth = -20.0 / size[0]; + + double rxf = dxy[0] * delta_azimuth * MotionFactor; + double ryf = dxy[1] * delta_elevation * MotionFactor; + + vtkCamera *camera = CurrentRenderer->GetActiveCamera(); + camera->Azimuth(rxf); + camera->Elevation(ryf); + camera->OrthogonalizeViewUp(); + + if (AutoAdjustCameraClippingRange) + CurrentRenderer->ResetCameraClippingRange(); + + if (Interactor->GetLightFollowCamera()) + CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + + Interactor->Render(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::Spin() +{ + if (!CurrentRenderer) + return; + + vtkRenderWindowInteractor *rwi = Interactor; + + double *center = CurrentRenderer->GetCenter(); + + double newAngle = vtkMath::DegreesFromRadians( atan2( rwi->GetEventPosition()[1] - center[1], rwi->GetEventPosition()[0] - center[0] ) ); + double oldAngle = vtkMath::DegreesFromRadians( atan2( rwi->GetLastEventPosition()[1] - center[1], rwi->GetLastEventPosition()[0] - center[0] ) ); + + vtkCamera *camera = CurrentRenderer->GetActiveCamera(); + camera->Roll( newAngle - oldAngle ); + camera->OrthogonalizeViewUp(); + + rwi->Render(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// +void cv::viz::vtkVizInteractorStyle::Pan() +{ + if (!CurrentRenderer) + return; + + vtkRenderWindowInteractor *rwi = Interactor; + + double viewFocus[4], focalDepth, viewPoint[3]; + double newPickPoint[4], oldPickPoint[4], motionVector[3]; + + // Calculate the focal depth since we'll be using it a lot + + vtkCamera *camera = CurrentRenderer->GetActiveCamera(); + camera->GetFocalPoint(viewFocus); + ComputeWorldToDisplay(viewFocus[0], viewFocus[1], viewFocus[2], viewFocus); + focalDepth = viewFocus[2]; + + ComputeDisplayToWorld(rwi->GetEventPosition()[0], rwi->GetEventPosition()[1], focalDepth, newPickPoint); + + // Has to recalc old mouse point since the viewport has moved, so can't move it outside the loop + ComputeDisplayToWorld(rwi->GetLastEventPosition()[0], rwi->GetLastEventPosition()[1], focalDepth, oldPickPoint); + + // Camera motion is reversed + motionVector[0] = oldPickPoint[0] - newPickPoint[0]; + motionVector[1] = oldPickPoint[1] - newPickPoint[1]; + motionVector[2] = oldPickPoint[2] - newPickPoint[2]; + + camera->GetFocalPoint(viewFocus); + camera->GetPosition(viewPoint); + camera->SetFocalPoint(motionVector[0] + viewFocus[0], motionVector[1] + viewFocus[1], motionVector[2] + viewFocus[2]); + camera->SetPosition( motionVector[0] + viewPoint[0], motionVector[1] + viewPoint[1], motionVector[2] + viewPoint[2]); + + if (Interactor->GetLightFollowCamera()) + CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + + Interactor->Render(); +} + +////////////////////////////////////////////////////////////////////////////////////////////// + +void cv::viz::vtkVizInteractorStyle::Dolly() +{ + if (!CurrentRenderer) + return; + + int dy = Interactor->GetEventPosition()[1] - Interactor->GetLastEventPosition()[1]; + Dolly(pow(1.1, MotionFactor * dy / CurrentRenderer->GetCenter()[1])); +} + +void cv::viz::vtkVizInteractorStyle::Dolly(double factor) +{ + if (!CurrentRenderer) + return; + + vtkCamera *camera = CurrentRenderer->GetActiveCamera(); + if (camera->GetParallelProjection()) + camera->SetParallelScale(camera->GetParallelScale() / factor); + else + { + camera->Dolly(factor); + if (AutoAdjustCameraClippingRange) + CurrentRenderer->ResetCameraClippingRange(); + } + + if (Interactor->GetLightFollowCamera()) + CurrentRenderer->UpdateLightsGeometryToFollowCamera(); + + Interactor->Render(); +} +////////////////////////////////////////////////////////////////////////////////////////////// + +void cv::viz::vtkVizInteractorStyle::Fly() +{ + if (CurrentRenderer == NULL) + return; + + if (KeysDown) + FlyByKey(); + else + FlyByMouse(); + + CurrentRenderer->GetActiveCamera()->OrthogonalizeViewUp(); + + if (AutoAdjustCameraClippingRange) + CurrentRenderer->ResetCameraClippingRange(); + + if (Interactor->GetLightFollowCamera()) + CurrentRenderer->UpdateLightsGeometryToFollowCamera(); +} + +void cv::viz::vtkVizInteractorStyle::SetupMotionVars() +{ + Vec6d bounds; + CurrentRenderer->ComputeVisiblePropBounds(bounds.val); + + if ( !vtkMath::AreBoundsInitialized(bounds.val) ) + DiagonalLength = 1.0; + else + DiagonalLength = norm(Vec3d(bounds[0], bounds[2], bounds[4]) - Vec3d(bounds[1], bounds[3], bounds[5])); +} + +void cv::viz::vtkVizInteractorStyle::MotionAlongVector(const Vec3d& vector, double amount, vtkCamera* cam) +{ + // move camera and focus along DirectionOfProjection + Vec3d campos = Vec3d(cam->GetPosition()) - amount * vector; + Vec3d camfoc = Vec3d(cam->GetFocalPoint()) - amount * vector; + + cam->SetPosition(campos.val); + cam->SetFocalPoint(camfoc.val); +} + +void cv::viz::vtkVizInteractorStyle::FlyByMouse() +{ + vtkCamera* cam = CurrentRenderer->GetActiveCamera(); + double speed = DiagonalLength * MotionStepSize * MotionUserScale; + speed = speed * ( Interactor->GetShiftKey() ? MotionAccelerationFactor : 1.0); + + // Sidestep + if (Interactor->GetAltKey()) + { + if (DeltaYaw!=0.0) + { + vtkMatrix4x4 *vtm = cam->GetViewTransformMatrix(); + Vec3d a_vector(vtm->GetElement(0,0), vtm->GetElement(0,1), vtm->GetElement(0,2)); + + MotionAlongVector(a_vector, -DeltaYaw*speed, cam); + } + if (DeltaPitch!=0.0) + { + Vec3d a_vector(cam->GetViewUp()); + MotionAlongVector(a_vector, DeltaPitch*speed, cam); + } + } + else + { + cam->Yaw(DeltaYaw); + cam->Pitch(DeltaPitch); + DeltaYaw = 0; + DeltaPitch = 0; + } + // + if (!Interactor->GetControlKey()) + { + Vec3d a_vector(cam->GetDirectionOfProjection()); // reversed (use -speed) + switch (State) + { + case VTKIS_FORWARDFLY: MotionAlongVector(a_vector, -speed, cam); break; + case VTKIS_REVERSEFLY: MotionAlongVector(a_vector, speed, cam); break; + } + } +} + +void cv::viz::vtkVizInteractorStyle::FlyByKey() +{ + vtkCamera* cam = CurrentRenderer->GetActiveCamera(); + + double speed = DiagonalLength * MotionStepSize * MotionUserScale; + speed = speed * ( Interactor->GetShiftKey() ? MotionAccelerationFactor : 1.0); + + // Left and right + if (Interactor->GetAltKey()) + { // Sidestep + vtkMatrix4x4 *vtm = cam->GetViewTransformMatrix(); + Vec3d a_vector(vtm->GetElement(0,0), vtm->GetElement(0,1), vtm->GetElement(0,2)); + + if (KeysDown & 1) + MotionAlongVector(a_vector, -speed, cam); + + if (KeysDown & 2) + MotionAlongVector(a_vector, speed, cam); + } + else + { + if (KeysDown & 1) + cam->Yaw( AngleStepSize); + + if (KeysDown & 2) + cam->Yaw(-AngleStepSize); + } + + // Up and Down + if (Interactor->GetControlKey()) + { // Sidestep + Vec3d a_vector = Vec3d(cam->GetViewUp()); + if (KeysDown & 4) + MotionAlongVector(a_vector,-speed, cam); + + if (KeysDown & 8) + MotionAlongVector(a_vector, speed, cam); + } + else + { + if (KeysDown & 4) + cam->Pitch(-AngleStepSize); + + if (KeysDown & 8) + cam->Pitch( AngleStepSize); + } + + // forward and backward + Vec3d a_vector(cam->GetDirectionOfProjection()); + if (KeysDown & 16) + MotionAlongVector(a_vector, speed, cam); + + if (KeysDown & 32) + MotionAlongVector(a_vector,-speed, cam); +} + +////////////////////////////////////////////////////////////////////////////////////////////// + +void cv::viz::vtkVizInteractorStyle::PrintSelf(ostream& os, vtkIndent indent) +{ + Superclass::PrintSelf(os, indent); + os << indent << "MotionFactor: " << MotionFactor << "\n"; + os << indent << "MotionStepSize: " << MotionStepSize << "\n"; + os << indent << "MotionAccelerationFactor: "<< MotionAccelerationFactor << "\n"; + os << indent << "AngleStepSize: " << AngleStepSize << "\n"; + os << indent << "MotionUserScale: "<< MotionUserScale << "\n"; +} diff --git a/modules/viz/src/interactor_style.hpp b/modules/viz/src/vtk/vtkVizInteractorStyle.hpp similarity index 61% rename from modules/viz/src/interactor_style.hpp rename to modules/viz/src/vtk/vtkVizInteractorStyle.hpp index 8d01697a87..3588a3b6cd 100644 --- a/modules/viz/src/interactor_style.hpp +++ b/modules/viz/src/vtk/vtkVizInteractorStyle.hpp @@ -46,64 +46,101 @@ #ifndef __OPENCV_VIZ_INTERACTOR_STYLE_H__ #define __OPENCV_VIZ_INTERACTOR_STYLE_H__ +#include + namespace cv { namespace viz { - class InteractorStyle : public vtkInteractorStyleTrackballCamera + class vtkVizInteractorStyle : public vtkInteractorStyle { public: - static InteractorStyle *New(); - virtual ~InteractorStyle() {} + static vtkVizInteractorStyle *New(); + vtkTypeMacro(vtkVizInteractorStyle, vtkInteractorStyle) + void PrintSelf(ostream& os, vtkIndent indent); - // this macro defines Superclass, the isA functionality and the safe downcast method - vtkTypeMacro(InteractorStyle, vtkInteractorStyleTrackballCamera) + virtual void OnChar(); + virtual void OnKeyDown(); + virtual void OnKeyUp(); - /** \brief Initialization routine. Must be called before anything else. */ - virtual void Initialize(); + virtual void OnMouseMove(); + virtual void OnLeftButtonDown(); + virtual void OnLeftButtonUp(); + virtual void OnMiddleButtonDown(); + virtual void OnMiddleButtonUp(); + virtual void OnRightButtonDown(); + virtual void OnRightButtonUp(); + virtual void OnMouseWheelForward(); + virtual void OnMouseWheelBackward(); + virtual void OnTimer(); + + virtual void Rotate(); + virtual void Spin(); + virtual void Pan(); + virtual void Dolly(); + + vtkSetMacro(FlyMode,bool) + vtkGetMacro(FlyMode,bool) + + + vtkSetMacro(MotionFactor, double) + vtkGetMacro(MotionFactor, double) - void setWidgetActorMap(const Ptr& actors) { widget_actor_map_ = actors; } void registerMouseCallback(void (*callback)(const MouseEvent&, void*), void* cookie = 0); void registerKeyboardCallback(void (*callback)(const KeyboardEvent&, void*), void * cookie = 0); + + void setWidgetActorMap(const Ptr& actors) { widget_actor_map_ = actors; } void saveScreenshot(const String &file); void exportScene(const String &file); + void exportScene(); + void changePointsSize(float delta); + void setRepresentationToPoints(); + void printCameraParams(); + void toggleFullScreen(); + void resetViewerPose(); + void toggleStereo(); + void printHelp(); + + // Set the basic unit step size : by default 1/250 of bounding diagonal + vtkSetMacro(MotionStepSize,double) + vtkGetMacro(MotionStepSize,double) + + // Set acceleration factor when shift key is applied : default 10 + vtkSetMacro(MotionAccelerationFactor,double) + vtkGetMacro(MotionAccelerationFactor,double) + + // Set the basic angular unit for turning : efault 1 degree + vtkSetMacro(AngleStepSize,double) + vtkGetMacro(AngleStepSize,double) private: - /** \brief Set to true after initialization is complete. */ - bool init_; - Ptr widget_actor_map_; Vec2i win_size_; Vec2i win_pos_; Vec2i max_win_size_; - /** \brief Interactor style internal method. Gets called whenever a key is pressed. */ - virtual void OnChar(); + void zoomIn(); + void zoomOut(); - // Keyboard events - virtual void OnKeyDown(); - virtual void OnKeyUp(); + protected: + vtkVizInteractorStyle(); + ~vtkVizInteractorStyle(); - // mouse button events - virtual void OnMouseMove(); - virtual void OnLeftButtonDown(); - virtual void OnLeftButtonUp(); - virtual void OnMiddleButtonDown(); - virtual void OnMiddleButtonUp(); - virtual void OnRightButtonDown(); - virtual void OnRightButtonUp(); - virtual void OnMouseWheelForward(); - virtual void OnMouseWheelBackward(); + virtual void Dolly(double factor); - /** \brief Interactor style internal method. Gets called periodically if a timer is set. */ - virtual void OnTimer(); + void Fly(); + void FlyByMouse(); + void FlyByKey(); + void SetupMotionVars(); + void MotionAlongVector(const Vec3d& vector, double amount, vtkCamera* cam); - void zoomIn(); - void zoomOut(); + private: + vtkVizInteractorStyle(const vtkVizInteractorStyle&); + vtkVizInteractorStyle& operator=(const vtkVizInteractorStyle&); - /** \brief True if we're using red-blue colors for anaglyphic stereo, false if magenta-green. */ - bool stereo_anaglyph_mask_default_; + //! True for red-blue colors, false for magenta-green. + bool stereo_anaglyph_redblue_; void (*keyboardCallback_)(const KeyboardEvent&, void*); void *keyboard_callback_cookie_; @@ -111,7 +148,20 @@ namespace cv void (*mouseCallback_)(const MouseEvent&, void*); void *mouse_callback_cookie_; + bool FlyMode; + double MotionFactor; + int getModifiers(); + + // from fly + unsigned char KeysDown; + double DiagonalLength; + double MotionStepSize; + double MotionUserScale; + double MotionAccelerationFactor; + double AngleStepSize; + double DeltaYaw; + double DeltaPitch; }; } } diff --git a/modules/ocl/src/opencl/arithm_bitwise_binary_scalar_mask.cl b/modules/viz/src/vtk/vtkXYZReader.cpp similarity index 52% rename from modules/ocl/src/opencl/arithm_bitwise_binary_scalar_mask.cl rename to modules/viz/src/vtk/vtkXYZReader.cpp index 756f20165b..283a592489 100644 --- a/modules/ocl/src/opencl/arithm_bitwise_binary_scalar_mask.cl +++ b/modules/viz/src/vtk/vtkXYZReader.cpp @@ -10,13 +10,9 @@ // 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. // -// @Authors -// Jiang Liyuan, jlyuan001.good@163.com -// // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // @@ -30,7 +26,7 @@ // * 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 +// 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, @@ -41,46 +37,71 @@ // 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. // +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com +// //M*/ -////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////bitwise_binary//////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////// +#include "precomp.hpp" + +namespace cv { namespace viz +{ + vtkStandardNewMacro(vtkXYZReader); +}} + -__kernel void arithm_bitwise_binary_scalar_mask(__global uchar *src1, int src1_step, int src1_offset, - __global uchar *src2, - __global uchar *mask, int mask_step, int mask_offset, - __global uchar *dst, int dst_step, int dst_offset, - int cols, int rows) +cv::viz::vtkXYZReader::vtkXYZReader() { - int x = get_global_id(0); - int y = get_global_id(1); + this->FileName = 0; + this->SetNumberOfInputPorts(0); +} - if (x < cols && y < rows) +cv::viz::vtkXYZReader::~vtkXYZReader() +{ + this->SetFileName(0); +} + +void cv::viz::vtkXYZReader::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "FileName: " << (this->FileName ? this->FileName : "(none)") << "\n"; +} + +int cv::viz::vtkXYZReader::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector* outputVector) +{ + // Make sure we have a file to read. + if(!this->FileName) { - int mask_index = mad24(y, mask_step, x + mask_offset); + vtkErrorMacro("A FileName must be specified."); + return 0; + } - if (mask[mask_index]) - { -#if elemSize > 1 - x *= elemSize; -#endif - int src1_index = mad24(y, src1_step, x + src1_offset); - int dst_index = mad24(y, dst_step, x + dst_offset); + // Open the input file. + ifstream fin(this->FileName); + if(!fin) + { + vtkErrorMacro("Error opening file " << this->FileName); + return 0; + } -#if elemSize > 1 - #pragma unroll - for (int i = 0; i < elemSize; i += vlen) - { - ucharv t0 = vloadn(0, src1 + src1_index + i); - ucharv t1 = vloadn(0, src2 + i); - ucharv t2 = t0 Operation t1; + // Allocate objects to hold points and vertex cells. + vtkSmartPointer points = vtkSmartPointer::New(); + vtkSmartPointer verts = vtkSmartPointer::New(); - vstoren(t2, 0, dst + dst_index + i); - } -#else - dst[dst_index] = src1[src1_index] Operation src2[0]; -#endif - } + // Read points from the file. + vtkDebugMacro("Reading points from file " << this->FileName); + double x[3]; + while(fin >> x[0] >> x[1] >> x[2]) + { + vtkIdType id = points->InsertNextPoint(x); + verts->InsertNextCell(1, &id); } + vtkDebugMacro("Read " << points->GetNumberOfPoints() << " points."); + + // Store the points and cells in the output data object. + vtkPolyData* output = vtkPolyData::GetData(outputVector); + output->SetPoints(points); + output->SetVerts(verts); + + return 1; } diff --git a/modules/ocl/src/opencl/arithm_bitwise_binary_scalar.cl b/modules/viz/src/vtk/vtkXYZReader.h similarity index 55% rename from modules/ocl/src/opencl/arithm_bitwise_binary_scalar.cl rename to modules/viz/src/vtk/vtkXYZReader.h index 434bd5eca8..13ae048ec6 100644 --- a/modules/ocl/src/opencl/arithm_bitwise_binary_scalar.cl +++ b/modules/viz/src/vtk/vtkXYZReader.h @@ -1,4 +1,4 @@ -//////////////////////////////////////////////////////////////////////////////////////// +/*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // @@ -10,14 +10,9 @@ // 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. // -// @Authors -// Jiang Liyuan, jlyuan001.good@163.com -// Peng Xiao, pengxiao@outlook.com -// // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // @@ -31,7 +26,7 @@ // * 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 +// 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, @@ -42,41 +37,44 @@ // 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. // +// Authors: +// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com // +//M*/ -/////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////bitwise_binary///////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////////// +#ifndef __vtkXYZReader_h +#define __vtkXYZReader_h -__kernel void arithm_bitwise_binary_scalar( - __global uchar *src1, int src1_step, int src1_offset, - __global uchar *src2, - __global uchar *dst, int dst_step, int dst_offset, - int cols, int rows) -{ - int x = get_global_id(0); - int y = get_global_id(1); +#include "vtkPolyDataAlgorithm.h" - if (x < cols && y < rows) +namespace cv +{ + namespace viz { -#if elemSize > 1 - x *= elemSize; -#endif - int src1_index = mad24(y, src1_step, src1_offset + x); - int dst_index = mad24(y, dst_step, dst_offset + x); - -#if elemSize > 1 - #pragma unroll - for (int i = 0; i < elemSize; i += vlen) + class vtkXYZReader : public vtkPolyDataAlgorithm { - ucharv t0 = vloadn(0, src1 + src1_index + i); - ucharv t1 = vloadn(0, src2 + i); - ucharv t2 = t0 Operation t1; + public: + static vtkXYZReader* New(); + vtkTypeMacro(vtkXYZReader,vtkPolyDataAlgorithm) + void PrintSelf(ostream& os, vtkIndent indent); - vstoren(t2, 0, dst + dst_index + i); - } -#else - dst[dst_index] = src1[src1_index] Operation src2[0]; -#endif + // Description: + // Set/Get the name of the file from which to read points. + vtkSetStringMacro(FileName) + vtkGetStringMacro(FileName) + + protected: + vtkXYZReader(); + ~vtkXYZReader(); + + char* FileName; + + int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*); + private: + vtkXYZReader(const vtkXYZReader&); // Not implemented. + void operator=(const vtkXYZReader&); // Not implemented. + }; } } + +#endif diff --git a/modules/viz/src/vtk/vtkXYZWriter.cpp b/modules/viz/src/vtk/vtkXYZWriter.cpp index 4518a0103a..5a3d7d5c83 100644 --- a/modules/viz/src/vtk/vtkXYZWriter.cpp +++ b/modules/viz/src/vtk/vtkXYZWriter.cpp @@ -61,10 +61,22 @@ void cv::viz::vtkXYZWriter::WriteData() if (!input) return; - // OpenVTKFile() will report any errors that happen - ostream *outfilep = this->OpenVTKFile(); - if (!outfilep) + if (!this->FileName ) + { + vtkErrorMacro(<< "No FileName specified! Can't write!"); + this->SetErrorCode(vtkErrorCode::NoFileNameError); + return; + } + + vtkDebugMacro(<<"Opening vtk file for writing..."); + ostream *outfilep = new ofstream(this->FileName, ios::out); + if (outfilep->fail()) + { + vtkErrorMacro(<< "Unable to open file: "<< this->FileName); + this->SetErrorCode(vtkErrorCode::CannotOpenFileError); + delete outfilep; return; + } ostream &outfile = *outfilep; @@ -76,7 +88,8 @@ void cv::viz::vtkXYZWriter::WriteData() } // Close the file - this->CloseVTKFile(outfilep); + vtkDebugMacro(<<"Closing vtk file\n"); + delete outfilep; // Delete the file if an error occurred if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) @@ -86,8 +99,24 @@ void cv::viz::vtkXYZWriter::WriteData() } } +int cv::viz::vtkXYZWriter::FillInputPortInformation(int, vtkInformation *info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); + return 1; +} + void cv::viz::vtkXYZWriter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "DecimalPrecision: " << this->DecimalPrecision << "\n"; } + +vtkPolyData* cv::viz::vtkXYZWriter::GetInput() +{ + return vtkPolyData::SafeDownCast(this->Superclass::GetInput()); +} + +vtkPolyData* cv::viz::vtkXYZWriter::GetInput(int port) +{ + return vtkPolyData::SafeDownCast(this->Superclass::GetInput(port)); +} diff --git a/modules/viz/src/vtk/vtkXYZWriter.h b/modules/viz/src/vtk/vtkXYZWriter.h index 3db18b793b..91d0c8f6b4 100644 --- a/modules/viz/src/vtk/vtkXYZWriter.h +++ b/modules/viz/src/vtk/vtkXYZWriter.h @@ -45,29 +45,41 @@ #ifndef __vtkXYZWriter_h #define __vtkXYZWriter_h -#include "vtkPolyDataWriter.h" +#include "vtkWriter.h" namespace cv { namespace viz { - class vtkXYZWriter : public vtkPolyDataWriter + class vtkXYZWriter : public vtkWriter { public: static vtkXYZWriter *New(); - vtkTypeMacro(vtkXYZWriter,vtkPolyDataWriter) + vtkTypeMacro(vtkXYZWriter,vtkWriter) void PrintSelf(ostream& os, vtkIndent indent); vtkGetMacro(DecimalPrecision, int) vtkSetMacro(DecimalPrecision, int) + // Description: + // Specify file name of data file to write. + vtkSetStringMacro(FileName) + vtkGetStringMacro(FileName) + + // Description: + // Get the input to this writer. + vtkPolyData* GetInput(); + vtkPolyData* GetInput(int port); + protected: vtkXYZWriter(); ~vtkXYZWriter(){} void WriteData(); + int FillInputPortInformation(int port, vtkInformation *info); int DecimalPrecision; + char *FileName; private: vtkXYZWriter(const vtkXYZWriter&); // Not implemented. diff --git a/modules/viz/test/test_precomp.hpp b/modules/viz/test/test_precomp.hpp index cd00b6e73b..05914e2848 100644 --- a/modules/viz/test/test_precomp.hpp +++ b/modules/viz/test/test_precomp.hpp @@ -54,12 +54,20 @@ #ifndef __OPENCV_TEST_PRECOMP_HPP__ #define __OPENCV_TEST_PRECOMP_HPP__ -#include "opencv2/ts/ts.hpp" -#include -#include -#include +#include #include +namespace cv +{ + Mat imread(const String& filename, int flags = 1); +} + +#if CV_MAJOR_VERSION < 3 + #include "opencv2/ts/ts.hpp" +#else + #include "opencv2/ts.hpp" +#endif + #include #include #include diff --git a/modules/viz/test/test_tutorial3.cpp b/modules/viz/test/test_tutorial3.cpp index 590e29ebfd..b20e8d7a11 100644 --- a/modules/viz/test/test_tutorial3.cpp +++ b/modules/viz/test/test_tutorial3.cpp @@ -15,50 +15,46 @@ void tutorial3(bool camera_pov) myWindow.showWidget("Coordinate Widget", viz::WCoordinateSystem()); /// Let's assume camera has the following properties - Point3d cam_pos(3.0, 3.0, 3.0), cam_focal_point(3.0, 3.0, 2.0), cam_y_dir(-1.0, 0.0, 0.0); + Point3d cam_origin(3.0, 3.0, 3.0), cam_focal_point(3.0, 3.0, 2.0), cam_y_dir(-1.0, 0.0, 0.0); /// We can get the pose of the cam using makeCameraPose - Affine3d cam_pose = viz::makeCameraPose(cam_pos, cam_focal_point, cam_y_dir); + Affine3d camera_pose = viz::makeCameraPose(cam_origin, cam_focal_point, cam_y_dir); /// We can get the transformation matrix from camera coordinate system to global using /// - makeTransformToGlobal. We need the axes of the camera - Affine3d transform = viz::makeTransformToGlobal(Vec3d(0.0, -1.0, 0.0), Vec3d(-1.0, 0.0, 0.0), Vec3d(0.0, 0.0, -1.0), cam_pos); + Affine3d transform = viz::makeTransformToGlobal(Vec3d(0.0, -1.0, 0.0), Vec3d(-1.0, 0.0, 0.0), Vec3d(0.0, 0.0, -1.0), cam_origin); /// Create a cloud widget. Mat dragon_cloud = viz::readCloud(get_dragon_ply_file_path()); viz::WCloud cloud_widget(dragon_cloud, viz::Color::green()); /// Pose of the widget in camera frame - Affine3d cloud_pose = Affine3d().translate(Vec3d(0.0, 0.0, 3.0)); + Affine3d cloud_pose = Affine3d().rotate(Vec3d(0.0, CV_PI/2, 0.0)).rotate(Vec3d(0.0, 0.0, CV_PI)).translate(Vec3d(0.0, 0.0, 3.0)); /// Pose of the widget in global frame Affine3d cloud_pose_global = transform * cloud_pose; /// Visualize camera frame + myWindow.showWidget("CPW_FRUSTUM", viz::WCameraPosition(Vec2f(0.889484f, 0.523599f)), camera_pose); if (!camera_pov) - { - viz::WCameraPosition cpw(0.5); // Coordinate axes - viz::WCameraPosition cpw_frustum(Vec2f(0.889484f, 0.523599f)); // Camera frustum - myWindow.showWidget("CPW", cpw, cam_pose); - myWindow.showWidget("CPW_FRUSTUM", cpw_frustum, cam_pose); - } + myWindow.showWidget("CPW", viz::WCameraPosition(0.5), camera_pose); /// Visualize widget myWindow.showWidget("bunny", cloud_widget, cloud_pose_global); /// Set the viewer pose to that of camera if (camera_pov) - myWindow.setViewerPose(cam_pose); + myWindow.setViewerPose(camera_pose); /// Start event loop. myWindow.spin(); } -TEST(Viz, DISABLED_tutorial3_global_view) +TEST(Viz, tutorial3_global_view) { tutorial3(false); } -TEST(Viz, DISABLED_tutorial3_camera_view) +TEST(Viz, tutorial3_camera_view) { tutorial3(true); } diff --git a/modules/viz/test/test_viz3d.cpp b/modules/viz/test/test_viz3d.cpp index 45d3cdc3cf..45128df2f7 100644 --- a/modules/viz/test/test_viz3d.cpp +++ b/modules/viz/test/test_viz3d.cpp @@ -59,6 +59,5 @@ TEST(Viz_viz3d, DISABLED_develop) //cv::Mat cloud = cv::viz::readCloud(get_dragon_ply_file_path()); //---->>>>> - viz.spin(); } diff --git a/modules/viz/test/tests_simple.cpp b/modules/viz/test/tests_simple.cpp index f84b60a475..d1b059cf67 100644 --- a/modules/viz/test/tests_simple.cpp +++ b/modules/viz/test/tests_simple.cpp @@ -52,6 +52,7 @@ TEST(Viz, show_cloud_bluberry) Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); Viz3d viz("show_cloud_bluberry"); + viz.setBackgroundColor(Color::black()); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("dragon", WCloud(dragon_cloud, Color::bluberry()), pose); @@ -81,7 +82,7 @@ TEST(Viz, show_cloud_masked) Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); Vec3f qnan = Vec3f::all(std::numeric_limits::quiet_NaN()); - for(size_t i = 0; i < dragon_cloud.total(); ++i) + for(int i = 0; i < (int)dragon_cloud.total(); ++i) if (i % 15 != 0) dragon_cloud.at(i) = qnan; @@ -102,6 +103,7 @@ TEST(Viz, show_cloud_collection) ccol.addCloud(cloud, Color::white(), Affine3d().translate(Vec3d(0, 0, 0)).rotate(Vec3d(CV_PI/2, 0, 0))); ccol.addCloud(cloud, Color::blue(), Affine3d().translate(Vec3d(1, 0, 0))); ccol.addCloud(cloud, Color::red(), Affine3d().translate(Vec3d(2, 0, 0))); + ccol.finalize(); Viz3d viz("show_cloud_collection"); viz.setBackgroundColor(Color::mlab()); @@ -154,6 +156,27 @@ TEST(Viz, show_mesh_random_colors) viz.spin(); } +TEST(Viz, show_widget_merger) +{ + WWidgetMerger merger; + merger.addWidget(WCube(Vec3d::all(0.0), Vec3d::all(1.0), true, Color::gold())); + + RNG& rng = theRNG(); + for(int i = 0; i < 77; ++i) + { + Vec3b c; + rng.fill(c, RNG::NORMAL, Scalar::all(128), Scalar::all(48), true); + merger.addWidget(WSphere(Vec3d(c)*(1.0/255.0), 7.0/255.0, 10, Color(c[2], c[1], c[0]))); + } + merger.finalize(); + + Viz3d viz("show_mesh_random_color"); + viz.showWidget("coo", WCoordinateSystem()); + viz.showWidget("merger", merger); + viz.showWidget("text2d", WText("Widget merger", Point(20, 20), 20, Color::green())); + viz.spin(); +} + TEST(Viz, show_textured_mesh) { Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); @@ -170,7 +193,7 @@ TEST(Viz, show_textured_mesh) tcoords.push_back(Vec2d(1.0, i/64.0)); } - for(size_t i = 0; i < points.size()/2-1; ++i) + for(int i = 0; i < (int)points.size()/2-1; ++i) { int polys[] = {3, 2*i, 2*i+1, 2*i+2, 3, 2*i+1, 2*i+2, 2*i+3}; polygons.insert(polygons.end(), polys, polys + sizeof(polys)/sizeof(polys[0])); @@ -193,12 +216,18 @@ TEST(Viz, show_textured_mesh) TEST(Viz, show_polyline) { - Mat polyline(1, 32, CV_64FC3); - for(size_t i = 0; i < polyline.total(); ++i) + const Color palette[] = { Color::red(), Color::green(), Color::blue(), Color::gold(), Color::raspberry(), Color::bluberry(), Color::lime() }; + size_t palette_size = sizeof(palette)/sizeof(palette[0]); + + Mat polyline(1, 32, CV_64FC3), colors(1, 32, CV_8UC3); + for(int i = 0; i < (int)polyline.total(); ++i) + { polyline.at(i) = Vec3d(i/16.0, cos(i * CV_PI/6), sin(i * CV_PI/6)); + colors.at(i) = palette[i & palette_size]; + } Viz3d viz("show_polyline"); - viz.showWidget("polyline", WPolyLine(Mat(polyline), Color::apricot())); + viz.showWidget("polyline", WPolyLine(polyline, colors)); viz.showWidget("coosys", WCoordinateSystem()); viz.showWidget("text2d", WText("Polyline", Point(20, 20), 20, Color::green())); viz.spin(); @@ -222,13 +251,14 @@ TEST(Viz, show_sampled_normals) TEST(Viz, show_trajectories) { std::vector path = generate_test_trajectory(), sub0, sub1, sub2, sub3, sub4, sub5; - - Mat(path).rowRange(0, path.size()/10+1).copyTo(sub0); - Mat(path).rowRange(path.size()/10, path.size()/5+1).copyTo(sub1); - Mat(path).rowRange(path.size()/5, 11*path.size()/12).copyTo(sub2); - Mat(path).rowRange(11*path.size()/12, path.size()).copyTo(sub3); - Mat(path).rowRange(3*path.size()/4, 33*path.size()/40).copyTo(sub4); - Mat(path).rowRange(33*path.size()/40, 9*path.size()/10).copyTo(sub5); + int size =(int)path.size(); + + Mat(path).rowRange(0, size/10+1).copyTo(sub0); + Mat(path).rowRange(size/10, size/5+1).copyTo(sub1); + Mat(path).rowRange(size/5, 11*size/12).copyTo(sub2); + Mat(path).rowRange(11*size/12, size).copyTo(sub3); + Mat(path).rowRange(3*size/4, 33*size/40).copyTo(sub4); + Mat(path).rowRange(33*size/40, 9*size/10).copyTo(sub5); Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); Viz3d viz("show_trajectories"); @@ -259,7 +289,7 @@ TEST(Viz, show_trajectory_reposition) Viz3d viz("show_trajectory_reposition_to_origin"); viz.showWidget("coos", WCoordinateSystem()); - viz.showWidget("sub3", WTrajectory(Mat(path).rowRange(0, path.size()/3), WTrajectory::BOTH, 0.2, Color::brown()), path.front().inv()); + viz.showWidget("sub3", WTrajectory(Mat(path).rowRange(0, (int)path.size()/3), WTrajectory::BOTH, 0.2, Color::brown()), path.front().inv()); viz.showWidget("text2d", WText("Trajectory resposition to origin", Point(20, 20), 20, Color::green())); viz.spin(); } diff --git a/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp b/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp index f4dd4e5e4e..424a38e93a 100644 --- a/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp +++ b/samples/cpp/tutorial_code/Histograms_Matching/compareHist_Demo.cpp @@ -40,13 +40,13 @@ int main( int argc, char** argv ) hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) ); - /// Using 30 bins for hue and 32 for saturation + /// Using 50 bins for hue and 60 for saturation int h_bins = 50; int s_bins = 60; int histSize[] = { h_bins, s_bins }; - // hue varies from 0 to 256, saturation from 0 to 180 - float s_ranges[] = { 0, 256 }; + // hue varies from 0 to 179, saturation from 0 to 255 float h_ranges[] = { 0, 180 }; + float s_ranges[] = { 0, 256 }; const float* ranges[] = { h_ranges, s_ranges };