【line features】线特征

2023-05-16

使用BinaryDescriptor接口提取线条并将其存储在KeyLine对象中,使用相同的接口计算每个提取线条的描述符,使用BinaryDescriptorMatcher确定从不同图像获得的描述符之间的匹配。
opencv提供接口实现

线提取和描述符计算
下面的代码片段展示了如何从图像中检测出线条。LSD提取器使用LSD_REFINE_ADV选项进行初始化;其余参数保持默认值。使用全1掩码以接受所有提取的线条,最后使用随机颜色显示第0个八度的线条。

#include <iostream>
 #include <opencv2/opencv_modules.hpp>
 
 #ifdef HAVE_OPENCV_FEATURES2D
 
 #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();
 }
 
 #else
 
 int main()
 {
     std::cerr << "OpenCV was built without features2d module" << std::endl;
     return 0;
 }
 
 #endif // HAVE_OPENCV_FEATURES2D

在这里插入图片描述

另一种提取线条的方法是使用LSDDetector类;这种类使用LSD提取器来计算线条。为了获得这个结果,只需使用上面看到的代码片段,通过修改行即可。
Here’s the result returned by LSD detector again on cameraman picture:
在这里插入图片描述

 #include <iostream>
 #include <opencv2/opencv_modules.hpp>
 
 #ifdef HAVE_OPENCV_FEATURES2D
 
 #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;
 
 
 static const char* keys =
 { "{@image_path | | Image path }" };
 
 static void help()
 {
   std::cout << "\nThis example shows the functionalities of lines extraction " << "and descriptors computation furnished by BinaryDescriptor class\n"
             << "Please, run this sample using a command in the form\n" << "./example_line_descriptor_compute_descriptors <path_to_input_image>"
             << std::endl;
 }
 
 int main( int argc, char** argv )
 {
   /* get parameters from command 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;
   }
 
   /* create a binary mask */
   cv::Mat mask = Mat::ones( imageMat.size(), CV_8UC1 );
 
   /* create a pointer to a BinaryDescriptor object with default parameters */
   Ptr<BinaryDescriptor> bd = BinaryDescriptor::createBinaryDescriptor();
 
   /* compute lines */
   std::vector<KeyLine> keylines;
   bd->detect( imageMat, keylines, mask );
 
   /* compute descriptors */
   cv::Mat descriptors;
 
   bd->compute( imageMat, keylines, descriptors);
 
 }
 
 #else
 
 int main()
 {
     std::cerr << "OpenCV was built without features2d module" << std::endl;
     return 0;
 }
 
 #endif // HAVE_OPENCV_FEATURES2D

Matching among descriptors
如果我们从两幅不同的图像中提取了描述符,那么可以在它们之间搜索匹配项。其中一种方法是将每个输入查询描述符与一个描述符进行精确匹配,并选择最接近的那个。

