diff --git a/CMakeLists.txt b/CMakeLists.txt index 166257eca5..3273eda4da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1617,6 +1617,10 @@ if(ENABLE_CONFIG_VERIFICATION) ocv_verify_config() endif() +if(HAVE_CUDA AND COMMAND CUDA_BUILD_CLEAN_TARGET) + CUDA_BUILD_CLEAN_TARGET() +endif() + ocv_cmake_hook(POST_FINALIZE) # ---------------------------------------------------------------------------- diff --git a/cmake/OpenCVCompilerOptions.cmake b/cmake/OpenCVCompilerOptions.cmake index 87b2161b33..080c78c547 100644 --- a/cmake/OpenCVCompilerOptions.cmake +++ b/cmake/OpenCVCompilerOptions.cmake @@ -191,7 +191,6 @@ if(CV_GCC OR CV_CLANG) # Profiling? if(ENABLE_PROFILING) - add_extra_compiler_option("-pg -g") # turn off incompatible options foreach(flags CMAKE_CXX_FLAGS CMAKE_C_FLAGS CMAKE_CXX_FLAGS_RELEASE CMAKE_C_FLAGS_RELEASE CMAKE_CXX_FLAGS_DEBUG CMAKE_C_FLAGS_DEBUG OPENCV_EXTRA_FLAGS_RELEASE OPENCV_EXTRA_FLAGS_DEBUG OPENCV_EXTRA_C_FLAGS OPENCV_EXTRA_CXX_FLAGS) @@ -199,6 +198,9 @@ if(CV_GCC OR CV_CLANG) string(REPLACE "-ffunction-sections" "" ${flags} "${${flags}}") string(REPLACE "-fdata-sections" "" ${flags} "${${flags}}") endforeach() + # -pg should be placed both in the linker and in the compiler settings + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") + add_extra_compiler_option("-pg -g") else() if(MSVC) # TODO: Clang/C2 is not supported diff --git a/cmake/OpenCVDetectCUDA.cmake b/cmake/OpenCVDetectCUDA.cmake index 8846e6b97b..9696861e02 100644 --- a/cmake/OpenCVDetectCUDA.cmake +++ b/cmake/OpenCVDetectCUDA.cmake @@ -417,6 +417,13 @@ if(HAVE_CUDA) set(CUDA_cufft_LIBRARY_ABS ${CUDA_cufft_LIBRARY}) ocv_convert_to_lib_name(CUDA_cufft_LIBRARY ${CUDA_cufft_LIBRARY}) endif() + + if(CMAKE_GENERATOR MATCHES "Visual Studio" + AND NOT OPENCV_SKIP_CUDA_CMAKE_SUPPRESS_REGENERATION + ) + message(WARNING "CUDA with MSVS generator is detected. Disabling CMake re-run checks (CMAKE_SUPPRESS_REGENERATION=ON). You need to run CMake manually if updates are required.") + set(CMAKE_SUPPRESS_REGENERATION ON) + endif() endif() diff --git a/cmake/OpenCVFindOpenBLAS.cmake b/cmake/OpenCVFindOpenBLAS.cmake index ae2daaa194..6cb486d95d 100644 --- a/cmake/OpenCVFindOpenBLAS.cmake +++ b/cmake/OpenCVFindOpenBLAS.cmake @@ -46,6 +46,7 @@ SET(Open_BLAS_INCLUDE_SEARCH_PATHS $ENV{OpenBLAS_HOME} $ENV{OpenBLAS_HOME}/include + $ENV{OpenBLAS_HOME}/include/openblas /opt/OpenBLAS/include /usr/local/include/openblas /usr/include/openblas @@ -103,4 +104,4 @@ MARK_AS_ADVANCED( OpenBLAS_INCLUDE_DIR OpenBLAS_LIB OpenBLAS -) \ No newline at end of file +) diff --git a/modules/core/include/opencv2/core/cuda_types.hpp b/modules/core/include/opencv2/core/cuda_types.hpp index 45dc2cad1c..b33f06179d 100644 --- a/modules/core/include/opencv2/core/cuda_types.hpp +++ b/modules/core/include/opencv2/core/cuda_types.hpp @@ -106,8 +106,8 @@ namespace cv size_t step; - __CV_CUDA_HOST_DEVICE__ T* ptr(int y = 0) { return ( T*)( ( char*)DevPtr::data + y * step); } - __CV_CUDA_HOST_DEVICE__ const T* ptr(int y = 0) const { return (const T*)( (const char*)DevPtr::data + y * step); } + __CV_CUDA_HOST_DEVICE__ T* ptr(int y = 0) { return ( T*)( ( char*)(((DevPtr*)this)->data) + y * step); } + __CV_CUDA_HOST_DEVICE__ const T* ptr(int y = 0) const { return (const T*)( (const char*)(((DevPtr*)this)->data) + y * step); } __CV_CUDA_HOST_DEVICE__ T& operator ()(int y, int x) { return ptr(y)[x]; } __CV_CUDA_HOST_DEVICE__ const T& operator ()(int y, int x) const { return ptr(y)[x]; } diff --git a/modules/dnn/perf/perf_net.cpp b/modules/dnn/perf/perf_net.cpp index f4d008f161..3bee2313c0 100644 --- a/modules/dnn/perf/perf_net.cpp +++ b/modules/dnn/perf/perf_net.cpp @@ -216,6 +216,19 @@ PERF_TEST_P_(DNNTestNetwork, YOLOv4) processNet("dnn/yolov4.weights", "dnn/yolov4.cfg", "", inp); } +PERF_TEST_P_(DNNTestNetwork, YOLOv4_tiny) +{ + if (backend == DNN_BACKEND_HALIDE) + throw SkipTestException(""); + if (target == DNN_TARGET_MYRIAD) + throw SkipTestException(""); + Mat sample = imread(findDataFile("dnn/dog416.png")); + cvtColor(sample, sample, COLOR_BGR2RGB); + Mat inp; + sample.convertTo(inp, CV_32FC3, 1.0f / 255, 0); + processNet("dnn/yolov4-tiny.weights", "dnn/yolov4-tiny.cfg", "", inp); +} + PERF_TEST_P_(DNNTestNetwork, EAST_text_detection) { if (backend == DNN_BACKEND_HALIDE) diff --git a/modules/dnn/src/darknet/darknet_io.cpp b/modules/dnn/src/darknet/darknet_io.cpp index 664a1d617b..f6504b96c7 100644 --- a/modules/dnn/src/darknet/darknet_io.cpp +++ b/modules/dnn/src/darknet/darknet_io.cpp @@ -363,6 +363,28 @@ namespace cv { fused_layer_names.push_back(last_layer); } + void setSlice(int input_index, int split_size, int group_id) + { + int begin[] = {0, split_size * group_id, 0, 0}; + cv::dnn::DictValue paramBegin = cv::dnn::DictValue::arrayInt(begin, 4); + + int end[] = {-1, begin[1] + split_size, -1, -1}; + cv::dnn::DictValue paramEnd = cv::dnn::DictValue::arrayInt(end, 4); + + darknet::LayerParameter lp; + lp.layer_name = cv::format("slice_%d", layer_id); + lp.layer_type = "Slice"; + lp.layerParams.set("begin", paramBegin); + lp.layerParams.set("end", paramEnd); + + lp.bottom_indexes.push_back(fused_layer_names.at(input_index)); + net->layers.push_back(lp); + + layer_id++; + last_layer = lp.layer_name; + fused_layer_names.push_back(last_layer); + } + void setReorg(int stride) { cv::dnn::LayerParams reorg_params; @@ -717,6 +739,7 @@ namespace cv { { std::string bottom_layers = getParam(layer_params, "layers", ""); CV_Assert(!bottom_layers.empty()); + int groups = getParam(layer_params, "groups", 1); std::vector layers_vec = getNumbers(bottom_layers); tensor_shape[0] = 0; @@ -725,10 +748,31 @@ namespace cv { tensor_shape[0] += net->out_channels_vec[layers_vec[k]]; } - if (layers_vec.size() == 1) - setParams.setIdentity(layers_vec.at(0)); + if (groups > 1) + { + int group_id = getParam(layer_params, "group_id", 0); + tensor_shape[0] /= groups; + int split_size = tensor_shape[0] / layers_vec.size(); + for (size_t k = 0; k < layers_vec.size(); ++k) + setParams.setSlice(layers_vec[k], split_size, group_id); + + if (layers_vec.size() > 1) + { + // layer ids in layers_vec - inputs of Slice layers + // after adding offset to layers_vec: layer ids - ouputs of Slice layers + for (size_t k = 0; k < layers_vec.size(); ++k) + layers_vec[k] += layers_vec.size(); + + setParams.setConcat(layers_vec.size(), layers_vec.data()); + } + } else - setParams.setConcat(layers_vec.size(), layers_vec.data()); + { + if (layers_vec.size() == 1) + setParams.setIdentity(layers_vec.at(0)); + else + setParams.setConcat(layers_vec.size(), layers_vec.data()); + } } else if (layer_type == "dropout" || layer_type == "cost") { diff --git a/modules/dnn/src/layers/reorg_layer.cpp b/modules/dnn/src/layers/reorg_layer.cpp index f8f7bc6269..da1c61adac 100644 --- a/modules/dnn/src/layers/reorg_layer.cpp +++ b/modules/dnn/src/layers/reorg_layer.cpp @@ -41,9 +41,15 @@ //M*/ #include "../precomp.hpp" -#include "../op_cuda.hpp" -#include "../op_inf_engine.hpp" +#include +#include + +#ifdef HAVE_OPENCL +#include "opencl_kernels_dnn.hpp" +#endif + +#include "../op_inf_engine.hpp" #ifdef HAVE_DNN_NGRAPH #include "../ie_ngraph.hpp" #if INF_ENGINE_VER_MAJOR_GT(INF_ENGINE_RELEASE_2020_4) @@ -53,13 +59,7 @@ #endif #endif -#include -#include - -#ifdef HAVE_OPENCL -#include "opencl_kernels_dnn.hpp" -#endif - +#include "../op_cuda.hpp" #ifdef HAVE_CUDA #include "../cuda4dnn/primitives/reorg.hpp" using namespace cv::dnn::cuda4dnn; diff --git a/modules/dnn/src/layers/slice_layer.cpp b/modules/dnn/src/layers/slice_layer.cpp index d771407b08..7b3a25fc05 100644 --- a/modules/dnn/src/layers/slice_layer.cpp +++ b/modules/dnn/src/layers/slice_layer.cpp @@ -209,6 +209,10 @@ public: #ifdef HAVE_OPENCL bool forward_ocl(InputArrayOfArrays inputs_, OutputArrayOfArrays outputs_, OutputArrayOfArrays internals_) { +#if 1 + // TODO fix that (brokes YOLOv4-tiny) + return false; +#else std::vector inputs; std::vector outputs; @@ -251,7 +255,8 @@ public: } return true; - } +#endif + } #endif void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE diff --git a/modules/dnn/test/test_common.impl.hpp b/modules/dnn/test/test_common.impl.hpp index b33b8e40d9..fa86f9b1c7 100644 --- a/modules/dnn/test/test_common.impl.hpp +++ b/modules/dnn/test/test_common.impl.hpp @@ -100,9 +100,12 @@ void normAssertDetections( const char *comment /*= ""*/, double confThreshold /*= 0.0*/, double scores_diff /*= 1e-5*/, double boxes_iou_diff /*= 1e-4*/) { + ASSERT_FALSE(testClassIds.empty()) << "No detections"; std::vector matchedRefBoxes(refBoxes.size(), false); + std::vector refBoxesIoUDiff(refBoxes.size(), 1.0); for (int i = 0; i < testBoxes.size(); ++i) { + //cout << "Test[i=" << i << "]: score=" << testScores[i] << " id=" << testClassIds[i] << " box " << testBoxes[i] << endl; double testScore = testScores[i]; if (testScore < confThreshold) continue; @@ -119,6 +122,7 @@ void normAssertDetections( double interArea = (testBox & refBoxes[j]).area(); double iou = interArea / (testBox.area() + refBoxes[j].area() - interArea); topIoU = std::max(topIoU, iou); + refBoxesIoUDiff[j] = std::min(refBoxesIoUDiff[j], 1.0f - iou); if (1.0 - iou < boxes_iou_diff) { matched = true; @@ -141,7 +145,9 @@ void normAssertDetections( if (!matchedRefBoxes[i] && refScores[i] > confThreshold) { std::cout << cv::format("Unmatched reference: class %d score %f box ", - refClassIds[i], refScores[i]) << refBoxes[i] << std::endl; + refClassIds[i], refScores[i]) << refBoxes[i] + << " IoU diff: " << refBoxesIoUDiff[i] + << std::endl; EXPECT_LE(refScores[i], confThreshold) << comment; } } diff --git a/modules/dnn/test/test_darknet_importer.cpp b/modules/dnn/test/test_darknet_importer.cpp index 61dd5414e2..c0143d9f3f 100644 --- a/modules/dnn/test/test_darknet_importer.cpp +++ b/modules/dnn/test/test_darknet_importer.cpp @@ -254,6 +254,13 @@ public: } + if (cvIsNaN(iouDiff)) + { + if (b == 0) + std::cout << "Skip accuracy checks" << std::endl; + continue; + } + normAssertDetections(refClassIds[b], refConfidences[b], refBoxes[b], nms_classIds, nms_confidences, nms_boxes, format("batch size %d, sample %d\n", batch_size, b).c_str(), confThreshold, scoreDiff, iouDiff); } @@ -467,7 +474,7 @@ TEST_P(Test_Darknet_nets_async, Accuracy) } INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_nets_async, Combine( - Values("yolo-voc", "tiny-yolo-voc", "yolov3", "yolov4"), + Values("yolo-voc", "tiny-yolo-voc", "yolov3", "yolov4", "yolov4-tiny"), dnnBackendsAndTargets() )); @@ -618,6 +625,63 @@ TEST_P(Test_Darknet_nets, YOLOv4) } } +TEST_P(Test_Darknet_nets, YOLOv4_tiny) +{ + applyTestTag( + target == DNN_TARGET_CPU ? CV_TEST_TAG_MEMORY_512MB : CV_TEST_TAG_MEMORY_1GB + ); + + const double confThreshold = 0.5; + // batchId, classId, confidence, left, top, right, bottom + const int N0 = 2; + const int N1 = 3; + static const float ref_[/* (N0 + N1) * 7 */] = { +0, 7, 0.85935f, 0.593484f, 0.141211f, 0.920356f, 0.291593f, +0, 16, 0.795188f, 0.169207f, 0.386886f, 0.423753f, 0.933004f, + +1, 2, 0.996832f, 0.653802f, 0.464573f, 0.815193f, 0.653292f, +1, 2, 0.963325f, 0.451151f, 0.458915f, 0.496255f, 0.52241f, +1, 0, 0.926244f, 0.194851f, 0.361743f, 0.260277f, 0.632364f, + }; + Mat ref(N0 + N1, 7, CV_32FC1, (void*)ref_); + + double scoreDiff = 0.01f; + double iouDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 0.15 : 0.01f; + + std::string config_file = "yolov4-tiny.cfg"; + std::string weights_file = "yolov4-tiny.weights"; + +#if defined(INF_ENGINE_RELEASE) + if (target == DNN_TARGET_MYRIAD) // bad accuracy + iouDiff = std::numeric_limits::quiet_NaN(); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL) + iouDiff = std::numeric_limits::quiet_NaN(); + if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || + backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && DNN_TARGET_OPENCL_FP16) + iouDiff = std::numeric_limits::quiet_NaN(); +#endif + + { + SCOPED_TRACE("batch size 1"); + testDarknetModel(config_file, weights_file, ref.rowRange(0, N0), scoreDiff, iouDiff, confThreshold); + } + + { + SCOPED_TRACE("batch size 2"); + testDarknetModel(config_file, weights_file, ref, scoreDiff, iouDiff, confThreshold); + } + +#if defined(INF_ENGINE_RELEASE) + if (target == DNN_TARGET_MYRIAD) // bad accuracy + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_VERSION); + if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && target == DNN_TARGET_OPENCL) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_VERSION); + if ((backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 || + backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) && DNN_TARGET_OPENCL_FP16) + applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL_FP16, CV_TEST_TAG_DNN_SKIP_IE_VERSION); +#endif +} + INSTANTIATE_TEST_CASE_P(/**/, Test_Darknet_nets, dnnBackendsAndTargets()); @@ -658,6 +722,12 @@ TEST_P(Test_Darknet_layers, reorg) testDarknetLayer("reorg"); } +TEST_P(Test_Darknet_layers, route) +{ + testDarknetLayer("route"); + testDarknetLayer("route_multi"); +} + TEST_P(Test_Darknet_layers, maxpool) { #if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_GE(2020020000) diff --git a/modules/flann/include/opencv2/flann/autotuned_index.h b/modules/flann/include/opencv2/flann/autotuned_index.h index eb4554f077..54a60a73d6 100644 --- a/modules/flann/include/opencv2/flann/autotuned_index.h +++ b/modules/flann/include/opencv2/flann/autotuned_index.h @@ -497,7 +497,7 @@ private: const int nn = 1; const size_t SAMPLE_COUNT = 1000; - assert(bestIndex_ != NULL); // must have a valid index + CV_Assert(bestIndex_ != NULL && "Requires a valid index"); // must have a valid index float speedup = 0; diff --git a/modules/flann/include/opencv2/flann/dist.h b/modules/flann/include/opencv2/flann/dist.h index b092b531a1..4cf32d5987 100644 --- a/modules/flann/include/opencv2/flann/dist.h +++ b/modules/flann/include/opencv2/flann/dist.h @@ -506,7 +506,7 @@ struct Hamming2 const uint64_t* pa = reinterpret_cast(a); const uint64_t* pb = reinterpret_cast(b); ResultType result = 0; - size /= (sizeof(uint64_t)/sizeof(unsigned char)); + size /= long_word_size_; for(size_t i = 0; i < size; ++i ) { result += popcnt64(*pa ^ *pb); ++pa; @@ -516,7 +516,7 @@ struct Hamming2 const uint32_t* pa = reinterpret_cast(a); const uint32_t* pb = reinterpret_cast(b); ResultType result = 0; - size /= (sizeof(uint32_t)/sizeof(unsigned char)); + size /= long_word_size_; for(size_t i = 0; i < size; ++i ) { result += popcnt32(*pa ^ *pb); ++pa; @@ -525,6 +525,13 @@ struct Hamming2 #endif return result; } + +private: +#ifdef FLANN_PLATFORM_64_BIT + static const size_t long_word_size_ = sizeof(uint64_t)/sizeof(unsigned char); +#else + static const size_t long_word_size_ = sizeof(uint32_t)/sizeof(unsigned char); +#endif }; diff --git a/modules/flann/include/opencv2/flann/flann_base.hpp b/modules/flann/include/opencv2/flann/flann_base.hpp index 83606d232f..641fdb01e2 100644 --- a/modules/flann/include/opencv2/flann/flann_base.hpp +++ b/modules/flann/include/opencv2/flann/flann_base.hpp @@ -34,7 +34,6 @@ //! @cond IGNORED #include -#include #include #include "general.h" diff --git a/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h b/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h index 20304ede73..a52166d3c4 100644 --- a/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h +++ b/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h @@ -35,7 +35,6 @@ #include #include -#include #include #include @@ -153,7 +152,7 @@ private: int n = indices_length; int rnd = rand_int(n); - assert(rnd >=0 && rnd < n); + CV_DbgAssert(rnd >=0 && rnd < n); centers[0] = dsindices[rnd]; @@ -208,7 +207,7 @@ private: // Choose one random center and set the closestDistSq values int index = rand_int(n); - assert(index >=0 && index < n); + CV_DbgAssert(index >=0 && index < n); centers[0] = dsindices[index]; // Computing distance^2 will have the advantage of even higher probability further to pick new centers @@ -295,7 +294,7 @@ private: // Choose one random center and set the closestDistSq values int index = rand_int(n); - assert(index >=0 && index < n); + CV_DbgAssert(index >=0 && index < n); centers[0] = dsindices[index]; for (int i = 0; i < n; i++) { @@ -386,7 +385,6 @@ public: throw FLANNException("Unknown algorithm for choosing initial centers."); } - trees_ = get_param(params,"trees",4); root = new NodePtr[trees_]; indices = new int*[trees_]; @@ -565,10 +563,10 @@ public: NodePtr node = branch.node; findNN(node, result, vec, checks, maxChecks, heap, checked); } - assert(result.full()); delete heap; + CV_Assert(result.full()); } IndexParams getParameters() const CV_OVERRIDE diff --git a/modules/flann/include/opencv2/flann/index_testing.h b/modules/flann/include/opencv2/flann/index_testing.h index 47b6f0b86f..f3d147588d 100644 --- a/modules/flann/include/opencv2/flann/index_testing.h +++ b/modules/flann/include/opencv2/flann/index_testing.h @@ -34,7 +34,6 @@ //! @cond IGNORED #include -#include #include #include "matrix.h" diff --git a/modules/flann/include/opencv2/flann/kdtree_index.h b/modules/flann/include/opencv2/flann/kdtree_index.h index 472350516f..acc87a3198 100644 --- a/modules/flann/include/opencv2/flann/kdtree_index.h +++ b/modules/flann/include/opencv2/flann/kdtree_index.h @@ -35,7 +35,6 @@ #include #include -#include #include #include "general.h" @@ -433,7 +432,7 @@ private: if (trees_>0) { searchLevelExact(result, vec, tree_roots_[0], 0.0, epsError); } - assert(result.full()); + CV_Assert(result.full()); } /** @@ -462,7 +461,7 @@ private: delete heap; - assert(result.full()); + CV_Assert(result.full()); } diff --git a/modules/flann/include/opencv2/flann/kdtree_single_index.h b/modules/flann/include/opencv2/flann/kdtree_single_index.h index ce4c1c5b7e..e571403b10 100644 --- a/modules/flann/include/opencv2/flann/kdtree_single_index.h +++ b/modules/flann/include/opencv2/flann/kdtree_single_index.h @@ -35,7 +35,6 @@ #include #include -#include #include #include "general.h" @@ -214,11 +213,11 @@ public: */ void knnSearch(const Matrix& queries, Matrix& indices, Matrix& dists, int knn, const SearchParams& params) CV_OVERRIDE { - assert(queries.cols == veclen()); - assert(indices.rows >= queries.rows); - assert(dists.rows >= queries.rows); - assert(int(indices.cols) >= knn); - assert(int(dists.cols) >= knn); + CV_Assert(queries.cols == veclen()); + CV_Assert(indices.rows >= queries.rows); + CV_Assert(dists.rows >= queries.rows); + CV_Assert(int(indices.cols) >= knn); + CV_Assert(int(dists.cols) >= knn); KNNSimpleResultSet resultSet(knn); for (size_t i = 0; i < queries.rows; i++) { diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h index f743d75224..e290fc5a26 100644 --- a/modules/flann/include/opencv2/flann/kmeans_index.h +++ b/modules/flann/include/opencv2/flann/kmeans_index.h @@ -35,7 +35,6 @@ #include #include -#include #include #include @@ -152,7 +151,7 @@ public: int n = indices_length; int rnd = rand_int(n); - assert(rnd >=0 && rnd < n); + CV_DbgAssert(rnd >=0 && rnd < n); centers[0] = indices[rnd]; @@ -207,7 +206,7 @@ public: // Choose one random center and set the closestDistSq values int index = rand_int(n); - assert(index >=0 && index < n); + CV_DbgAssert(index >=0 && index < n); centers[0] = indices[index]; for (int i = 0; i < n; i++) { @@ -502,9 +501,9 @@ public: KMeansNodePtr node = branch.node; findNN(node, result, vec, checks, maxChecks, heap); } - assert(result.full()); - delete heap; + + CV_Assert(result.full()); } } @@ -663,7 +662,7 @@ private: memset(mean,0,veclen_*sizeof(DistanceType)); - for (size_t i=0; i<(size_t)indices_length; ++i) { + for (int i=0; i(), veclen_); } for (size_t j=0; j(), veclen_); DistanceType tmp = 0; @@ -726,15 +725,6 @@ private: } - cv::AutoBuffer dcenters_buf(branching*veclen_); - Matrix dcenters(dcenters_buf.data(), branching, veclen_); - for (int i=0; i radiuses(branching); cv::AutoBuffer count_buf(branching); int* count = count_buf.data(); @@ -748,10 +738,10 @@ private: int* belongs_to = belongs_to_buf.data(); for (int i=0; inew_sq_dist) { belongs_to[i] = j; sq_dist = new_sq_dist; @@ -763,6 +753,15 @@ private: count[belongs_to[i]]++; } + cv::AutoBuffer dcenters_buf(branching*veclen_); + Matrix dcenters(dcenters_buf.data(), branching, veclen_); + for (int i=0; i -#include #include #include #include @@ -53,6 +52,11 @@ #include "random.h" #include "saving.h" +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4702) //disable unreachable code +#endif + namespace cvflann { @@ -191,11 +195,11 @@ public: */ virtual void knnSearch(const Matrix& queries, Matrix& indices, Matrix& dists, int knn, const SearchParams& params) CV_OVERRIDE { - assert(queries.cols == veclen()); - assert(indices.rows >= queries.rows); - assert(dists.rows >= queries.rows); - assert(int(indices.cols) >= knn); - assert(int(dists.cols) >= knn); + CV_Assert(queries.cols == veclen()); + CV_Assert(indices.rows >= queries.rows); + CV_Assert(dists.rows >= queries.rows); + CV_Assert(int(indices.cols) >= knn); + CV_Assert(int(dists.cols) >= knn); KNNUniqueResultSet resultSet(knn); @@ -391,6 +395,10 @@ private: }; } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + //! @endcond #endif //OPENCV_FLANN_LSH_INDEX_H_ diff --git a/modules/flann/include/opencv2/flann/lsh_table.h b/modules/flann/include/opencv2/flann/lsh_table.h index 8f5250171b..a189562d3a 100644 --- a/modules/flann/include/opencv2/flann/lsh_table.h +++ b/modules/flann/include/opencv2/flann/lsh_table.h @@ -58,6 +58,12 @@ #include "dynamic_bitset.h" #include "matrix.h" +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4702) //disable unreachable code +#endif + + namespace cvflann { @@ -162,8 +168,7 @@ public: { feature_size_ = feature_size; CV_UNUSED(key_size); - std::cerr << "LSH is not implemented for that type" << std::endl; - assert(0); + CV_Error(cv::Error::StsUnsupportedFormat, "LSH is not implemented for that type" ); } /** Add a feature to the table @@ -243,8 +248,7 @@ public: */ size_t getKey(const ElementType* /*feature*/) const { - std::cerr << "LSH is not implemented for that type" << std::endl; - assert(0); + CV_Error(cv::Error::StsUnsupportedFormat, "LSH is not implemented for that type" ); return 0; } @@ -510,6 +514,10 @@ inline LshStats LshTable::getStats() const } } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //! @endcond diff --git a/modules/flann/include/opencv2/flann/nn_index.h b/modules/flann/include/opencv2/flann/nn_index.h index 00fe6ec5ae..fbb4c7924c 100644 --- a/modules/flann/include/opencv2/flann/nn_index.h +++ b/modules/flann/include/opencv2/flann/nn_index.h @@ -69,11 +69,11 @@ public: */ virtual void knnSearch(const Matrix& queries, Matrix& indices, Matrix& dists, int knn, const SearchParams& params) { - assert(queries.cols == veclen()); - assert(indices.rows >= queries.rows); - assert(dists.rows >= queries.rows); - assert(int(indices.cols) >= knn); - assert(int(dists.cols) >= knn); + CV_Assert(queries.cols == veclen()); + CV_Assert(indices.rows >= queries.rows); + CV_Assert(dists.rows >= queries.rows); + CV_Assert(int(indices.cols) >= knn); + CV_Assert(int(dists.cols) >= knn); #if 0 KNNResultSet resultSet(knn); diff --git a/modules/flann/include/opencv2/flann/simplex_downhill.h b/modules/flann/include/opencv2/flann/simplex_downhill.h index 20b7e03c92..02970148b2 100644 --- a/modules/flann/include/opencv2/flann/simplex_downhill.h +++ b/modules/flann/include/opencv2/flann/simplex_downhill.h @@ -72,7 +72,7 @@ float optimizeSimplexDownhill(T* points, int n, F func, float* vals = NULL ) { const int MAX_ITERATIONS = 10; - assert(n>0); + CV_DbgAssert(n>0); T* p_o = new T[n]; T* p_r = new T[n]; diff --git a/modules/flann/src/miniflann.cpp b/modules/flann/src/miniflann.cpp index 1cbe57f887..6cb99564e5 100644 --- a/modules/flann/src/miniflann.cpp +++ b/modules/flann/src/miniflann.cpp @@ -801,7 +801,7 @@ bool Index::load(InputArray _data, const String& filename) loadIndex< ::cvflann::MaxDistance >(this, index, data, fin); break; case FLANN_DIST_HIST_INTERSECT: - loadIndex< ::cvflann::HistIntersectionDistance >(index, data, fin); + loadIndex< ::cvflann::HistIntersectionDistance >(this, index, data, fin); break; case FLANN_DIST_HELLINGER: loadIndex< ::cvflann::HellingerDistance >(this, index, data, fin); diff --git a/modules/imgcodecs/include/opencv2/imgcodecs.hpp b/modules/imgcodecs/include/opencv2/imgcodecs.hpp index 89b014d768..97ca866e1b 100644 --- a/modules/imgcodecs/include/opencv2/imgcodecs.hpp +++ b/modules/imgcodecs/include/opencv2/imgcodecs.hpp @@ -208,16 +208,17 @@ can be saved using this function, with these exceptions: - PNG images with an alpha channel can be saved using this function. To do this, create 8-bit (or 16-bit) 4-channel image BGRA, where the alpha channel goes last. Fully transparent pixels should have alpha set to 0, fully opaque pixels should have alpha set to 255/65535 (see the code sample below). +- Multiple images (vector of Mat) can be saved in TIFF format (see the code sample below). If the format, depth or channel order is different, use Mat::convertTo and cv::cvtColor to convert it before saving. Or, use the universal FileStorage I/O functions to save the image to XML or YAML format. -The sample below shows how to create a BGRA image and save it to a PNG file. It also demonstrates how to set custom -compression parameters: +The sample below shows how to create a BGRA image, how to set custom compression parameters and save it to a PNG file. +It also demonstrates how to save multiple images in a TIFF file: @include snippets/imgcodecs_imwrite.cpp @param filename Name of the file. -@param img Image to be saved. +@param img (Mat or vector of Mat) Image or Images to be saved. @param params Format-specific parameters encoded as pairs (paramId_1, paramValue_1, paramId_2, paramValue_2, ... .) see cv::ImwriteFlags */ CV_EXPORTS_W bool imwrite( const String& filename, InputArray img, diff --git a/modules/imgcodecs/test/test_read_write.cpp b/modules/imgcodecs/test/test_read_write.cpp index 83451982db..890d47a543 100644 --- a/modules/imgcodecs/test/test_read_write.cpp +++ b/modules/imgcodecs/test/test_read_write.cpp @@ -31,6 +31,7 @@ const tuple images[] = #ifdef HAVE_PNG make_tuple("../cv/shared/pic1.png", Size(400, 300)), #endif + make_tuple("../highgui/readwrite/ordinary.bmp", Size(480, 272)), }; TEST_P(Imgcodecs_Resize, imread_reduce_flags) diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 937a8bcf88..d23f2b0db9 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -385,7 +385,7 @@ enum FloodFillFlags { //! @addtogroup imgproc_shape //! @{ -//! connected components algorithm output formats +//! connected components statistics enum ConnectedComponentsTypes { CC_STAT_LEFT = 0, //!< The leftmost (x) coordinate which is the inclusive start of the bounding //!< box in the horizontal direction. @@ -3786,9 +3786,9 @@ parallel framework is enabled and if the rows of the image are at least twice th @param image the 8-bit single-channel image to be labeled @param labels destination labeled image -@param stats statistics output for each label, including the background label, see below for -available statistics. Statistics are accessed via stats(label, COLUMN) where COLUMN is one of -#ConnectedComponentsTypes. The data type is CV_32S. +@param stats statistics output for each label, including the background label. +Statistics are accessed via stats(label, COLUMN) where COLUMN is one of +#ConnectedComponentsTypes, selecting the statistic. The data type is CV_32S. @param centroids centroid output for each label, including the background label. Centroids are accessed via centroids(label, 0) for x and centroids(label, 1) for y. The data type CV_64F. @param connectivity 8 or 4 for 8-way or 4-way connectivity respectively @@ -3802,9 +3802,9 @@ CV_EXPORTS_AS(connectedComponentsWithStatsWithAlgorithm) int connectedComponents /** @overload @param image the 8-bit single-channel image to be labeled @param labels destination labeled image -@param stats statistics output for each label, including the background label, see below for -available statistics. Statistics are accessed via stats(label, COLUMN) where COLUMN is one of -#ConnectedComponentsTypes. The data type is CV_32S. +@param stats statistics output for each label, including the background label. +Statistics are accessed via stats(label, COLUMN) where COLUMN is one of +#ConnectedComponentsTypes, selecting the statistic. The data type is CV_32S. @param centroids centroid output for each label, including the background label. Centroids are accessed via centroids(label, 0) for x and centroids(label, 1) for y. The data type CV_64F. @param connectivity 8 or 4 for 8-way or 4-way connectivity respectively diff --git a/samples/cpp/tutorial_code/snippets/imgcodecs_imwrite.cpp b/samples/cpp/tutorial_code/snippets/imgcodecs_imwrite.cpp index 10f4151694..ad9ee6d6b2 100644 --- a/samples/cpp/tutorial_code/snippets/imgcodecs_imwrite.cpp +++ b/samples/cpp/tutorial_code/snippets/imgcodecs_imwrite.cpp @@ -3,7 +3,7 @@ using namespace cv; using namespace std; -static void createAlphaMat(Mat &mat) +static void paintAlphaMat(Mat &mat) { CV_Assert(mat.channels() == 4); for (int i = 0; i < mat.rows; ++i) @@ -21,9 +21,9 @@ static void createAlphaMat(Mat &mat) int main() { - // Create mat with alpha channel - Mat mat(480, 640, CV_8UC4); - createAlphaMat(mat); + Mat mat(480, 640, CV_8UC4); // Create a matrix with alpha channel + paintAlphaMat(mat); + vector compression_params; compression_params.push_back(IMWRITE_PNG_COMPRESSION); compression_params.push_back(9); @@ -37,9 +37,18 @@ int main() { fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what()); } + if (result) printf("Saved PNG file with alpha data.\n"); else printf("ERROR: Can't save PNG file.\n"); + + vector imgs; + imgs.push_back(mat); + imgs.push_back(~mat); + imgs.push_back(mat(Rect(0, 0, mat.cols / 2, mat.rows / 2))); + imwrite("test.tiff", imgs); + printf("Multiple files saved in test.tiff\n"); + return result ? 0 : 1; }