LSD线特征提取方法+Opencv实现C++

本文介绍了一种基于梯度信息的直线检测方法LSD,并详细解释了如何在OpenCV环境中使用此算法,包括如何更改其高级参数以提高检测精度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

边缘检测: 传统的直线检测方法一般采用边缘检测算法提取二值边缘图像,然后利用Hough变换将表示每条直线属性的参数投影到Hough空间中。该线检测方法是一种全局拟合算法。缺点是依赖于边缘检测算法的准确性,在边缘密集的地方容易出现异常检测
LSD检测 LSD算法是一种基于梯度信息的直线检测方法,具有检测速度快、参数自适应、精度可达到亚像素级的特点。其主要思想是将局部区域内具有相同梯度方向的像素进行合并,以达到直线检测的目的

下面有用到自己更改LBD的高级参数:

line_descriptor::LSDDetector::LSDOptions opts;
但是编译报错:
error: ‘LSDOptions’ is not a member of ‘cv::line_descriptor::LSDDetector’
经查找:这个错误通常是由于版本不兼容引起的。可能是你正在使用的OpenCV版本与你的代码中使用的OpenCV版本不同导致的。

在OpenCV 4.0版本及更高版本中,LSDDetector类的构造函数中没有LSDOptions参数。相反,它被重构为BinaryDescriptor::Params参数。因此,如果你的OpenCV版本高于4.0,那么在构造LSDDetector对象时,应该使用BinaryDescriptor::Params参数,而不是LSDOptions参数。

以下是在OpenCV 4.0版本及更高版本中使用BinaryDescriptor::Params参数的示例代码:


#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
    // 读取图像
    Mat img = imread("image.jpg");

    // 创建BinaryDescriptor对象
    Ptr<BinaryDescriptor> bd = BinaryDescriptor::createBinaryDescriptor();

    // 设置计算参数
    BinaryDescriptor::Params params;
    params.numOfOctaves = 3;
    params.numOfLevels = 4;
    params.widthOfBand = 7;
    params.extractSIFT = true;

    // 初始化BinaryDescriptor对象
    bd->init(params);

    // 计算二进制描述子
    vector<KeyPoint> keypoints;
    Mat descriptors;
    bd->compute(img, keypoints, descriptors);

    // 输出计算结果
    cout << "Number of keypoints: " << keypoints.size() << endl;
    cout << "Descriptor size: " << descriptors.cols << endl;

    return 0;
}
/*在这个示例中,我们首先读取了一个图像,然后创建了一个BinaryDescriptor对象bd。
接着,我们定义了一个BinaryDescriptor::Params对象params,并设置了三个计算参数:
numOfOctaves、numOfLevels和widthOfBand。这些参数可以影响二进制描述子的计算效果。
最后,我们使用bd->compute()函数计算了二进制描述子,并输出了计算结果。
在这个示例中,我们计算了SIFT特征点的二进制描述子。你可以根据自己的需求来设置
BinaryDescriptor::Params对象的计算参数。*/



原文链接地址:https://zhuanlan.zhihu.com/p/54126417


#include <chrono>
#include <cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/core/utility.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/line_descriptor/descriptor.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <iostream>
#include <sstream>
#include <sys/time.h>
#include <unistd.h>
#include<math.h>

using namespace cv;
using namespace std;
using namespace cv::line_descriptor;
struct sort_descriptor_by_queryIdx
{
    inline bool operator()(const vector<DMatch> &a, const vector<DMatch> &b)
    {
        return (a[0].queryIdx < b[0].queryIdx);
    }
};
struct sort_lines_by_response
{
    inline bool operator()(const KeyLine &a, const KeyLine &b)
    {
        return (a.response > b.response);
    }
};
void ExtractLineSegment(const Mat &img, const Mat &image2, vector<KeyLine> &keylines, vector<KeyLine> &keylines2);

// #define  FILTER_LINES  //用来验证线段长度的筛选效果

