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?
CodePudding user response:
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.