【line features】线特征

news2024/12/23 9:07:09

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

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

线特征基础实现

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

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

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

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

相关文章

K8S相关核心概念

个人笔记&#xff1a; 要弄明白k8s的细节&#xff0c;需要知道k8s是个什么东西。它的主要功能&#xff0c;就是容器的调度--也就是把部署实例&#xff0c;根据整体资源的使用状况&#xff0c;部署到任何地方 注意任何这两个字&#xff0c;预示着你并不能够通过常规的IP、端口…

如何全面学习Object-C语言的语法知识 (Xmind Copilot生成)

网址&#xff1a;https://xmind.ai/login/ 登录后直接输入&#xff1a;如何全面学习Object-C语言的语法知识&#xff0c;就可以生成大纲 点击右上角的 按钮&#xff0c;可以显示md格式的问题&#xff0c;再点击生成全文&#xff0c;就可以生成所有内容了&#xff0c; 还有这个…

CentOS7/8 安装 5+ 以上的Linux kernel

CentOS以稳定著称&#xff0c;稳定在另外一方面就是保守。所以CentOS7还在用3.10&#xff0c;CentOS8也才是4.18。而当前最新的Linux Kernel都更新到6.0 rc3了。其他较新的发行版都用上了5.10的版本。本文简单介绍如何在CentOS7、8上直接安装5.1以上版本的第三方内核。 使用ted…

5.8晚间黄金行情走势分析及短线交易策略

近期有哪些消息面影响黄金走势&#xff1f;本周黄金多空该如何研判&#xff1f; ​黄金消息面解析&#xff1a;周一亚洲时段&#xff0c;现货黄金小幅反弹&#xff0c;目前交投于2024.3美元/盎司附近&#xff0c;一方面是金价上周五守住了 2000 整数关口&#xff0c;逢低买盘涌…

java环境Springboot框架中配置使用GDAL,并演示使用GDAL读取shapefile文件

GDAL是应用广泛的空间数据处理库&#xff0c;可以处理几何、栅格数据&#xff0c;Springboot是常用的JAVA后端开发框架。本文讲解如何在Springboot中配置使用GDAL。本文示例中使用的GDAL版本为3.4.1&#xff08;64位&#xff09; 图1 GDAL读取shp效果 一、部署GDAL类库 将GDA…

什么是点对点传输?什么是点对多传输

点对点技术&#xff08;peer-to-peer&#xff0c; 简称P2P&#xff09;又称对等互联网络技术&#xff0c;是一种网络新技术&#xff0c;依赖网络中参与者的计算能力和带宽&#xff0c;而不是把依赖都聚集在较少的几台服务器上。P2P网络通常用于通过Ad Hoc连接来连接节点。这类网…

WiFi(Wireless Fidelity)基础(四)

目录 一、基本介绍&#xff08;Introduction&#xff09; 二、进化发展&#xff08;Evolution&#xff09; 三、PHY帧&#xff08;&#xff08;PHY Frame &#xff09; 四、MAC帧&#xff08;MAC Frame &#xff09; 五、协议&#xff08;Protocol&#xff09; 六、安全&#x…

功能测试常用的测试用例大全

登录、添加、删除、查询模块是我们经常遇到的&#xff0c;这些模块的测试点该如何考虑 1)登录 ① 用户名和密码都符合要求(格式上的要求) ② 用户名和密码都不符合要求(格式上的要求) ③ 用户名符合要求&#xff0c;密码不符合要求(格式上的要求) ④ 密码符合要求&#xff0c;…

1_1torch学习

一、torch基础知识 1、torch安装 pytorch cuda版本下载地址&#xff1a;https://download.pytorch.org/whl/torch_stable.html 其中先看官网安装torch需要的cuda版本&#xff0c;之后安装cuda版本&#xff0c;之后采用pip 下载对应的torch的gpu版本whl来进行安装。使用pip安装…

Linux内核中的链表(list_head)使用分析

【摘要】本文分析了linux内核中的list_head数据结构的底层实现及其相关的各种调用源码&#xff0c;有助于理解内核中链表对象的使用。 二、内核中的队列/链表对象 在内核中存在4种不同类型的列表数据结构&#xff1a; singly-linked listssingly-linked tail queuesdoubly-lin…