int main(int argc, char **argv)
{
    if (argc != 3)
    {
        cerr << endl
             << "Usage: ./Line path_to_image1 path_to_image2" << endl;
        return 1;
    }
    std::string window_name("LSD Detect");

    string imagePath1 = string(argv[1]);
    string imagePath2 = string(argv[2]);
    cout << "import two images" << endl;
    Mat image1 = imread(imagePath1);
    Mat image2 = imread(imagePath2);

    imshow("ima1", image1);
    imshow("ima2", image2);
    waitKey(0);
    if (image1.data == NULL)
    {
        cout << "the path is wrong" << endl;
    }

    vector<KeyLine> keylines, keylines2;

    ExtractLineSegment(image1, image2, keylines, keylines2);

    return 0;
}
void ExtractLineSegment(const Mat &img, const Mat &image2, vector<KeyLine> &keylines, vector<KeyLine> &keylines2)
{
    Mat mLdesc, mLdesc2;
    vector<vector<DMatch>> lmatches;
    Ptr<BinaryDescriptor> lbd = BinaryDescriptor::createBinaryDescriptor();

    //         // 创建LSDDetector对象,并且可以更改默认参数
    // line_descriptor::LSDDetector::LSDOptions opts;
    // opts.refine       = line_descriptor::LSD_REFINE_STD;  // 设置线段精化模式
    // opts.scale        = 1.2;                              // 设置线检测的尺度因子
    // opts.sigma_scale  = 0.6;                              // 设置线检测的高斯核参数
    // opts.quant        = 2.0;                              // 设置线检测的图像离散程度
    // opts.ang_th       = 22.5;                             // 设置线检测的最小角度
    // opts.log_eps      = 0;                                // 设置线检测的对数响应阈值
    // opts.density_th   = 0.7;                              // 设置线检测的密度阈值
    // opts.n_bins       = 1024;                             // 设置线检测的直方图bin数
    // opts.min_length   = 0;                                // 设置线检测的最小线段长度
    // opts.max_line_gap = -1;                               // 设置线检测的最大线段间隔
    // Ptr<line_descriptor::LSDDetector> lsd = line_descriptor::LSDDetector::createLSDDetector( opts );

    Ptr<line_descriptor::LSDDetector> lsd = line_descriptor::LSDDetector::createLSDDetector();

    struct timeval time1, time2, time3;
    //记录两个时间差
    unsigned long diff1, diff2;

    cout << "extract lsd line segments" << endl;
    //获取开始前的瞬间时间
    gettimeofday(&time1, NULL);
    lsd->detect(img, keylines, 1.2, 1); //后面俩个参数是scale (– scale factor used in pyramids generation)
                                        // numOctaves (– number of octaves inside pyramid)

    gettimeofday(&time2, NULL);
    lsd->detect(image2, keylines2, 1.2, 1);
    gettimeofday(&time3, NULL);
    //计算开始和结束时间差
    diff1 = (time2.tv_sec - time1.tv_sec) + (time2.tv_usec - time1.tv_usec) / 1000000.0;
    diff2 = (time3.tv_sec - time2.tv_sec) + (time3.tv_usec - time2.tv_usec) / 1000000.0;

    cout << " LSDDetector在图片1 中得到的线段数量" << keylines.size() << " ,,耗时为==" << diff1 << endl;
    cout << " LSDDetector 在图片2中得到的线段数量" << keylines2.size() << " ,,耗时为==" << diff2 << endl;

    double x1, y1, x2, y2;
    double m, c, theta, len;
    ostringstream os1, os2, os3;
    string str1;

     // 记得重复使用同一个stringstream对象(kp_depth_str)时要先继续清空对象里的内容,要不然会一直添加到kp_depth_str末尾(印象中是),不会像int那样简单的覆盖之前的内容
    double x1, y1, x2, y2;
    double m, c, theta, theta_standard,len,len_standard;

    string str1;
 Point2f standard_mid_pt;
     // 记得重复使用同一个 ostringstream 对象(os1)时要先继续清空对象里的内容,要不然会一直添加到 os1 末尾,不会像int那样简单的覆盖之前的内容
    ostringstream os1, os2, os3;    
    	double text_size_ratio = 0.5;  //  text_size_ratio = font_scale  尺寸因子,可以小于1,值越大文字越大
        int thickness = 1; // 线条宽度
        int lineType = 2; // 线型(4邻域或8邻域,默认8邻域)
    int itor = 0;
    for (auto &kp : keylines)
    {
        x1 = kp.startPointX, y1 = kp.startPointY;
        x2 = kp.endPointX, y2 = kp.endPointX;
        cv::Point2d pt1(kp.startPointX, kp.startPointY);
        cv::Point2d pt2(kp.endPointX, kp.endPointY);
    // cout<< "第"<<itor<<"线段的x1=="<<x1<<",,y1=="<<y1<<endl;
    //     cout<< "第"<<itor<<"线段的x2=="<<x2<<",,y1=="<<y2<<endl;


        // Calculating equation of the line : y = mx + c
        if (x1 != x2)
            m = (double)(y2 - y1) / (double)(x2 - x1);
        else
            m = 100000000.0;
        c = y2 - m * x2;
                // cout<< "第"<<itor<<"线段的斜率m=="<<m<<",,theta="<< theta<<endl;

        // theta will contain values between - 90 -> + 90.
        theta = atan(m) * (180.0 / M_PI);
theta_standard =  kp.angle; 
        len_standard= kp.lineLength;
        standard_mid_pt =  kp.pt ;
        len = pow((pow((y2 - y1), 2) + pow((x2 - x1), 2)), 0.5); // length of the line
        len = round(len * pow(10, 3)) * pow(10, -3);//3位小数,函数round():四舍五入到最接近的整数值
            // cout<< "第"<<itor<<"线段的长度为len=="<<len<<endl;
                cv::circle(image1, cv::Point((x1 + x2) / 2, (y2 + y1) / 2)  , (int)(5), cv::Scalar(250,0,250),2, 8, 0);

        os1 << len;
        str1 = os1.str();

                putText(image1, str1,  cv::Point((x1 + x2) / 2, (y2 + y1) / 2) , cv::FONT_HERSHEY_COMPLEX, text_size_ratio, cv::Scalar(100, 0, 0), thickness, lineType);   
        os1.str("");//清空对象  os1 里的内容
    // cout<< "第"<<itor<<"线段的长度为str1=="<<str1<<endl;

    itor++;
    }


    // 	因此,在我们的方法中,我们将从之后获得的所有行中只选取最长的15行
    // 在上一步中对它们进行过滤(只有当行数多于15时,否则小于15排队,我们会把他们都带走)。数字“15”只是一个我认为正确的参数
    // 我们的计算消失点,但你可以改变它根据你的愿望。为了获得最长的行,我们首先使用
    // sort函数,然后我们分割出前15行(最长的15行)。
    // if (FinalLines.size() > 15)
    // {
    // 	std::sort(FinalLines.begin(), FinalLines.end(),
    // 			  [](const std::vector< double >& a,
    // 				 const std::vector< double >& b)
    // 				{ return a[6] > b[6]; });
    //   FilteredLines = std::vector<std::vector<double>>(FinalLines.begin(), FinalLines.begin() + 15);
    // }

    // 绘制直线,用紫色绘制
    cv::Mat pre_image_output = img.clone();
    cv::line_descriptor::drawKeylines(img, keylines, pre_image_output, cv::Scalar(255, 0, 255));
    // 绘制直线,用green 色绘制
    cv::Mat pre_image_output2 = image2.clone();
    cv::line_descriptor::drawKeylines(image2, keylines2, pre_image_output2, cv::Scalar(255, 255, 0));

    cv::imshow("pre_keylines", pre_image_output);
    cv::imshow("pre_keylines2", pre_image_output2);
    cv::waitKey(0);
    int lsdNFeatures = 50;
    cout << "filter lines" << endl;
    if (keylines.size() > lsdNFeatures)
    {
        sort(keylines.begin(), keylines.end(), sort_lines_by_response());
        keylines.resize(lsdNFeatures);
        for (int i = 0; i < lsdNFeatures; i++)
            keylines[i].class_id = i;
    }
    if (keylines2.size() > lsdNFeatures)
    {
        sort(keylines2.begin(), keylines2.end(), sort_lines_by_response());
        keylines2.resize(lsdNFeatures);
        for (int i = 0; i < lsdNFeatures; i++)
            keylines2[i].class_id = i;
    }

   
    // 绘制直线,用蓝色绘制
    cv::Mat image_output = img.clone();
    cv::line_descriptor::drawKeylines(img, keylines, image_output, cv::Scalar(255, 0, 0));
    // 绘制直线,用green 色绘制
    cv::Mat image_output2 = image2.clone();
    cv::line_descriptor::drawKeylines(image2, keylines2, image_output2, cv::Scalar(0, 255, 0));
    cv::imshow("keylines", image_output);
    cv::imshow("keylines2", image_output2);
    cv::waitKey(0);

    cout << "lbd describle" << endl;
    lbd->compute(img, keylines, mLdesc);
    lbd->compute(image2, keylines2, mLdesc2); //计算特征线段的描述子
    BFMatcher *bfm = new BFMatcher(NORM_HAMMING, false);
    bfm->knnMatch(mLdesc, mLdesc2, lmatches, 2);
    vector<DMatch> matches;
    for (size_t i = 0; i < lmatches.size(); i++)
    {
        const DMatch &bestMatch = lmatches[i][0];
        const DMatch &betterMatch = lmatches[i][1];
        float distanceRatio = bestMatch.distance / betterMatch.distance;
        if (distanceRatio < 0.75)
            matches.push_back(bestMatch);
    }

    cv::Mat outImg;
    std::vector<char> mask(lmatches.size(), 1);
    drawLineMatches(img, keylines, image2, keylines2, matches, outImg, Scalar::all(-1), Scalar::all(-1), mask,
                    DrawLinesMatchesFlags::DEFAULT);

    imshow("Matches", outImg);
    waitKey();
}

