opencv中两个LSD直线检测算法的区别与应用

news2024/11/17 9:51:47

opencv中两个LSD直线检测算法的区别与应用

同样是Line Segment Detector(lsd)算法,opencv中提供了两种实现,并且位于不同的模块。下面分别介绍它们的使用方法:

1. LineSegmentDetector

由于源码许可证问题 OpenCV 3.4.6-3.4.15、4.1.0-4.5.3中无法使用这个方法

使用该类检测直线并显示的代码如下:

import cv2

 if __name__ == '__main__':
    img = cv2.imread("test.jpg")
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    gray_img = cv2.GaussianBlur(gray_img, (3,3), 2.0)
    #LineSegmentDetector
    lsd = cv2.createLineSegmentDetector(refine=cv2.LSD_REFINE_NONE, scale=0.8, ang_th=35)
    lines_detected, width, prec, nfa = lsd.detect(gray_img)
    #lsd.drawSegments(img,lines_detected)
    #绘制检测结果
    for dline in lines_detected:
        x0 = int(round(dline[0][0]))
        y0 = int(round(dline[0][1]))
        x1 = int(round(dline[0][2]))
        y1 = int(round(dline[0][3]))
        cv2.line(mask, (x0, y0), (x1,y1), 255, 1, cv2.LINE_AA)
    cv2.imshow("Detected lines", img)
    cv2.waitKey(0)
    cv.destroyAllWindows()

c++示例代码如下(lsd_lines.cpp):

#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
    cv::CommandLineParser parser(argc, argv,
                                 "{input   i|../data/building.jpg|input image}"
                                 "{refine  r|false|if true use LSD_REFINE_STD method, if false use LSD_REFINE_NONE method}"
                                 "{canny   c|false|use Canny edge detector}"
                                 "{overlay o|false|show result on input image}"
                                 "{help    h|false|show help message}");
    if (parser.get<bool>("help"))
    {
        parser.printMessage();
        return 0;
    }
    parser.printMessage();
    String filename = parser.get<String>("input");
    bool useRefine = parser.get<bool>("refine");
    bool useCanny = parser.get<bool>("canny");
    bool overlay = parser.get<bool>("overlay");
    Mat image = imread(filename, IMREAD_GRAYSCALE);
    if( image.empty() )
    {
        cout << "Unable to load " << filename;
        return 1;
    }
    imshow("Source Image", image);
    if (useCanny)
    {
        Canny(image, image, 50, 200, 3); // Apply Canny edge detector
    }
    // Create and LSD detector with standard or no refinement.
    Ptr<LineSegmentDetector> ls = useRefine ? createLineSegmentDetector(LSD_REFINE_STD) : createLineSegmentDetector(LSD_REFINE_NONE);
    double start = double(getTickCount());
    vector<Vec4f> lines_std;
    // Detect the lines
    ls->detect(image, lines_std);
    double duration_ms = (double(getTickCount()) - start) * 1000 / getTickFrequency();
    std::cout << "It took " << duration_ms << " ms." << std::endl;
    // Show found lines
    if (!overlay || useCanny)
    {
        image = Scalar(0, 0, 0);
    }
    ls->drawSegments(image, lines_std);
    String window_name = useRefine ? "Result - standard refinement" : "Result - no refinement";
    window_name += useCanny ? " - Canny edge detector used" : "";
    imshow(window_name, image);
    waitKey();
    return 0;
}

2. cv::line_descriptor::LSDDetector

这个类在opencv_contrib中实现。源码目录结构示例如下:在这里插入图片描述
如果c++编译opencv时未包含contrib模块;或在python中用pip安装了opencv-python而不是opencv-contrib-python,均无法使用该LSD直线检测方法。
python用户只管卸载opencv-python,安装opencv-contrib-python,前者是后者的子集。

pip uninstall opencv-python
pip install opencv-contrib-python

使用该类检测直线并显示的python代码如下:

import cv2

 if __name__ == '__main__':
    img = cv2.imread("test.jpg")
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    gray_img = cv2.GaussianBlur(gray_img, (3,3), 2.0)
    #LSDDetector
    lsd = cv2.line_descriptor_LSDDetector.createLSDDetector()
    lines = lsd.detect(gray, 2, 1)
    for kl in lines:#绘制检测结果
        if kl.octave == 0:
            # cv.line only accepts integer coordinate
            pt1 = (int(kl.startPointX), int(kl.startPointY))
            pt2 = (int(kl.endPointX), int(kl.endPointY))
            cv.line(img, pt1, pt2, [255, 0, 0], 2)
    cv.imshow('Detected lines', img)
    cv.waitKey(0)
    cv.destroyAllWindows()

c++示例代码如下(lines_extraction.cpp):

#include <iostream>
#include <opencv2/opencv_modules.hpp>
#include <opencv2/line_descriptor.hpp>
#include <opencv2/core/utility.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/highgui.hpp>

using namespace cv;
using namespace cv::line_descriptor;
using namespace std;

static const char* keys =
{ "{@image_path | | Image path }" };

static void help()
{
  cout << "\nThis example shows the functionalities of lines extraction " << "furnished by BinaryDescriptor class\n"
       << "Please, run this sample using a command in the form\n" << "./example_line_descriptor_lines_extraction <path_to_input_image>" << endl;
}

int main( int argc, char** argv )
{
  /* get parameters from comand line */
  CommandLineParser parser( argc, argv, keys );
  String image_path = parser.get<String>( 0 );

  if( image_path.empty() )
  {
    help();
    return -1;
  }

  /* load image */
  cv::Mat imageMat = imread( image_path, 1 );
  if( imageMat.data == NULL )
  {
    std::cout << "Error, image could not be loaded. Please, check its path" << std::endl;
    return -1;
  }

  /* create a random binary mask */
  cv::Mat mask = Mat::ones( imageMat.size(), CV_8UC1 );

  /* create a pointer to a BinaryDescriptor object with deafult parameters */
  Ptr<LSDDetector> bd = LSDDetector::createLSDDetector();

  /* create a structure to store extracted lines */
  vector<KeyLine> lines;

  /* extract lines */
  cv::Mat output = imageMat.clone();
  bd->detect( imageMat, lines, 2, 1, mask );

  /* draw lines extracted from octave 0 */
  if( output.channels() == 1 )
    cvtColor( output, output, COLOR_GRAY2BGR );
  for ( size_t i = 0; i < lines.size(); i++ )
  {
    KeyLine kl = lines[i];
    if( kl.octave == 0)
    {
      /* get a random color */
      int R = ( rand() % (int) ( 255 + 1 ) );
      int G = ( rand() % (int) ( 255 + 1 ) );
      int B = ( rand() % (int) ( 255 + 1 ) );

      /* get extremes of line */
      Point pt1 = Point2f( kl.startPointX, kl.startPointY );
      Point pt2 = Point2f( kl.endPointX, kl.endPointY );

      /* draw line */
      line( output, pt1, pt2, Scalar( B, G, R ), 3 );
    }

  }

  /* show lines on image */
  imshow( "LSD lines", output );
  waitKey();
}

3. 区别与应用

这两种LSD实现的处理结果基本一致,但是获取检测到的直线的端点坐标的方式有所不同:
前者的直线检测结果是numpy array类型,每个直线由4个浮点数表示(x1, y1, x2, y2);后者的检测结果的直线类型,具有起点和端点成员变量,分别是(startPointX,startPointY,endPointX,endPointY),并且还具有直线的方向(角度)和长度成员变量。
具体从上面两个代码片段的可视化部分展示的清清楚楚。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1476515.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于uniapp小程序的分包问题

