From 96ee83898ddffc4706ad814bfcdbfaf477ef1a5f Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sat, 10 Nov 2018 21:38:24 +0000 Subject: [PATCH 1/5] core(test): extend divideByZero test to verify SIMD code path --- modules/core/test/test_arithm.cpp | 80 +++++++++++++++++++++++++------ 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 0eb2318c76..78ad907603 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -2249,33 +2249,53 @@ void testDivideChecks(const Mat& dst) { for (int x = 0; x < dst.cols; x++) { - if (x == 2) + if ((x % 4) == 2) { EXPECT_EQ(0, dst.at(y, x)) << "dst(" << y << ", " << x << ") = " << dst.at(y, x); } + else + { + EXPECT_TRUE(0 == cvIsNaN((double)dst.at(y, x))) << "dst(" << y << ", " << x << ") = " << dst.at(y, x); + EXPECT_TRUE(0 == cvIsInf((double)dst.at(y, x))) << "dst(" << y << ", " << x << ") = " << dst.at(y, x); + } } } } - -template static inline -void testDivide() +template static inline +void testDivide(bool isUMat, double scale, bool largeSize, bool tailProcessing, bool roi) { Mat src1, src2; testDivideInitData(src1, src2); ASSERT_FALSE(src1.empty()); ASSERT_FALSE(src2.empty()); + if (largeSize) + { + repeat(src1.clone(), 1, 8, src1); + repeat(src2.clone(), 1, 8, src2); + } + if (tailProcessing) + { + src1 = src1(Rect(0, 0, src1.cols - 1, src1.rows)); + src2 = src2(Rect(0, 0, src2.cols - 1, src2.rows)); + } + if (!roi && tailProcessing) + { + src1 = src1.clone(); + src2 = src2.clone(); + } + Mat dst; if (!isUMat) { - cv::divide(src1, src2, dst); + cv::divide(src1, src2, dst, scale); } else { UMat usrc1, usrc2, udst; src1.copyTo(usrc1); src2.copyTo(usrc2); - cv::divide(usrc1, usrc2, udst); + cv::divide(usrc1, usrc2, udst, scale); udst.copyTo(dst); } @@ -2289,14 +2309,46 @@ void testDivide() } } -TEST(Core_DivideRules, type_32s) { testDivide(); } -TEST(UMat_Core_DivideRules, type_32s) { testDivide(); } -TEST(Core_DivideRules, type_16s) { testDivide(); } -TEST(UMat_Core_DivideRules, type_16s) { testDivide(); } -TEST(Core_DivideRules, type_32f) { testDivide(); } -TEST(UMat_Core_DivideRules, type_32f) { testDivide(); } -TEST(Core_DivideRules, type_64f) { testDivide(); } -TEST(UMat_Core_DivideRules, type_64f) { testDivide(); } +typedef tuple DivideRulesParam; +typedef testing::TestWithParam Core_DivideRules; + +TEST_P(Core_DivideRules, type_32s) +{ + DivideRulesParam param = GetParam(); + testDivide(get<0>(param), get<1>(param), get<2>(param), get<3>(param), get<4>(param)); +} +TEST_P(Core_DivideRules, type_16s) +{ + DivideRulesParam param = GetParam(); + testDivide(get<0>(param), get<1>(param), get<2>(param), get<3>(param), get<4>(param)); +} +TEST_P(Core_DivideRules, type_32f) +{ + DivideRulesParam param = GetParam(); + testDivide(get<0>(param), get<1>(param), get<2>(param), get<3>(param), get<4>(param)); +} +TEST_P(Core_DivideRules, type_64f) +{ + DivideRulesParam param = GetParam(); + testDivide(get<0>(param), get<1>(param), get<2>(param), get<3>(param), get<4>(param)); +} + + +INSTANTIATE_TEST_CASE_P(/* */, Core_DivideRules, testing::Combine( +/* isMat */ testing::Values(false), +/* scale */ testing::Values(1.0, 5.0), +/* largeSize */ testing::Bool(), +/* tail */ testing::Bool(), +/* roi */ testing::Bool() +)); + +INSTANTIATE_TEST_CASE_P(UMat, Core_DivideRules, testing::Combine( +/* isMat */ testing::Values(true), +/* scale */ testing::Values(1.0, 5.0), +/* largeSize */ testing::Bool(), +/* tail */ testing::Bool(), +/* roi */ testing::Bool() +)); TEST(Core_MinMaxIdx, rows_overflow) From 801c943009cd8ef6ecb10ce49c4dc3c1c4c7ebbf Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Sun, 11 Nov 2018 13:51:47 +0000 Subject: [PATCH 2/5] fix coverity reports --- modules/dnn/src/dnn.cpp | 2 +- modules/videoio/src/cap_v4l.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/dnn/src/dnn.cpp b/modules/dnn/src/dnn.cpp index 16547645a0..8880edbd2d 100644 --- a/modules/dnn/src/dnn.cpp +++ b/modules/dnn/src/dnn.cpp @@ -1801,7 +1801,7 @@ struct Net::Impl nextEltwiseLayer = nextData->layerInstance.dynamicCast(); if( !nextEltwiseLayer.empty() && pinsToKeep.count(lpNext) == 0 && - nextData->inputBlobsId.size() == 2 ) + nextData && nextData->inputBlobsId.size() == 2 ) { LayerData *eltwiseData = nextData; diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 4a628f961c..1e7af0cb24 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -348,7 +348,9 @@ struct CvCaptureCAM_V4L CV_FINAL : public CvCapture /*********************** Implementations ***************************************/ CvCaptureCAM_V4L::CvCaptureCAM_V4L() : deviceHandle(-1), bufferIndex(-1) -{} +{ + memset(×tamp, 0, sizeof(timestamp)); +} CvCaptureCAM_V4L::~CvCaptureCAM_V4L() { streaming(false); @@ -1739,7 +1741,6 @@ double CvCaptureCAM_V4L::getProperty(int property_id) const return value; } } - return -1.0; } bool CvCaptureCAM_V4L::icvSetFrameSize(int _width, int _height) From 6c76c8f88120e5e73372b7645ff646cf4566609e Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Mon, 12 Nov 2018 13:38:18 +0300 Subject: [PATCH 3/5] Add a test for FileNode::keys() --- modules/core/src/persistence_cpp.cpp | 11 +++++------ modules/core/test/test_io.cpp | 6 ++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/modules/core/src/persistence_cpp.cpp b/modules/core/src/persistence_cpp.cpp index 334c787c98..4b2fbb52d0 100644 --- a/modules/core/src/persistence_cpp.cpp +++ b/modules/core/src/persistence_cpp.cpp @@ -271,14 +271,13 @@ FileNode FileNode::operator[](int i) const std::vector FileNode::keys() const { + CV_Assert(isMap()); + std::vector res; - if (isMap()) + res.reserve(size()); + for (FileNodeIterator it = begin(); it != end(); ++it) { - res.reserve(size()); - for (FileNodeIterator it = begin(); it != end(); ++it) - { - res.push_back((*it).name()); - } + res.push_back((*it).name()); } return res; } diff --git a/modules/core/test/test_io.cpp b/modules/core/test/test_io.cpp index c7473b9ded..0ee0534a7f 100644 --- a/modules/core/test/test_io.cpp +++ b/modules/core/test/test_io.cpp @@ -1597,6 +1597,12 @@ TEST(Core_InputOutput, FileStorage_json_bool) ASSERT_EQ((int)fs["map_value"]["bool_true"], 1); ASSERT_EQ((std::string)fs["map_value"]["str_false"], "false"); ASSERT_EQ((int)fs["bool_false"], 0); + + std::vector keys = fs["map_value"].keys(); + ASSERT_EQ((int)keys.size(), 3); + ASSERT_EQ(keys[0], "int_value"); + ASSERT_EQ(keys[1], "bool_true"); + ASSERT_EQ(keys[2], "str_false"); fs.release(); } From c54676d6259d036194b50fe5af31a0dc2d7c59d7 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Mon, 12 Nov 2018 14:09:57 +0300 Subject: [PATCH 4/5] cmake: fix supporting of legacy flags --- cmake/OpenCVCompilerOptimizations.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/OpenCVCompilerOptimizations.cmake b/cmake/OpenCVCompilerOptimizations.cmake index 4d6e0aa48d..7deb127e65 100644 --- a/cmake/OpenCVCompilerOptimizations.cmake +++ b/cmake/OpenCVCompilerOptimizations.cmake @@ -56,7 +56,7 @@ macro(ocv_optimization_process_obsolete_option legacy_flag OPT legacy_warn) message(STATUS " Behaviour of this option is not backward compatible") message(STATUS " Refer to 'CPU_BASELINE'/'CPU_DISPATCH' CMake options documentation") endif() - if("${legacy_flag}") + if("${${legacy_flag}}") if(NOT ";${CPU_BASELINE_REQUIRE};" MATCHES ";${OPT};") set(CPU_BASELINE_REQUIRE "${CPU_BASELINE_REQUIRE};${OPT}" CACHE STRING "${HELP_CPU_BASELINE_REQUIRE}" FORCE) endif() From 82c2aa6e6522ade3e20ba4763b4dc0b9febf198e Mon Sep 17 00:00:00 2001 From: Alexander Nesterov Date: Mon, 12 Nov 2018 11:55:22 -0100 Subject: [PATCH 5/5] Added bugfix and some tests --- .../objdetect/perf/perf_qrcode_pipeline.cpp | 27 +++++- modules/objdetect/src/qrcode.cpp | 92 +++++++++---------- 2 files changed, 66 insertions(+), 53 deletions(-) diff --git a/modules/objdetect/perf/perf_qrcode_pipeline.cpp b/modules/objdetect/perf/perf_qrcode_pipeline.cpp index e3a0bc68c6..da5f278c66 100644 --- a/modules/objdetect/perf/perf_qrcode_pipeline.cpp +++ b/modules/objdetect/perf/perf_qrcode_pipeline.cpp @@ -74,6 +74,17 @@ PERF_TEST_P_(Perf_Objdetect_Not_QRCode, detect) RNG rng; rng.fill(not_qr_code, RNG::UNIFORM, Scalar(0), Scalar(1)); } + if (type_gen == "chessboard") + { + uint8_t next_pixel = 0; + for (int r = 0; r < not_qr_code.rows * not_qr_code.cols; r++) + { + int i = r / not_qr_code.cols; + int j = r % not_qr_code.cols; + not_qr_code.ptr(i)[j] = next_pixel; + next_pixel = 255 - next_pixel; + } + } QRCodeDetector qrcode; TEST_CYCLE() ASSERT_FALSE(qrcode.detect(not_qr_code, corners)); @@ -96,6 +107,17 @@ PERF_TEST_P_(Perf_Objdetect_Not_QRCode, decode) RNG rng; rng.fill(not_qr_code, RNG::UNIFORM, Scalar(0), Scalar(1)); } + if (type_gen == "chessboard") + { + uint8_t next_pixel = 0; + for (int r = 0; r < not_qr_code.rows * not_qr_code.cols; r++) + { + int i = r / not_qr_code.cols; + int j = r % not_qr_code.cols; + not_qr_code.ptr(i)[j] = next_pixel; + next_pixel = 255 - next_pixel; + } + } QRCodeDetector qrcode; TEST_CYCLE() ASSERT_TRUE(qrcode.decode(not_qr_code, corners, straight_barcode).empty()); @@ -105,8 +127,9 @@ PERF_TEST_P_(Perf_Objdetect_Not_QRCode, decode) INSTANTIATE_TEST_CASE_P(/*nothing*/, Perf_Objdetect_Not_QRCode, ::testing::Combine( - ::testing::Values("zero", "random"), - ::testing::Values(Size(640, 480), Size(1280, 720), Size(1920, 1080)) + ::testing::Values("zero", "random", "chessboard"), + ::testing::Values(Size(640, 480), Size(1280, 720), + Size(1920, 1080), Size(3840, 2160)) )); } diff --git a/modules/objdetect/src/qrcode.cpp b/modules/objdetect/src/qrcode.cpp index 62bbefd16b..f18a3c3a06 100644 --- a/modules/objdetect/src/qrcode.cpp +++ b/modules/objdetect/src/qrcode.cpp @@ -48,6 +48,7 @@ protected: void QRDetect::init(const Mat& src, double eps_vertical_, double eps_horizontal_) { + CV_TRACE_FUNCTION(); CV_Assert(!src.empty()); const double min_side = std::min(src.size().width, src.size().height); if (min_side < 512.0) @@ -72,26 +73,26 @@ void QRDetect::init(const Mat& src, double eps_vertical_, double eps_horizontal_ vector QRDetect::searchHorizontalLines() { + CV_TRACE_FUNCTION(); vector result; const int height_bin_barcode = bin_barcode.rows; const int width_bin_barcode = bin_barcode.cols; const size_t test_lines_size = 5; double test_lines[test_lines_size]; - const size_t count_pixels_position = 1024; - size_t pixels_position[count_pixels_position]; - size_t index = 0; + vector pixels_position; for (int y = 0; y < height_bin_barcode; y++) { + pixels_position.clear(); const uint8_t *bin_barcode_row = bin_barcode.ptr(y); int pos = 0; for (; pos < width_bin_barcode; pos++) { if (bin_barcode_row[pos] == 0) break; } if (pos == width_bin_barcode) { continue; } - index = 0; - pixels_position[index] = pixels_position[index + 1] = pixels_position[index + 2] = pos; - index +=3; + pixels_position.push_back(pos); + pixels_position.push_back(pos); + pixels_position.push_back(pos); uint8_t future_pixel = 255; for (int x = pos; x < width_bin_barcode; x++) @@ -99,13 +100,11 @@ vector QRDetect::searchHorizontalLines() if (bin_barcode_row[x] == future_pixel) { future_pixel = 255 - future_pixel; - pixels_position[index] = x; - index++; + pixels_position.push_back(x); } } - pixels_position[index] = width_bin_barcode - 1; - index++; - for (size_t i = 2; i < index - 4; i+=2) + pixels_position.push_back(width_bin_barcode - 1); + for (size_t i = 2; i < pixels_position.size() - 4; i+=2) { test_lines[0] = static_cast(pixels_position[i - 1] - pixels_position[i - 2]); test_lines[1] = static_cast(pixels_position[i ] - pixels_position[i - 1]); @@ -120,8 +119,8 @@ vector QRDetect::searchHorizontalLines() if (length == 0) { continue; } for (size_t j = 0; j < test_lines_size; j++) { - if (j == 2) { weight += fabs((test_lines[j] / length) - 3.0/7.0); } - else { weight += fabs((test_lines[j] / length) - 1.0/7.0); } + if (j != 2) { weight += fabs((test_lines[j] / length) - 1.0/7.0); } + else { weight += fabs((test_lines[j] / length) - 3.0/7.0); } } if (weight < eps_vertical) @@ -139,6 +138,7 @@ vector QRDetect::searchHorizontalLines() vector QRDetect::separateVerticalLines(const vector &list_lines) { + CV_TRACE_FUNCTION(); vector result; int temp_length = 0; uint8_t next_pixel; @@ -157,7 +157,7 @@ vector QRDetect::separateVerticalLines(const vector &list_lines) for (int j = y; j < bin_barcode.rows - 1; j++) { - next_pixel = bin_barcode.at(j + 1, x); + next_pixel = bin_barcode.ptr(j + 1)[x]; temp_length++; if (next_pixel == future_pixel_up) { @@ -173,7 +173,7 @@ vector QRDetect::separateVerticalLines(const vector &list_lines) uint8_t future_pixel_down = 255; for (int j = y; j >= 1; j--) { - next_pixel = bin_barcode.at(j - 1, x); + next_pixel = bin_barcode.ptr(j - 1)[x]; temp_length++; if (next_pixel == future_pixel_down) { @@ -195,8 +195,8 @@ vector QRDetect::separateVerticalLines(const vector &list_lines) CV_Assert(length > 0); for (size_t i = 0; i < test_lines.size(); i++) { - if (i % 3 == 0) { weight += fabs((test_lines[i] / length) - 3.0/14.0); } - else { weight += fabs((test_lines[i] / length) - 1.0/ 7.0); } + if (i % 3 != 0) { weight += fabs((test_lines[i] / length) - 1.0/ 7.0); } + else { weight += fabs((test_lines[i] / length) - 3.0/14.0); } } if(weight < eps_horizontal) @@ -218,7 +218,7 @@ vector QRDetect::separateVerticalLines(const vector &list_lines) void QRDetect::fixationPoints(vector &local_point) { - + CV_TRACE_FUNCTION(); double cos_angles[3], norm_triangl[3]; norm_triangl[0] = norm(local_point[1] - local_point[2]); @@ -311,6 +311,7 @@ void QRDetect::fixationPoints(vector &local_point) bool QRDetect::localization() { + CV_TRACE_FUNCTION(); Point2f begin, end; vector list_lines_x = searchHorizontalLines(); if( list_lines_x.empty() ) { return false; } @@ -356,6 +357,7 @@ bool QRDetect::localization() bool QRDetect::computeTransformationPoints() { + CV_TRACE_FUNCTION(); if (localization_points.size() != 3) { return false; } vector locations, non_zero_elem[3], newHull; @@ -367,8 +369,7 @@ bool QRDetect::computeTransformationPoints() int count_test_lines = 0, index = cvRound(localization_points[i].x); for (; index < bin_barcode.cols - 1; index++) { - next_pixel = bin_barcode.at( - cvRound(localization_points[i].y), index + 1); + next_pixel = bin_barcode.ptr(cvRound(localization_points[i].y))[index + 1]; if (next_pixel == future_pixel) { future_pixel = 255 - future_pixel; @@ -495,6 +496,7 @@ Point2f QRDetect::intersectionLines(Point2f a1, Point2f a2, Point2f b1, Point2f // test function (if true then ------> else <------ ) bool QRDetect::testBypassRoute(vector hull, int start, int finish) { + CV_TRACE_FUNCTION(); int index_hull = start, next_index_hull, hull_size = (int)hull.size(); double test_length[2] = { 0.0, 0.0 }; do @@ -521,6 +523,7 @@ bool QRDetect::testBypassRoute(vector hull, int start, int finish) vector QRDetect::getQuadrilateral(vector angle_list) { + CV_TRACE_FUNCTION(); size_t angle_size = angle_list.size(); uint8_t value, mask_value; Mat mask = Mat::zeros(bin_barcode.rows + 2, bin_barcode.cols + 2, CV_8UC1); @@ -828,6 +831,7 @@ protected: void QRDecode::init(const Mat &src, const vector &points) { + CV_TRACE_FUNCTION(); original = src.clone(); intermediate = Mat::zeros(src.size(), CV_8UC1); original_points = points; @@ -839,6 +843,7 @@ void QRDecode::init(const Mat &src, const vector &points) bool QRDecode::updatePerspective() { + CV_TRACE_FUNCTION(); const Point2f centerPt = QRDetect::intersectionLines(original_points[0], original_points[2], original_points[1], original_points[3]); if (cvIsNaN(centerPt.x) || cvIsNaN(centerPt.y)) @@ -887,6 +892,7 @@ inline Point computeOffset(const vector& v) bool QRDecode::versionDefinition() { + CV_TRACE_FUNCTION(); LineIterator line_iter(intermediate, Point2f(0, 0), Point2f(test_perspective_size, test_perspective_size)); Point black_point = Point(0, 0); for(int j = 0; j < line_iter.count; j++, ++line_iter) @@ -949,6 +955,7 @@ bool QRDecode::versionDefinition() bool QRDecode::samplingForVersion() { + CV_TRACE_FUNCTION(); const double multiplyingFactor = (version < 3) ? 1 : (version == 3) ? 1.5 : version * (5 + version - 4); @@ -958,21 +965,20 @@ bool QRDecode::samplingForVersion() Mat postIntermediate(newFactorSize, CV_8UC1); resize(no_border_intermediate, postIntermediate, newFactorSize, 0, 0, INTER_AREA); - const int no_inter_rows = postIntermediate.rows; - const int no_inter_cols = postIntermediate.cols; - const int delta_rows = cvRound((no_inter_rows * 1.0) / version_size); - const int delta_cols = cvRound((no_inter_cols * 1.0) / version_size); + const int delta_rows = cvRound((postIntermediate.rows * 1.0) / version_size); + const int delta_cols = cvRound((postIntermediate.cols * 1.0) / version_size); - vector listFrequencyElem; - for (int r = 0; r < no_inter_rows; r += delta_rows) + vector listFrequencyElem(version_size * version_size, 0); + int k = 0; + for (int r = 0; r < postIntermediate.rows; r += delta_rows) { - for (int c = 0; c < no_inter_cols; c += delta_cols) + for (int c = 0; c < postIntermediate.cols; c += delta_cols) { Mat tile = postIntermediate( - Range(r, min(r + delta_rows, no_inter_rows)), - Range(c, min(c + delta_cols, no_inter_cols))); + Range(r, min(r + delta_rows, postIntermediate.rows)), + Range(c, min(c + delta_cols, postIntermediate.cols))); const double frequencyElem = (countNonZero(tile) * 1.0) / tile.total(); - listFrequencyElem.push_back(frequencyElem); + listFrequencyElem[k] = frequencyElem; k++; } } @@ -995,27 +1001,11 @@ bool QRDecode::samplingForVersion() } straight = Mat(Size(version_size, version_size), CV_8UC1, Scalar(0)); - size_t k = 0; - for (int r = 0; r < no_inter_rows && - k < listFrequencyElem.size() && - floor((r * 1.0) / delta_rows) < version_size; r += delta_rows) + for (int r = 0; r < version_size * version_size; r++) { - for (int c = 0; c < no_inter_cols && - k < listFrequencyElem.size() && - floor((c * 1.0) / delta_cols) < version_size; c += delta_cols, k++) - { - Mat tile = postIntermediate( - Range(r, min(r + delta_rows, no_inter_rows)), - Range(c, min(c + delta_cols, no_inter_cols))); - - if (listFrequencyElem[k] < experimentalFrequencyElem) { tile.setTo(0); } - else - { - tile.setTo(255); - straight.at(cvRound(floor((r * 1.0) / delta_rows)), - cvRound(floor((c * 1.0) / delta_cols))) = 255; - } - } + int i = r / straight.cols; + int j = r % straight.cols; + straight.ptr(i)[j] = (listFrequencyElem[r] < experimentalFrequencyElem) ? 0 : 255; } return true; } @@ -1035,7 +1025,7 @@ bool QRDecode::decodingProcess() { int position = y * qr_code.size + x; qr_code.cell_bitmap[position >> 3] - |= straight.at(y, x) ? 0 : (1 << (position & 7)); + |= straight.ptr(y)[x] ? 0 : (1 << (position & 7)); } }