针对自己的Cmakelists.txt文件 的执行命令:./bin/HC++ /home/jyy/图片/test1.png /home/jyy/图片/test1.png

PROJECT(HC++)
cmake_minimum_required(VERSION 3.5)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${HC++_SOURCE_DIR}/bin) #可执行文件的输出位置

# find required opencv
find_package(OpenCV REQUIRED)
# directory of opencv headers
link_directories(${OpenCV_LIBRARY_DIRS}) 
# opencv libr
include_directories(${OpenCV_INCLUDE_DIRS})

add_executable(${PROJECT_NAME} "./baselineExperiment.cpp" )      
# directory of opencv libraryaries
target_link_libraries(HC++ ${OpenCV_LIBS} -lpthread -lm)
 

在这里插入图片描述

在这里插入图片描述




附上一个使用互动条动态调整线段长度的函数

#include <opencv2/opencv.hpp>
using namespace cv;

// 回调函数
void onChange(int pos, void* userdata)
{
    Mat img = *(Mat*)userdata;

    // 使用LSD算法提取线段
    Mat gray;
    cvtColor(img, gray, COLOR_BGR2GRAY);
    Ptr<LineSegmentDetector> lsd = createLineSegmentDetector(0);
    std::vector<Vec4f> lines;
    lsd->detect(gray, lines);

    // 根据滑动条位置调整线段长度
    float maxLength = pos / 10.0f;
    for (Vec4f line : lines) {
        float length = norm(Point2f(line[0], line[1]) - Point2f(line[2], line[3]));
        if (length > maxLength) {
            float dx = line[2] - line[0];
            float dy = line[3] - line[1];
            float scale = maxLength / length;
            dx *= scale;
            dy *= scale;
            line[2] = line[0] + dx;
            line[3] = line[1] + dy;
        }
    }

    // 绘制线段并显示图像
    Mat drawImg;
    cvtColor(gray, drawImg, COLOR_GRAY2BGR);
    lsd->drawSegments(drawImg, lines);
    imshow("Image", drawImg);
}