SSM框架学习-bean生命周期理解

Spring启动&#xff0c;查找并加载需要被Spring管理的Bean&#xff0c;进行Bean的实例化&#xff08;反射机制&#xff09;&#xff1b;利用依赖注入完成 Bean 中所有属性值的配置注入&#xff1b; 第一类Aware接口&#xff1a; 如果 Bean 实现了 BeanNameAware 接口的话&#…

Yolov8改进---注意力机制:CoTAttention,效果秒杀CBAM、SE

1.CoTAttention 论文:https://arxiv.org/pdf/2107.12292.pdf CoTAttention网络是一种用于多模态场景下的视觉问答(Visual Question Answering,VQA)任务的神经网络模型。它是在经典的注意力机制(Attention Mechanism)上进行了改进,能够自适应地对不同的视觉和语言输入进…

day28_mysql

今日内容 零、 复习昨日 一、函数[了解,会用] 二、事务[重点,理解,面试] 三、索引[重点,理解,面试] 四、存储引擎 五、数据库范式 六、其他 零、 复习昨日 见晨考 一、函数 字符串函数数学函数日期函数日期-字符串转换函数流程函数 1.1 字符串函数 函数解释CHARSET(str)返回字…

一个简单的watch以及ESModule导入和解构的区别

背景 最近写了个很有意思的方法&#xff0c;感觉还蛮不错的就分享一下。起先是我在写calss组件的时候遇到一个问题&#xff0c;我需要监听一个导入的值&#xff0c;导入的值最开始是undefined&#xff0c;经过异步操作以后会得到一个新的值&#xff0c;而我需要在这个class组件…

[echarts] legend icon 自定义的几种方式

echarts 官方配置项 地址 一、默认 图例项的 icon circle, rect, roundRect, triangle, diamond, pin, arrow, none legend: {top: 5%,left: center,itemWidth: 20,itemHeight: 20,data: [{icon: circle, name: 搜索引擎},{icon: rect, name: 直接访问},{icon: roundRect, n…

分布式系统---MapReduce实现(Go语言)

一、说明 本次实验是基于MIT-6.824的课程&#xff0c;详情请参见官网主页下载源代码 二、MapReduce原理 2.1 经典的分布式模型 MapReduce是经典的分布式模型。通过Map函数和Reduce函数实现。 分布式计算&#xff0c;就是利用多台机器&#xff0c;完成一个任务。关于分布式…

算法第一天力扣---2651. 计算列车到站时间

1.题目要求&#xff1a; 给你一个正整数 arrivalTime 表示列车正点到站的时间&#xff08;单位&#xff1a;小时&#xff09;&#xff0c;另给你一个正整数 delayedTime 表示列车延误的小时数。 返回列车实际到站的时间。 注意&#xff0c;该问题中的时间采用 24 小时制。 示…

让ChatGPT猜你喜欢——ChatGPT后面的推荐系统

Chat GPT的大热&#xff0c;让人们的视线又一次聚焦于“人工智能”领域。通过与用户持续对话的形式&#xff0c;更加丰富的数据会不断滚动“雪球”&#xff0c;让Chat GPT的回答变得越来越智能&#xff0c;越来越接近用户最想要的答案。ChatGPT能否颠覆当下的推荐系统范式&…

第三章 灰度变换与空间滤波

第三章 灰度变换与空间滤波 3.1背景知识 ​ 空间域指图像平面本身。变换域的图像处理首先把一幅图像变换到变换域&#xff0c;在变换域中进行处理&#xff0c;然后通过反变换把处理结果返回到空间域。空间域处理主要分为灰度变换与空间滤波。 3.1.1 灰度变换和空间滤波基础 …

cmcc_simplerop

1,三连 2&#xff0c;IDA分析 溢出点&#xff1a; 偏移&#xff1a;0x144(错误) 这里动态重新测试了一下偏移&#xff1a; 正确偏移&#xff1a;0x20 3&#xff0c;找ROP 思路&#xff1a; 1、找系统调用号 2、ROPgadget找寄存器 3、写入/bin/sh ROPgadget --binary simpler…