#include <iostream>
 #include <opencv2/opencv_modules.hpp>
 
 #ifdef HAVE_OPENCV_FEATURES2D
 
 #include <opencv2/line_descriptor.hpp>
 #include <opencv2/core/utility.hpp>
 #include <opencv2/imgproc.hpp>
 #include <opencv2/features2d.hpp>
 #include <opencv2/highgui.hpp>
 
 #define MATCHES_DIST_THRESHOLD 25
 
 using namespace cv;
 using namespace cv::line_descriptor;
 
 static const char* keys =
 { "{@image_path1 | | Image path 1 }"
     "{@image_path2 | | Image path 2 }" };
 
 static void help()
 {
   std::cout << "\nThis example shows the functionalities of lines extraction " << "and descriptors computation furnished by BinaryDescriptor class\n"
             << "Please, run this sample using a command in the form\n" << "./example_line_descriptor_compute_descriptors <path_to_input_image 1>"
             << "<path_to_input_image 2>" << std::endl;
 
 }
 
 int main( int argc, char** argv )
 {
   /* get parameters from command line */
   CommandLineParser parser( argc, argv, keys );
   String image_path1 = parser.get<String>( 0 );
   String image_path2 = parser.get<String>( 1 );
 
   if( image_path1.empty() || image_path2.empty() )
   {
     help();
     return -1;
   }
 
   /* load image */
   cv::Mat imageMat1 = imread( image_path1, 1 );
   cv::Mat imageMat2 = imread( image_path2, 1 );
 
   if( imageMat1.data == NULL || imageMat2.data == NULL )
   {
     std::cout << "Error, images could not be loaded. Please, check their path" << std::endl;
   }
 
   /* create binary masks */
   cv::Mat mask1 = Mat::ones( imageMat1.size(), CV_8UC1 );
   cv::Mat mask2 = Mat::ones( imageMat2.size(), CV_8UC1 );
 
   /* create a pointer to a BinaryDescriptor object with default parameters */
   Ptr<BinaryDescriptor> bd = BinaryDescriptor::createBinaryDescriptor(  );
 
   /* compute lines and descriptors */
   std::vector<KeyLine> keylines1, keylines2;
   cv::Mat descr1, descr2;
 
   ( *bd )( imageMat1, mask1, keylines1, descr1, false, false );
   ( *bd )( imageMat2, mask2, keylines2, descr2, false, false );
 
   /* select keylines from first octave and their descriptors */
   std::vector<KeyLine> lbd_octave1, lbd_octave2;
   Mat left_lbd, right_lbd;
   for ( int i = 0; i < (int) keylines1.size(); i++ )
   {
     if( keylines1[i].octave == 0 )
     {
       lbd_octave1.push_back( keylines1[i] );
       left_lbd.push_back( descr1.row( i ) );
     }
   }
 
   for ( int j = 0; j < (int) keylines2.size(); j++ )
   {
     if( keylines2[j].octave == 0 )
     {
       lbd_octave2.push_back( keylines2[j] );
       right_lbd.push_back( descr2.row( j ) );
     }
   }
 
   /* create a BinaryDescriptorMatcher object */
   Ptr<BinaryDescriptorMatcher> bdm = BinaryDescriptorMatcher::createBinaryDescriptorMatcher();
 
   /* require match */
   std::vector<DMatch> matches;
   bdm->match( left_lbd, right_lbd, matches );
 
   /* select best matches */
   std::vector<DMatch> good_matches;
   for ( int i = 0; i < (int) matches.size(); i++ )
   {
     if( matches[i].distance < MATCHES_DIST_THRESHOLD )
       good_matches.push_back( matches[i] );
   }
 
   /* plot matches */
   cv::Mat outImg;
   cv::Mat scaled1, scaled2;
   std::vector<char> mask( matches.size(), 1 );
   drawLineMatches( imageMat1, lbd_octave1, imageMat2, lbd_octave2, good_matches, outImg, Scalar::all( -1 ), Scalar::all( -1 ), mask,
                      DrawLinesMatchesFlags::DEFAULT );
 
   imshow( "Matches", outImg );
   waitKey();
   imwrite("/home/ubisum/Desktop/images/env_match/matches.jpg", outImg);
   /* create an LSD detector */
   Ptr<LSDDetector> lsd = LSDDetector::createLSDDetector();
 
   /* detect lines */
   std::vector<KeyLine> klsd1, klsd2;
   Mat lsd_descr1, lsd_descr2;
   lsd->detect( imageMat1, klsd1, 2, 2, mask1 );
   lsd->detect( imageMat2, klsd2, 2, 2, mask2 );
 
   /* compute descriptors for lines from first octave */
   bd->compute( imageMat1, klsd1, lsd_descr1 );
   bd->compute( imageMat2, klsd2, lsd_descr2 );
 
   /* select lines and descriptors from first octave */
   std::vector<KeyLine> octave0_1, octave0_2;
   Mat leftDEscr, rightDescr;
   for ( int i = 0; i < (int) klsd1.size(); i++ )
   {
     if( klsd1[i].octave == 1 )
     {
       octave0_1.push_back( klsd1[i] );
       leftDEscr.push_back( lsd_descr1.row( i ) );
     }
   }
 
   for ( int j = 0; j < (int) klsd2.size(); j++ )
   {
     if( klsd2[j].octave == 1 )
     {
       octave0_2.push_back( klsd2[j] );
       rightDescr.push_back( lsd_descr2.row( j ) );
     }
   }
 
   /* compute matches */
   std::vector<DMatch> lsd_matches;
   bdm->match( leftDEscr, rightDescr, lsd_matches );
 
   /* select best matches */
   good_matches.clear();
   for ( int i = 0; i < (int) lsd_matches.size(); i++ )
   {
     if( lsd_matches[i].distance < MATCHES_DIST_THRESHOLD )
       good_matches.push_back( lsd_matches[i] );
   }
 
   /* plot matches */
   cv::Mat lsd_outImg;
   resize( imageMat1, imageMat1, Size( imageMat1.cols / 2, imageMat1.rows / 2 ), 0, 0, INTER_LINEAR_EXACT );
   resize( imageMat2, imageMat2, Size( imageMat2.cols / 2, imageMat2.rows / 2 ), 0, 0, INTER_LINEAR_EXACT );
   std::vector<char> lsd_mask( matches.size(), 1 );
   drawLineMatches( imageMat1, octave0_1, imageMat2, octave0_2, good_matches, lsd_outImg, Scalar::all( -1 ), Scalar::all( -1 ), lsd_mask,
                    DrawLinesMatchesFlags::DEFAULT );
 
   imshow( "LSD matches", lsd_outImg );
   waitKey();
 
 
 }
 
 #else
 
 int main()
 {
     std::cerr << "OpenCV was built without features2d module" << std::endl;
     return 0;
 }
 
 #endif // HAVE_OPENCV_FEATURES2D