开发uniapp小程序时&#xff0c;在打包上传代码时会出现超出2M的打包限制不能上传&#xff0c;那么我们该怎么做呢&#xff1f; 1.对于图片&#xff0c;将图片从后端服务取&#xff0c;尽量不要放在静态资源&#xff0c;图片体积会影响打包大小。 2.使用分包&#xff0c;tabb…

蓝桥杯_中断系统

一 中断 中断&#xff0c;即cpu暂停执行当前程序&#xff0c;转而执行另外一段特殊程序&#xff0c;处理结束后。返回之前暂停程序继续执行。 中断向量&#xff0c;中断服务程序的入口地址&#xff0c;每个中断源都对应一个固定的入口地址。 中断服务函数&#xff0c;内核响应中…

华为s5720s-28p-power-li-ac堆叠配置

叠物理约束&#xff1a; • 连线推荐示意图选用产品子系列中固定的一款设备做示例&#xff0c;与选择产品时指定型号的外观可能不同。示意图主要用于让用户了解相同子系列设备可以用作堆叠的端口的位置&#xff0c;以及使用不同的连线方式时如何连接设备上的端口。因此&#xf…

解决vscode内置视图npm脚本操作报权限问题

项目背景 当我们使用 vscode 运行NPM脚本时却爆红了&#xff0c;提示系统上禁止运行脚本。 解决思路 竟然提示权限不够&#xff0c;那么咱们就从系统权限出发&#xff0c;vscode右键以管理员身份运行 在集成终端中输入一下命令 # get-executionpolicy是PowerShell中的命令,用…

推荐5个python可视化库

你是否曾为数据可视化而烦恼&#xff1f; 在浩瀚的数据海洋中&#xff0c;如何将复杂的数据以直观、易懂的方式展现出来&#xff0c;成为了每个数据分析师和开发者必须面对的挑战。 幸运的是&#xff0c;我们有众多强大的可视化工具可以选择。 推荐5个Python可视化库&#x…

JS画摆线

最近看到一个很漂亮的曲线&#xff0c;研究了一下。 从圆心画一条线匀速转动&#xff0c;终点再画一条线转动&#xff0c;2条线转速不同&#xff0c;会画出很漂亮的花纹。 一个周期 完整周期 <html> <style> body { background:black; } p { text-align:center; c…

Spring中的事务和事务的传播机制

事务是一组操作的集合&#xff0c;不可以被分割。事务会把所有的操作作为一个整体&#xff0c;这组操作要么全部成功&#xff0c;要么全部失败。 事务有三种操作&#xff1a; 开启事务&#xff1b;提交事务&#xff1b;回滚事务。 如果代码的执行逻辑是这样&#xff1a; 开…

国际黄金价格是什么?和黄金价格有何区别?

黄金是世界上最珍贵的贵金属之一&#xff0c;其价值被无数人所垂涎。而国际黄金价格作为市场上的参考指标&#xff0c;直接影响着黄金交易的买卖。那么国际黄金价格到底是什么&#xff0c;与黄金价格又有何区别呢&#xff1f;本文将为您详细解答。 国际黄金价格是指以美元计量的…

【双碳】Acrel-1000DP分布式光伏并网及数据采集与控制的方式

摘要&#xff1a; 在“双碳”、整县分布式光伏等相关政策的目标背景下&#xff0c;分布式新能源广泛建设&#xff0c;对分布式新能 源规划的科学性提出更高的要求&#xff0c;有源配电网调度面临大规模分布式新能源参与后的运行管理问题&#xff0c;增 大了电网运行管理的风险和…

用友 NC 23处接口XML实体注入漏洞复现

0x01 产品简介 用友 NC 是用友网络科技股份有限公司开发的一款大型企业数字化平台。 0x02 漏洞概述 用友 NC 多处接口存在XML实体注入漏洞,未经身份验证攻击者可通过该漏洞读取系统重要文件(如数据库配置文件、系统配置文件)、数据库配置文件等等,导致网站处于极度不安全…

图搜索基础-深度优先搜索

