From e17293565816f0901ab7a33325758886a97294bc Mon Sep 17 00:00:00 2001 From: shimat Date: Mon, 9 Apr 2018 23:31:56 +0900 Subject: [PATCH] LSD: support vector lines (#11042) * add LSD supportsVec4iResult * LineSegmentDetector.drawSegments: support vector * test_lsd.cpp: replace detect() * test_lsd.cpp: add compareSegments tests * lsd.cpp: LSD.compareSegments support Vec4i * test_lsd.cpp: fix trailing whitespace --- modules/imgproc/src/lsd.cpp | 56 ++++++++---- modules/imgproc/test/test_lsd.cpp | 138 ++++++++++++++++++++++++++++++ 2 files changed, 176 insertions(+), 18 deletions(-) diff --git a/modules/imgproc/src/lsd.cpp b/modules/imgproc/src/lsd.cpp index a17a8f2f20..d73787407e 100644 --- a/modules/imgproc/src/lsd.cpp +++ b/modules/imgproc/src/lsd.cpp @@ -1130,17 +1130,31 @@ void LineSegmentDetectorImpl::drawSegments(InputOutputArray _image, InputArray l cvtColor(_image, _image, COLOR_GRAY2BGR); } - Mat _lines; - _lines = lines.getMat(); - int N = _lines.checkVector(4); + Mat _lines = lines.getMat(); + const int N = _lines.checkVector(4); + + CV_Assert(_lines.depth() == CV_32F || _lines.depth() == CV_32S); // Draw segments - for(int i = 0; i < N; ++i) + if (_lines.depth() == CV_32F) { - const Vec4f& v = _lines.at(i); - Point2f b(v[0], v[1]); - Point2f e(v[2], v[3]); - line(_image, b, e, Scalar(0, 0, 255), 1); + for (int i = 0; i < N; ++i) + { + const Vec4f& v = _lines.at(i); + const Point2f b(v[0], v[1]); + const Point2f e(v[2], v[3]); + line(_image, b, e, Scalar(0, 0, 255), 1); + } + } + else + { + for (int i = 0; i < N; ++i) + { + const Vec4i& v = _lines.at(i); + const Point2i b(v[0], v[1]); + const Point2i e(v[2], v[3]); + line(_image, b, e, Scalar(0, 0, 255), 1); + } } } @@ -1156,24 +1170,30 @@ int LineSegmentDetectorImpl::compareSegments(const Size& size, InputArray lines1 Mat_ I1 = Mat_::zeros(sz); Mat_ I2 = Mat_::zeros(sz); - Mat _lines1; - Mat _lines2; - _lines1 = lines1.getMat(); - _lines2 = lines2.getMat(); - int N1 = _lines1.checkVector(4); - int N2 = _lines2.checkVector(4); + Mat _lines1 = lines1.getMat(); + Mat _lines2 = lines2.getMat(); + const int N1 = _lines1.checkVector(4); + const int N2 = _lines2.checkVector(4); + + CV_Assert(_lines1.depth() == CV_32F || _lines1.depth() == CV_32S); + CV_Assert(_lines2.depth() == CV_32F || _lines2.depth() == CV_32S); + + if (_lines1.depth() == CV_32S) + _lines1.convertTo(_lines1, CV_32F); + if (_lines2.depth() == CV_32S) + _lines2.convertTo(_lines2, CV_32F); // Draw segments for(int i = 0; i < N1; ++i) { - Point2f b(_lines1.at(i)[0], _lines1.at(i)[1]); - Point2f e(_lines1.at(i)[2], _lines1.at(i)[3]); + const Point2f b(_lines1.at(i)[0], _lines1.at(i)[1]); + const Point2f e(_lines1.at(i)[2], _lines1.at(i)[3]); line(I1, b, e, Scalar::all(255), 1); } for(int i = 0; i < N2; ++i) { - Point2f b(_lines2.at(i)[0], _lines2.at(i)[1]); - Point2f e(_lines2.at(i)[2], _lines2.at(i)[3]); + const Point2f b(_lines2.at(i)[0], _lines2.at(i)[1]); + const Point2f e(_lines2.at(i)[2], _lines2.at(i)[3]); line(I2, b, e, Scalar::all(255), 1); } diff --git a/modules/imgproc/test/test_lsd.cpp b/modules/imgproc/test/test_lsd.cpp index 5bc2c10066..835d88f901 100644 --- a/modules/imgproc/test/test_lsd.cpp +++ b/modules/imgproc/test/test_lsd.cpp @@ -51,6 +51,14 @@ protected: }; +class Imgproc_LSD_Common : public LSDBase +{ +public: + Imgproc_LSD_Common() { } +protected: + +}; + void LSDBase::GenerateWhiteNoise(Mat& image) { image = Mat(img_size, CV_8UC1); @@ -264,4 +272,134 @@ TEST_F(Imgproc_LSD_NONE, rotatedRect) ASSERT_EQ(EPOCHS, passedtests); } +TEST_F(Imgproc_LSD_Common, supportsVec4iResult) +{ + for (int i = 0; i < EPOCHS; ++i) + { + GenerateWhiteNoise(test_image); + Ptr detector = createLineSegmentDetector(LSD_REFINE_STD); + detector->detect(test_image, lines); + + std::vector linesVec4i; + detector->detect(test_image, linesVec4i); + + if (lines.size() == linesVec4i.size()) + { + bool pass = true; + for (size_t lineIndex = 0; pass && lineIndex < lines.size(); lineIndex++) + { + for (int ch = 0; ch < 4; ch++) + { + if (cv::saturate_cast(lines[lineIndex][ch]) != linesVec4i[lineIndex][ch]) + { + pass = false; + break; + } + } + } + if (pass) + ++passedtests; + } + } + ASSERT_EQ(EPOCHS, passedtests); +} + +TEST_F(Imgproc_LSD_Common, drawSegmentsVec4f) +{ + GenerateConstColor(test_image); + + std::vector linesVec4f; + RNG cr(0); // constant seed for deterministic test + for (int j = 0; j < 10; j++) { + linesVec4f.push_back( + Vec4f(float(cr) * test_image.cols, float(cr) * test_image.rows, float(cr) * test_image.cols, float(cr) * test_image.rows)); + } + + Mat actual = Mat::zeros(test_image.size(), CV_8UC3); + Mat expected = Mat::zeros(test_image.size(), CV_8UC3); + + Ptr detector = createLineSegmentDetector(LSD_REFINE_STD); + detector->drawSegments(actual, linesVec4f); + + // something should be drawn + ASSERT_EQ(sum(actual == expected) != Scalar::all(0), true); + + for (size_t lineIndex = 0; lineIndex < linesVec4f.size(); lineIndex++) + { + const Vec4f &v = linesVec4f[lineIndex]; + const Point2f b(v[0], v[1]); + const Point2f e(v[2], v[3]); + line(expected, b, e, Scalar(0, 0, 255), 1); + } + + ASSERT_EQ(sum(actual != expected) == Scalar::all(0), true); +} + +TEST_F(Imgproc_LSD_Common, drawSegmentsVec4i) +{ + GenerateConstColor(test_image); + + std::vector linesVec4i; + RNG cr(0); // constant seed for deterministic test + for (int j = 0; j < 10; j++) { + linesVec4i.push_back( + Vec4i(cr(test_image.cols), cr(test_image.rows), cr(test_image.cols), cr(test_image.rows))); + } + + Mat actual = Mat::zeros(test_image.size(), CV_8UC3); + Mat expected = Mat::zeros(test_image.size(), CV_8UC3); + + Ptr detector = createLineSegmentDetector(LSD_REFINE_STD); + detector->drawSegments(actual, linesVec4i); + + // something should be drawn + ASSERT_EQ(sum(actual == expected) != Scalar::all(0), true); + + for (size_t lineIndex = 0; lineIndex < linesVec4i.size(); lineIndex++) + { + const Vec4f &v = linesVec4i[lineIndex]; + const Point2f b(v[0], v[1]); + const Point2f e(v[2], v[3]); + line(expected, b, e, Scalar(0, 0, 255), 1); + } + + ASSERT_EQ(sum(actual != expected) == Scalar::all(0), true); +} + +TEST_F(Imgproc_LSD_Common, compareSegmentsVec4f) +{ + GenerateConstColor(test_image); + Ptr detector = createLineSegmentDetector(LSD_REFINE_STD); + + std::vector lines1, lines2; + lines1.push_back(Vec4f(0, 0, 100, 200)); + lines2.push_back(Vec4f(0, 0, 100, 200)); + int result1 = detector->compareSegments(test_image.size(), lines1, lines2); + + ASSERT_EQ(result1, 0); + + lines2.push_back(Vec4f(100, 100, 110, 100)); + int result2 = detector->compareSegments(test_image.size(), lines1, lines2); + + ASSERT_EQ(result2, 11); +} + +TEST_F(Imgproc_LSD_Common, compareSegmentsVec4i) +{ + GenerateConstColor(test_image); + Ptr detector = createLineSegmentDetector(LSD_REFINE_STD); + + std::vector lines1, lines2; + lines1.push_back(Vec4i(0, 0, 100, 200)); + lines2.push_back(Vec4i(0, 0, 100, 200)); + int result1 = detector->compareSegments(test_image.size(), lines1, lines2); + + ASSERT_EQ(result1, 0); + + lines2.push_back(Vec4i(100, 100, 110, 100)); + int result2 = detector->compareSegments(test_image.size(), lines1, lines2); + + ASSERT_EQ(result2, 11); +} + }} // namespace