int main()
{
    Mat img = imread("image.jpg");

    // 创建窗口并显示图像
    namedWindow("Image");
    imshow("Image", img);

    // 创建滑动条并注册回调函数
    int maxLength = 100;
    createTrackbar("Max Length", "Image", &maxLength, 1000, onChange, &img);

    waitKey(0);
    return 0;
}


下面有用到自己更改LSD的高级参数(来源于chatgpt的方法):(但是在line_descriptor.hpp中并没有找到这俩个成员函数,难不成这东西也骗人??)

在OpenCV 4.0版本中,LSDOptions类已经从line_descriptor命名空间中移除,并被放置在line_descriptor::OptimizePose类中。因此,如果你在使用line_descriptor库时出现了“error: ‘LSDOptions’ is not a member of ‘cv::line_descriptor’”的错误,可能是因为你使用了过时的LSDOptions类。

为了解决这个问题,你可以使用line_descriptor::OptimizePose类来设置LSD算法的参数。请注意,在使用line_descriptor::OptimizePose类时,你需要包含<opencv2/line_descriptor.hpp>头文件。下面是一个示例代码,展示如何使用line_descriptor::OptimizePose来计算图像中的直线特征:

#include <opencv2/opencv.hpp>
#include <opencv2/line_descriptor.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
    // 读取图像
    Mat img = imread("image.jpg");

    // 创建LSDDetector对象
    Ptr<line_descriptor::LSDDetector> lsd = line_descriptor::LSDDetector::create();
