无法在C++中使用OpenCV中的线段检测器

ttvkxqim  于 2022-11-15  发布在  其他
关注(0)|答案(1)|浏览(247)

我正在尝试使用OpenCV执行线检测,以便在卫星图像中选择植被行。
我决定使用OpenCV LineSegmentDetector,因为它似乎在单个代码行中提供了我所需要的内容,而不是使用Hough变换或其他需要一些额外工作和预处理的更复杂的方法。
然而,即使在最简单的例子中,我也无法使它工作。
我的代码:

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);

在第4行:

lsd->detect(coco, lines_std)

无论我尝试什么(OutputArray中的不同类型,使用cv::Mat作为输出,等等),我都会得到AccessViolationException或NullPointerException。代码几乎与下面的代码完全相同:https://docs.opencv.org/4.6.0/df/dfa/tutorial_line_descriptor_main.html(可能是旧版本,因为我没有定义“KeyLine”类型)
我知道由于许可问题,这个特性在以前的OpenCV版本中被删除了,这可以在官方文档中看到:
由于原始代码许可证冲突,OpenCV版本3.4.6到3.4.15和版本4.1.0到4.5.3中删除了实现。在MIT许可证下发布的NFA代码计算后再次恢复。
......但由于我使用的是OpenCV 4.6.0,我怀疑这不是问题所在。
我已经在Visual Studio 2022中为这个测试配置了一个新的项目,并且我熟悉通常的OpenCV操作(添加包含文件夹、链接器中的静态和动态库等)。
我错过了什么?

c3frrgcw

c3frrgcw1#

多亏了Micka的准确建议,我才能追踪到这个问题。看起来cv::Ptr是一个要求,标准的C++指针不起作用,即使在像这样一个相当简单的设置中。我不知道这一点。
我提供的固定代码只是为了以防万一,它可以帮助别人:

#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;
}

一些变量名称被更改为更容易解释的名称,此外,图像被调整大小,以保存测试之间的一些时间。
edit:使用LineSegmentDetector::drawSegments(...)绘制线条时出错,这是由于线条坐标上的小数点导致的。已通过使用cv::Vec4i(整数类型)而不是cv::Vec4d存储坐标修复此问题。此更改不再需要注解掉的循环。

相关问题