LSD: support vector<Vec4i> lines (#11042)
authorshimat <schimatk@gmail.com>
Mon, 9 Apr 2018 14:31:56 +0000 (23:31 +0900)
committerVadim Pisarevsky <vadim.pisarevsky@gmail.com>
Mon, 9 Apr 2018 14:31:56 +0000 (17:31 +0300)
* add LSD supportsVec4iResult

* LineSegmentDetector.drawSegments: support vector<Vec4i>

* 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
modules/imgproc/test/test_lsd.cpp

index a17a8f2f2093783d39dcaea7adcd4bdbd57a284d..d73787407ea9b13bcf5b86fe4c0f319475dfc073 100644 (file)
@@ -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)
+    {
+        for (int i = 0; i < N; ++i)
+        {
+            const Vec4f& v = _lines.at<Vec4f>(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
     {
-        const Vec4f& v = _lines.at<Vec4f>(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 Vec4i& v = _lines.at<Vec4i>(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_<uchar> I1 = Mat_<uchar>::zeros(sz);
     Mat_<uchar> I2 = Mat_<uchar>::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<Vec4f>(i)[0], _lines1.at<Vec4f>(i)[1]);
-        Point2f e(_lines1.at<Vec4f>(i)[2], _lines1.at<Vec4f>(i)[3]);
+        const Point2f b(_lines1.at<Vec4f>(i)[0], _lines1.at<Vec4f>(i)[1]);
+        const Point2f e(_lines1.at<Vec4f>(i)[2], _lines1.at<Vec4f>(i)[3]);
         line(I1, b, e, Scalar::all(255), 1);
     }
     for(int i = 0; i < N2; ++i)
     {
-        Point2f b(_lines2.at<Vec4f>(i)[0], _lines2.at<Vec4f>(i)[1]);
-        Point2f e(_lines2.at<Vec4f>(i)[2], _lines2.at<Vec4f>(i)[3]);
+        const Point2f b(_lines2.at<Vec4f>(i)[0], _lines2.at<Vec4f>(i)[1]);
+        const Point2f e(_lines2.at<Vec4f>(i)[2], _lines2.at<Vec4f>(i)[3]);
         line(I2, b, e, Scalar::all(255), 1);
     }
 
index 5bc2c10066847faa0984dc4380fa311079c32868..835d88f9019077c963f7b40eab834555e81ad65e 100644 (file)
@@ -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<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
+        detector->detect(test_image, lines);
+
+        std::vector<Vec4i> 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<int>(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<Vec4f> 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<LineSegmentDetector> 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<Vec4i> 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<LineSegmentDetector> 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<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
+
+    std::vector<Vec4f> 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<LineSegmentDetector> detector = createLineSegmentDetector(LSD_REFINE_STD);
+
+    std::vector<Vec4i> 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