///**********************参数设置一:报错***********************
            // 创建LSDDetector对象,并且可以更改默认参数
    // line_descriptor::LSDDetector::LSDOptions  opts; 
    // line_descriptor::LSDOptions  opts; 
    // opts.refine       = line_descriptor::LSD_REFINE_STD;  // 设置线段精化模式
    // opts.scale        = 1.2;                              // 设置线检测的尺度因子
    // opts.sigma_scale  = 0.6;                              // 设置线检测的高斯核参数
    // opts.quant        = 2.0;                              // 设置线检测的图像离散程度
    // opts.ang_th       = 22.5;                             // 设置线检测的最小角度
    // opts.log_eps      = 0;                                // 设置线检测的对数响应阈值
    // opts.density_th   = 0.7;                              // 设置线检测的密度阈值
    // opts.n_bins       = 1024;                             // 设置线检测的直方图bin数
    // opts.min_length   = 0;                                // 设置线检测的最小线段长度
    // opts.max_line_gap = -1;                               // 设置线检测的最大线段间隔
        // Ptr<line_descriptor::LSDDetector> lsd = line_descriptor::LSDDetector::createLSDDetector(opt );

///***********************************************************************************

    Ptr<line_descriptor::LSDDetector> lsd = line_descriptor::LSDDetector::createLSDDetector();
//***************参数设置二
// // 创建OptimizePose对象
//    cv::line_descriptor::OptimizePose pose;

//     // 设置计算参数
//     pose.setLSDDetector(lsd);
//     pose.setLineLengthThresh(40);
//     pose.setMinLineLength(10);
//     pose.setNumOfOctave(1);
//     pose.setRatioThreshold(0.9f);
//     pose.setScale(1.2f);

//******************************

    // 计算直线特征
    vector<line_descriptor::KeyLine> keylines;
    lsd->detect(img, keylines);

    // 输出计算结果
    cout << "Number of keylines: " << keylines.size() << endl;

    return 0;
}