图搜索基础-深度优先搜索 参考原理引入流程解析手推例子 代码实现运行结果结果分析 参考 理论参考&#xff1a;深蓝学院 实现参考&#xff1a;github项目 原理 引入 对于这样一个图&#xff0c;我们试图找到S到G的通路&#xff1a; 计算机程序不会像人眼一样&#xff0c;一…

事件驱动的奇迹:深入理解Netty中的EventLoop

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 事件驱动的奇迹&#xff1a;深入理解Netty中的EventLoop 前言基础概念EventLoop的工作原理Channel与EventLoop的关系定时任务与延时任务EventLoop的生命周期EventLoop中的线程模型性能优化与最佳实践 …

前后端依赖下载上传

在某些情况下&#xff0c;可能需要在没有互联网连接的环境中进行构建或部署。通过提前下载所有依赖&#xff0c;你可以将它们保存在本地&#xff0c;然后在没有网络连接时使用&#xff0c;提高构建或部署的效率。 前端下载依赖 脚本getTzgUrl.js const { readFileSync, writ…

前端架构: 脚手架之包管理工具的案例对比及workspace特性的基本使用

Npm WorkSpace 特性 1 &#xff09;使用或不使用包管理工具的对比 vue-cli 这个脚手架使用 Lerna 管理&#xff0c;它的项目显得非常清晰在 vue-cli 中包含很多 package 点开进去&#xff0c;每一个包都有package.json它里面有很多项目&#xff0c;再没有 Lerna 之前去维护和管…

sql | leecode 1147 |即时事务配送II | sql 优化

sql 有时候还是挺有意思的&#xff0c;有时候不只是crud 下面来看一道sql 题&#xff0c;第一个题解能跑完&#xff0c;但是超时 浮躁的人总是很难看的进去&#xff0c;有时候孤单又在所难免&#xff0c;所以啊 要继续坚持&#xff0c;原来中学老师讲的那句&#xff0c;要耐住寂…

arm服务器上部署kibana

1.首先需要从elasticsearch对应的kibana版本(arm) ​​​​​​Download Kibana Free | Get Started Now | Elastic 注意:选平台时切勿选错,linux aarch64,并选择elasticsearch对应的历史版本 2.可以通过rz命令上传压缩包至 linux 服务器进行解压&#xff0c;存放路径建议和e…

物联网通信协议介绍

为了方便&#xff0c;将物联网通信协议分为两大类&#xff0c;一类是接入协议&#xff0c;一类是通讯协议。接入协议一般负责子网内设备间的组网及通信&#xff1b;通讯协议主要是运行在传统互联网TCP/IP协议之上的设备通讯协议&#xff0c;负责设备通过互联网进行数据交换及通…

数据结构:排序算法+查找算法

一、概念 程序数据结构算法 1.算法的特性和要求 特性&#xff1a; 确定性&#xff08;每次运行相同的输入都是同样的结果&#xff09;、有穷性、输入、输出、可行性 设计要求&#xff1a; 正确性、高效率、低存储、健壮性、可读性 2.时间复杂度 3.常见排序算法的时间复杂…

K8S存储卷与PV,PVC

一、前言 Kubernetes&#xff08;K8s&#xff09;中的存储卷是用于在容器之间共享数据的一种机制。存储卷可以在多个Pod之间共享数据&#xff0c;并且可以保持数据的持久性&#xff0c;即使Pod被重新调度或者删除&#xff0c;数据也不会丢失。 Kubernetes支持多种类型的存储卷…

MyBatis 学习(二)之 第一个 MyBatis 案例

目录 1 配置 MyBatis 方式 1.1 XML 配置文件 1.2 Java 注解配置 1.3. Java API 配置 2 在 MySQL 中创建一张表 3 创建一个基于 Maven 的 JavaWeb 工程 4 编写 User 实体类 5 创建Mybatis全局配置文件 6 编写一个 DAO 或 Mapper 接口 7 编写 SQL 映射配置文件&#xf…