1

I am trying to perform line detection, using OpenCV, in order to select rows of vegetation in satellite imagery.

I decided to use OpenCV LineSegmentDetector since it seemed to provide just what I need in a single code line, as opposed to using Hough Transform or other more complex methods that require some additional work and preprocessing.

However, I am unable to make it work even in the simplest example.

My code:

Mat coco = imread("C:/Users/XX/Images/cococo.png", IMREAD_GRAYSCALE);
cv::LineSegmentDetector* lsd = cv::createLineSegmentDetector();
std::vector<cv::Vec4f> lines_std;
lsd->detect(coco, lines_std);
lsd->drawSegments(coco, lines_std);

in the 4th line:

lsd->detect(coco, lines_std)

I get either an AccessViolationException or a NullPointerException no matter what i try (different types in the OutputArray, using a cv::Mat as output, etc). The code is almost exactly the same as here: https://docs.opencv.org/4.6.0/df/dfa/tutorial_line_descriptor_main.html (probably with an older version since I do not have the "KeyLine" type defined)

I am aware this feature was removed in prior OpenCV versions due to licensing issues, as can be seen in the official docs:

Implementation has been removed from OpenCV version 3.4.6 to 3.4.15 and version 4.1.0 to 4.5.3 due original code license conflict. restored again after Computation of a NFA code published under the MIT license.

...but since I am using OpenCV 4.6.0 i suspect that is not the issue.

I have configured a fresh project in Visual Studio 2022 for this test, and I am familiar with the usual OpenCV things (add include folders, static and dynamic libs in linker, etc.). Other operations on Mats work just fine.

What am I missing?

Igb
  • 227
  • 2
  • 10
  • Provide a complete [mcve], the exact errors and where exactly they come from. | Since you're using MSVC -- are you sure you're not mixing runtimes? That is, are you linking debug version of OpenCV with your debug build, and release version with the release build? – Dan Mašek Oct 24 '22 at 12:57
  • 1
    Try cv::Ptr see https://stackoverflow.com/a/45481619/2393191 . – Micka Oct 24 '22 at 14:10
  • Please test whether coco is a successfully loaded image. – Micka Oct 24 '22 at 14:12

1 Answers1

2

Thanks to Micka accurate suggestion, I was able to trace the problem. Seems that cv::Ptr was a requirement and standard C++ pointers do not work, even in a fairly simple setup like this one. I was not aware of that.

I am providing the fixed code just in case it can be helpful to someone:

#include "stdafx.h"
#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

int main() {
    Mat img = imread("C:/Users/XX/Images/test.png", IMREAD_GRAYSCALE);
    Mat resizedimg, resizedimgRGB;
    resize(img, resizedimg, cv::Size(img.rows/16, img.cols/16));
    cv::cvtColor(resizedimg, resizedimgRGB, COLOR_GRAY2BGR);

    cv::Ptr<cv::LineSegmentDetector> lsd = cv::createLineSegmentDetector(0);
    std::vector<cv::Vec4i> lines_std;
    lsd->detect(resizedimg, lines_std);
    lsd->drawSegments(resizedimgRGB, lines_std); // For some reason this does not work when lines_std coordinates are stored as doubles
    
    /*
    for (cv::Vec4d lin : lines_std) {
        cv::line(resizedimgRGB, cv::Point(lin[0], lin[1]), cv::Point(lin[2], lin[3]), Scalar(255, 0, 0), 1);
    }
    */

    imshow("IMAGE", resizedimgRGB);
    waitKey(0);

    return 0;
}

Some variable names were changed to a bit more self-explanatory ones, also, the image was resized in order to save some time between tests.

edit: There was an error when drawing the lines using LineSegmentDetector::drawSegments(...), caused by decimals on the line coordinates. It was fixed by using cv::Vec4i (integer type) instead of cv::Vec4d to store the coordinates. The commented-out loop is no longer needed with this change.

Igb
  • 227
  • 2
  • 10
  • You didn’t get a compiler error (or even warning) when you assigned the return value to a variable of the wrong type? – Cris Luengo Oct 25 '22 at 14:04
  • No, it seems to use C++ pointers (smart pointers maybe?) under the hood, so it does not complain at compile time. On runtime it does fail though. It seems weird to me that it even fails with two different error codes (AccessViolation and NullPointer) – Igb Oct 25 '22 at 22:52
  • 1
    My guess: the shared pointer returned by the function, because it’s not preserved, is destructed. This frees the object pointed to. – Cris Luengo Oct 26 '22 at 01:04
  • Yes, should be shared pointers – Micka Oct 26 '22 at 05:01