<think>好的,我现在需要帮助用户在Ubuntu系统上实现LSD线特征提取算法。根据用户提供的引用内容,我需要先整理现有的信息,并找到合适的方法。 首先,用户提到的引用[2]和引用[3]指出,OpenCV的新版本(如4.4.0)移除了LSD算法,但可以通过移植旧版本的代码或使用第三方库来实现。用户还提到在OpenCV 3.1中可以找到LSD实现,所以可能需要从那里提取代码。 另外,引用[4]和引用[5]提到LSD在实时性上的问题,但用户主要关注的是如何在Ubuntu上实现,所以性能优化可能不是当前重点,但可能需要考虑如何提升效率。 接下来,我需要考虑几种可能的实现方法: 1. **使用OpenCV 3.x版本的LSD模块**:用户提到引用[2]中的第二种方法,即从OpenCV 3.1提取lsd.cpp和precomp.hpp文件,并将其添加到项目中。这可能是一个直接的方法,但需要处理可能的依赖和头文件问题。 2. **第三方库或源码**:比如LSD作者的原生实现,可能需要编译或集成到项目中。引用[2]中提到需要从GitHub获取作者源码,但可能需要更多步骤。 3. **使用MATLAB调用OpenCV**:但用户需求是在Ubuntu上实现,可能更倾向于C++或Python环境,所以这个方法可能不太适用。 另外,用户询问的是Ubuntu环境,所以需要确保步骤适用于Linux系统,可能需要安装依赖项,如CMake、g++等。 根据引用[2]中的经验,移植OpenCV3.1的LSD代码可能更简单。需要指导用户如何下载旧版本的OpenCV源码,提取必要文件,并集成到自己的项目中。同时,需要注意可能的编译问题,比如头文件缺失或命名空间变化。 此外,用户可能需要安装旧版本的OpenCV,但引用[2]中的用户通过直接导入文件避免了重新编译整个OpenCV,这可能更高效。因此,建议用户采用这种方法,并指导如何修改代码以适应新环境。 可能的步骤包括: - 下载OpenCV3.1的源码。 - 提取lsd相关的源文件和头文件。 - 创建新的项目,将这些文件加入其中。 - 处理编译时的依赖和错误,比如注释掉无法找到的头文件。 - 测试代码是否正常运行。 另外,可能需要使用CMake来管理项目,确保正确链接OpenCV库。 另外,用户可能需要Python接口,但LSDOpenCV中的Python绑定可能在新版本中不可用,所以可能需要用C++编写,或者寻找其他Python库如lsd-py。 不过,根据引用[5],MATLAB调用OpenCVLSD可能存在,但用户可能更倾向于在Ubuntu上使用C++或Python。 总结可能的步骤: 1. **方法一:移植OpenCV3.1的LSD模块** - 下载OpenCV3.1源码 - 提取lsd.cpp和precomp.hpp - 创建新项目,添加这些文件 - 调整头文件和命名空间 - 编译并测试 2. **方法二:使用第三方实现** - 克隆LSD作者的原生实现(如https://github.com/primetang/LSD-OpenCV-MATLAB) - 编译并集成到项目中 3. **方法三:安装旧版OpenCV** - 通过源码安装OpenCV3.1 - 在项目中使用LSD算法 其中,方法一可能更简单,如引用[2]中用户成功通过此方法实现。需要详细说明如何操作,包括文件路径、代码修改等。 同时,需要提醒用户注意可能的兼容性问题,比如OpenCV其他模块的版本冲突。 此外,可能还需要示例代码,展示如何调用LSD检测线段,并显示结果。 最后,需要生成相关问题,如优化检测速度、处理实时性问题、替代算法比较等,根据引用内容中的信息。</think>### LSD线特征提取算法在Ubuntu上的实现方法 #### 方法一:移植OpenCV 3.1的LSD模块(推荐) **步骤说明:** 1. **下载OpenCV 3.1源码** 从官方仓库获取旧版本代码: ```bash wget https://github.com/opencv/opencv/archive/3.1.0.zip unzip 3.1.0.zip ``` 2. **提取关键文件** 复制以下文件到你的工程目录: - `opencv-3.1.0/modules/imgproc/src/lsd.cpp` - `opencv-3.1.0/modules/imgproc/include/opencv2/imgproc/detail/precomp.hpp` 3. **修改代码适配新环境** - 在`precomp.hpp`中注释掉无法找到的头文件引用,例如: ```cpp // #include "opencv2/core/private.hpp" // 注释掉此行 ``` - 在`lsd.cpp`中将命名空间`cv::detail`改为`cv`[^2]。 4. **编写调用示例(C++)** ```cpp #include <opencv2/opencv.hpp> #include "lsd.cpp" // 导入移植后的LSD实现 int main() { cv::Mat image = cv::imread("test.jpg", 0); std::vector<cv::Vec4i> lines; cv::Ptr<cv::LineSegmentDetector> lsd = cv::createLineSegmentDetector(); lsd->detect(image, lines); // 可视化结果 cv::Mat result; lsd->drawSegments(image, result, lines); cv::imshow("LSD Result", result); cv::waitKey(0); return 0; } ``` 5. **编译项目** 使用CMake管理工程,示例`CMakeLists.txt`: ```cmake cmake_minimum_required(VERSION 3.10) project(LSD_Demo) find_package(OpenCV REQUIRED) add_executable(main main.cpp lsd.cpp) target_link_libraries(main ${OpenCV_LIBS}) ``` --- #### 方法二:使用第三方库(原生LSD实现) 1. **克隆源码并编译** 例如使用作者维护的版本: ```bash git clone https://github.com/primetang/LSD-OpenCV-MATLAB cd LSD-OpenCV-MATLAB mkdir build && cd build cmake .. && make ``` 2. **在代码中调用** ```cpp #include "lsd.h" cv::Mat image = cv::imread("test.jpg", 0); double* lines; int n_lines; lines = lsd(&n_lines, (double*)image.data, image.cols, image.rows); ``` --- #### 方法三:安装旧版OpenCV(不推荐) 若需完整安装OpenCV 3.1: ```bash sudo apt install libopencv-dev=3.1.0 # 需确认仓库版本 ``` 但可能因依赖冲突难以实现,建议优先选择方法一。 --- ### 性能优化建议 - **减少检测线段数量**:通过调整LSD参数(如`scale`、`sigma_scale`)过滤短线[^4]。 - **并行计算**:结合OpenMP加速处理。 - **硬件加速**:使用GPU版本的OpenCV(需重新编译)。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值