这段文本讨论了一种图像处理中的技术,即寻找最接近的k个描述符。描述符是一种用于描述图像特征的数学表示。在这种技术中,我们需要对先前的代码进行一些修改。

// prepare a structure to host matches
std::vector<std::vector<DMatch> > matches;
// require knn match
bdm->knnMatch( descr1, descr2, matches, 6 );

在上面的例子中,对于每个查询,返回最接近的6个描述符。在某些情况下,我们可以有一个搜索半径,查找距离输入查询最多为r的所有描述符。必须修改先前的代码:

// prepare a structure to host matches
std::vector<std::vector<DMatch> > matches;
// compute matches
bdm->radiusMatch( queries, matches, 30 );

这是一个从原始摄影师图像及其下采样(和模糊)版本提取描述符进行匹配的示例。

线特征基础实现

线特征优化实现
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

优化前后:里哟个均匀性质

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【line features】线特征 的相关文章

  • 5 Ways To Fix Slow 802.11n Speed

    http www cnblogs com jjkv3 archive 2012 04 22 2464919 html o you went and bought a shiny new 802 11n router and were all
  • Linux IPC总结(全)

    IPC进程间通信 Inter Process Communication 就是指多个进程之间相互通信 xff0c 交换信息的方法 Linux IPC基本上都是从Unix平台上继承而来的 主要包括最初的Unix IPC xff0c Syste
  • 升级WEXT到NL80211/CFG80211

    内容包括 xff1a 1 分析两者的区别 2 分析两者的架构 xff0c 重点在后者 3 如何将在WE架构中用到的standard和private的command在新的架构中实现 请等待
  • Zebra-VTYSH源码分析和改造(三):添加定制命令

    一 视图介绍 由上面几篇文章分析可见 xff0c 所有的命令都是包含在node中的 xff0c 根据Cisco或者H3常见路由器或者交换机的CLI格式可见 xff0c 一个node就对应着一个视图 xff08 View xff09 常用的视
  • Bringup wifi driver to android 6.0

    1 android root system core rootdir init rc mkdir data misc systemkeys 0700 system system mkdir data misc wifi 0770 wifi
  • [简单总结] WiFi中的RTS和CTS简单回顾

    通信协议中的RTS CTS协议 xff1a 即请求发送 允许发送协议 xff0c 相当于一种握手协议 xff0c 主要用来解决 34 隐藏终端 34 问题 34 隐藏终端 34 xff08 Hidden Stations xff09 是指
  • 【OpenCV】 2D-2D:对极几何算法原理

    2D 2D匹配 对极几何 SLAM十四讲笔记1 1 1 对极几何數學模型 考虑从两张图像上观测到了同一个3D点 xff0c 如图所示 我们希望可以求解相机两个时刻的运动 R t R t R t 假设我们要求取两帧图像
  • 蓝牙技术谈之跳频技术(一)

    跳频技术 Frequency Hopping Spread Spectrum xff1b FHSS 在同步 且同时的情况下 xff0c 接收两端以特定型式的窄频载波来传送讯号 xff0c 对于一个非特定的接收器 xff0c FHSS所产生的
  • 女生应该选JAVA还是前端?

    纵观现阶段互联网web前端开发工程师的就业人员 xff0c 女孩子从事这个行业的比例不大 xff0c 由于这种想象的存在 xff0c 当有女孩说想要学习web前端开发 xff0c 想成为一个牛逼的程序员的时候 xff0c 很多不一样的声音就
  • 在VNC中Xfce4中Tab键失效的解决方法

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 说明 在Ubuntu Server 14 04上安装了xfce4桌面环境 xff0c 但是却发现 在终端中Tab键不能自动补齐
  • 浏览器网页视频怎么快速下载到本地?

    我们在浏览网页时 xff0c 经常会遇到一些特别喜欢的视频文件 xff0c 想要下载收藏却苦于不会操作怎恶魔办呢 xff1f 这时候可以通过一些小插件快速达成下载 xff0c 比如通过猫爪视频下载插件用户可以轻松的抓取任意网页的视频文件 x
  • [golang]-interface转string

    导语 xff1a 使用将gitlab中某个项目的分支提取出来后返回的是interface类型 希望转换成string后存入数据库 interface 转 string 代码是抄来的 xff5e Strval 获取变量的字符串值 浮点型 3
  • [问题已处理]-linux在关机前执行脚本

    导语 xff1a 需要在关机和重启前执行一下关机前的脚本 避免某些服务没有正常关闭导致的问题 xff0c 或者某些服务关闭慢的问题 创建 lib systemd system cleanup service Unit Description
  • [linux]-ubuntu使用ufw及相关配置

    导语 xff1a 记录一下ufw的使用方式以及规则配置文件的更改 UFW配置文件 虽然可以通过命令行添加简单的规则 xff0c 但有些时候也需要添加或删除更加高级或特定的防火墙规则 在运行通过终端输入的规则之前 xff0c UFW会首先运行
  • dependencyManagement与dependencies区别

    dependencyManagement与dependencies区别 最近在阅读maven项目代码时 xff0c dependencyManagement与dependencies之间的区别不是很了解 xff0c 现通过项目实例进行总结
  • Linux-Day2_(包含软件)防火墙配置_软件安装_项目部署_虚拟机克隆_镜像还原

    Linux Day02 软件安装 soft https www aliyundrive com s 8ybAVk3nwhL 点击链接保存 xff0c 或者复制本段内容 xff0c 打开 阿里云盘 APP xff0c 无需下载极速在线查看 x
  • gnome菜单图标显示

    国产操作系统deepin uos都是gnome为基础的 xff0c 默认菜单里面不显示图标 这是因为他们基础gnome xff0c 而GNOME 从2 28之后 xff0c 按钮和菜单中的图标默认不再显示 如果要显示 xff0c 可以使用下
  • 【Algorithm】连续线性表模拟实现vector功能

    Cmakelists span class token function cmake minimum required span span class token punctuation span VERSION span class to
  • Spring+Springmvc+Mabatis环境搭建

    1 Download JDK 8 http www oracle com technetwork java javase downloads jdk8 downloads 2133151 html 环境变量 JAVA HOME D Prog
  • Ubuntu启动VirtualBox虚拟机之后鼠标无法打开菜单或者其他窗口的问题

    不知道从哪个版本 xff08 大概6 0之前的版本 xff09 开始 xff0c 某次升级了VirtualBox xff0c VirtualBox启动虚拟机之后 xff0c 鼠标点击菜单无法打开菜单 xff0c 任务栏上点击其他任务的图标也

