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

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),并且还具有直线的方向(角度)和长度成员变量。
具体从上面两个代码片段的可视化部分展示的清清楚楚。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IDEA类和方法注释模板设置

一、概述 IDEA自带的注释模板不是太好用&#xff0c;我本人到网上搜集了很多资料系统的整理了一下制作了一份比较完整的模板来分享给大家&#xff0c;我不是专业玩博客的&#xff0c;写这篇文章只是为了让大家省事。 这里设置的注释模板采用Eclipse的格式&#xff0c;下面先贴…

【深度优先搜索】【图论】【推荐】332. 重新安排行程

作者推荐 动态规划的时间复杂度优化 本文涉及知识点 深度优先搜索 图论 LeetCode332. 重新安排行程 给你一份航线列表 tickets &#xff0c;其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。 所有这些机票都属于一个从 JFK&a…

C++:常量表达式

C11开始constexpr作为一种声明&#xff0c;为编译器提供了在编译期间确认结果的优化建议&#xff0c;满足部分编译期特性的需求 constexpr和const区别 int b10; const int ab; //运行成功 constexpr int cb; //编译器报错&#xff0c;b的值在编译期间不能确定 const int size1…

研发日记,MatlabSimulink开箱报告(九)——Simulink Test模块

文章目录 前言 Simulink Test模块 静态测试 动态测试 逻辑测试 前言 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;四&#xff09;——S-Fuction模块》 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;五&#xff09;——S-F…

vue a-table 实现指定字段相同数据合并行

vue a-table 实现相同数据合并行 实现效果代码实现cloums数据格式数据源格式合并代码 实现效果 代码实现 cloums数据格式 const getColumns function () {return [{title: "分类",dataIndex: "checked",width: "150px",customRender: (text, …

有哪些视频媒体?邀请视频媒体报道活动的好处

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 视频媒体在当今的媒体生态中占据了重要的地位。以下是一些主要的视频媒体类型&#xff1a; 电视台&#xff1a;如中央电视台、各省级卫视台、地方电视台等&#xff0c;他们拥有专业的视…

mac命令行下计算文件SHA-256散列值

源起 从国内的第三方网站下载了Android sutiod的zip包下载地址&#xff0c;为了安全起见还是得跟Android官网上的对应的zip包的SHA值做下对比。以前是经常使用md5命令的&#xff0c;所以理论在命令行下应该是有对应的命令行工具可以计算SHA值的。后来搜索到可以用 shasum命令来…

yolov8训练目标检测模型

1.环境安装 conda安装&#xff08;miniconda&#xff09;&#xff0c;配置环境变量 创建环境 conda create -n yolo python3.8安装ultralytics conda activate yolopip install ultralytics2.数据集标注 使用labelimg标注工具对图片进行标注&#xff1a;将标注产生的xml转为t…

表格图片太大怎么批量压缩?快速处理图片大小的方法

在工作或者学习中制作表格的时候&#xff0c;经常需要插入一些图片来修饰内容&#xff0c;当遇到图片太大无法导入的情况就比较麻烦&#xff0c;尤其是多张图片处理的时候&#xff0c;那么表格图片太大怎么批量压缩呢&#xff1f;接下来小编就分享给大家一个快速图片压缩的方法…

HTTP详解(HTTP的特点,状态码,工作原理,GET和POST的区别,如何解决无状态通信)!!!

文章目录 一、HTTP协议简介二、HTTP的主要特点三、HTTP之URL四、Request和Respons五、HTTP的状态码六、HTTP工作原理七、GET和POST请求的区别八、解决HTTP无状态通信——Cookie和Session 一、HTTP协议简介 HTTP协议是Hyper Text Transfer Protocol&#xff08;超文本传输协议&…

92. 递归实现指数型枚举 刷题笔记

思路 dfs 考虑选或者不选每个位置 用0表示未考虑 1表示选 2表示不选 用u表示搜索状态 u>n时 已经搜到底层了 需要输出当前方案 遍历 如果选了则输出 #include<iostream> using namespace std; int n; const int N16; int st[N]; void dfs(int u){ //u来记…

JVM运行时数据区——程序计数器

1、程序计数器介绍 JVM中的程序计数器英文全称是Program Counter Register&#xff0c;其中Register的命名源于CPU的寄存器&#xff0c;寄存器用于存储指令相关的现场信息&#xff0c;CPU只有把数据装载到寄存器才能够运行。 程序计数器中的寄存器并非是广义上所指的物理寄存…

音频提取使用什么方法?视频提取音频

在数字技术与多媒体日益普及的今天&#xff0c;音频提取已成为一个常见且重要的任务。无论是为了制作视频、编辑音乐&#xff0c;还是进行语音识别和分析&#xff0c;我们都需要从原始材料中提取音频。那么&#xff0c;音频提取通常使用什么方法呢&#xff1f; 1. 使用专业的音…

vue-router4 (六) 路由嵌套

应用场景&#xff1a; ①比如京东页面的首页、购物车、我的按钮&#xff0c;可以点击切换到对应的页面&#xff1b; ② 比如 Ant Design左侧这些按钮点击就会切到对应的页面&#xff0c;此时可以把左侧按钮放在父路由中&#xff0c;右侧的子路由 1.路由配置&#xff0c;子路由…

NLP-词向量、Word2vec

Word2vec Skip-gram算法的核心部分 我们做什么来计算一个词在中心词的上下文中出现的概率&#xff1f; 似然函数 词已知&#xff0c;它的上下文单词的概率 相乘。 然后所有中心词的这个相乘数 再全部相乘&#xff0c;希望得到最大。 目标函数&#xff08;代价函数&#xff0…

web学习笔记(二十二)DOM开始

目录 1.DOM简介 2.DOM树 3.DOM节点 4.查找DOM节点方法汇总 5.查找子结点的属性 5.1父子关系 5.2兄弟关系 6.几个特殊元素的查找 1.DOM简介 DOM&#xff08;Document Object Model&#xff09; 也叫页面文档对象模型&#xff0c;是W3C组织推荐的处理可扩展标记语言(HTML…

年度目标制定:数据驱动的深度策略,打造你的成功蓝图!

导语&#xff1a;在快节奏的生活中&#xff0c;制定年度目标不仅仅是为了完成任务&#xff0c;更是为了在一年中明确方向、聚焦重点、持续进步。而数据分析&#xff0c;则是我们制定年度目标时不可或缺的利器。通过深入挖掘数据&#xff0c;我们可以更准确地理解自己的需求、优…

数据中台的演进与实践——构建企业的数字核心_光点科技

数据中台&#xff0c;一个在近年来被频繁提及的概念&#xff0c;已经成为众多企业数字化转型的核心组成部分。然而&#xff0c;尽管它的重要性被业界广泛认可&#xff0c;对于数据中台的深入理解和有效实践仍然是许多企业面临的挑战。在本文中&#xff0c;我们将从数据中台的演…

在线原型工具有哪些比较好用?

随着云计算和5G网络的发展&#xff0c;互联网办公工具的发展 Web 这是一个不可避免的趋势。那么&#xff0c;对于产品设计团队来说&#xff0c;哪些在线设计工具值得体验呢&#xff1f;今天&#xff0c;让我们来看看一些国内外经典的在线原型工具。 即时设计 - 可实时协作的专…

React入门之react_jsx入门

简单语法写法 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><script s…