随机推荐

  • spring boot使用logback时控制台不打印日志,使用slf4j解决不打印日志问题

    maven项目在pom中添加slf4j依赖 lt 用于解决日志不打印问题 gt lt dependency gt lt groupId gt org slf4j lt groupId gt lt artifactId gt slf4j ap
  • Android P 下keymaster安装流程

    转载请说明出处 菜鸡一只 xff0c 刚好学习到这里 xff0c 就分享一下 如有不对请各位大佬指出 InstallKeybox cpp 入口函数 KmInstallKeybox 进行安装 KM SECURITY LEVEL TRUSTED
  • 解决msvcr120.dll文件丢失问题(搞了半天,简直奔溃,最后完美解决)

    我是在安装MySQL时提示缺少这个文件 xff0c 搞了1太多 xff0c 各种方法都试了 解决办法 xff1a 试了好多方法 xff0c 都解决不了 网上下载msvcr120 dll放到对应目录下失败 下载安装VC 43 43 2013
  • NSS 错误码详细信息

    Table 8 1 Error codes defined in sslerr h SSL ERROR EXPORT ONLY SERVER 12288 Unable to communicate securely Peer does no
  • nltk.download失败解决方案

    因国际网络连接不稳定 xff0c 很多国内的小伙伴在使用NLTK下载停用词表时都碰到过下载失败的情况 其实解决方法很简单 xff0c 只要先下载官网停用词包 xff0c 然后在手动复制到NLTK对应目录下就好了 xff0c 具体方法如下 x
  • 谨以此文献给正在面临选择的你

    我是2011届的考生 xff0c 当我从我们学校的的分数公布栏上看到自己的分数时 xff0c 我感觉我的世界都变成了灰色 xff0c 一切都暗淡无光 在那段时间里 xff0c 我思考了很多的问题 xff0c 诸如要不要去复读 去哪一所学校
  • Android应用程序获取系统签名的方法

    在Android应用程序开发过程中 xff0c 经常会碰到要获取系统权限的问题 例如 xff1a lt uses permission android name 61 34 android permission STATUS BAR 34
  • VMware安装openEuler-20.03系统图文安装教程

    VMware安装openEuler 20 03系统图文安装教程 1 环境概要 系统架构 xff1a x86 64虚拟机软件 xff1a VMware16 pro安装的操作系统 xff1a openEuler 20 03 LTS 2 安装前准
  • 【雅可比左乘右乘】

    常见雅可比左乘 xff08 以自变量R为例子 xff0c 围绕旋转点p的旋转点的左扰动雅可比 xff09 xff1a 旋转点的右扰动雅可比 xff08 右乘 xff09 xff1a 左雅可比和右雅可比之间的区别在于它们各自描述了不同的变换方
  • Linux 下的 ActiveMQ C++ 客户端开发

    ActiveMQ CPP 是一个提供消息库 xff0c 即 ActiveMQ C 43 43 客户端 API 通过该接口 xff0c 我们可以使用多种协议来与消息中间件进行通信 本文主要针对 CentOS 7 x64 xff08 Linux
  • 基于Docker快速搭建ELK6.7.0

    1 安装ElasticSearch 1 1准备工作 1 1 1节点介绍 192 168 1 21 192 168 1 22 192 168 1 23 1 1 2拉取镜像 三台虚拟机都执行 docker pull elasticsearch
  • mysql事务中ddl语句的隐式提交

    1 当执行到DDL语句时 xff0c 会隐式的将当前回话的事务进行一次 COMMIT 操作 xff0c 因此在MySQL中执行DDL语句时 xff0c 应该严格地将DDL和DML完全分开 xff0c 不能混合在一起执行 2 为什么DDL语句
  • python基于UDP广播实现查找局域网服务器

    UDP广播案例 发送端 from socket import import time 设定目标地址 dest 61 39 192 168 31 255 39 9999 192 168 31是我的网段 255代表任意IP s 61 socke
  • 基于kibana开发工具(Dev Tools )修改logstash模板

    1 查询模板 GET template logstash Deprecation types removal The parameter include type name should be explicitly specified in
  • CentOS 7 MySQL自动备份shell脚本

    系统环境 xff1a CentOS7 64位 Minimal版 xff08 VMware xff09 MySQL5 7 原理与工具 xff1a shell脚本 mysqldump程序 crontab命令 1 新建shell脚本 vi opt
  • Centos7.2下RocketMQ 集群部署(2m-2s-sync)

    一 环境准备与介绍 1 部署架构 使用的模式是 2m 2s sync 2 broker机器信息 Master 1 xff1a 192 168 31 5 Slave 1 xff1a 192 168 31 6 Master 2 xff1a 19
  • centos7 快速卸载openjdk

    rpm qa grep java xargs rpm e nodeps 参考 xff1a https blog csdn net weixin 34060741 article details 91905833
  • CentOS7下安装部署kafka集群

    一 环境 在centos7 2系统下 xff0c 使用3台服务器搭建集群 Server1 192 168 1 11 Server2 192 168 1 12 Server3 192 168 1 13 二 安装配置JDK 下载并安装JDK1
  • Centos7安装Hadoop2.6.0集群

    一 环境准备与介绍 1 部署架构 使用的模式是 1m 2s 2 nameserver机器信息 192 168 1 89 node1 192 168 1 149 node2 192 168 1 180 node3 2 修改主机名称 2 1 分
  • 【line features】线特征

    使用BinaryDescriptor接口提取线条并将其存储在KeyLine对象中 xff0c 使用相同的接口计算每个提取线条的描述符 xff0c 使用BinaryDescriptorMatcher确定从不同图像获得的描述符之间的匹配 ope