OpenCV实现霍夫变换

返回:OpenCV系列文章目录(持续更新中......)

上一篇:OpenCV 如何实现边缘检测器
下一篇 :OpenCV 实现霍夫圆变换

目标

在本教程中,您将学习如何:

  • 使用 OpenCV 函数 HoughLines()和 HoughLinesP()检测图像中的线条。
  • 注:由于输入法问题按Q替代进行角度说明。

理论

注意

下面的解释属于 Bradski 和 Kaehler 的 Learning OpenCV 一书。

Hough 线变换

  1. Hough 线变换是用于检测直线的变换。
  2. 要应用变换,首先需要边缘检测预处理。

它是如何工作的?

  1. 如您所知,图像空间中的一条线可以用两个变量表示。例如:
    1. 笛卡尔坐标系中:参数:(m,b)
    2. 极坐标系中: 参数:(r,Q)

对于 Hough 变换,我们将在 Polar 系统中表示线。因此,直线方程可以写成:

排列项:

  1. 一般来说,对于每个点 \((x_{0}, y_{0})\),我们可以将通过该点的线族定义为:

    这意味着每对 \(r_{\theta},\theta)\) 表示经过 \((x_{0}, y_{0})\) 的每条线。

  2. 如果对于给定的(x0,有),我们绘制穿过它的线族,我们得到一个正弦曲线。例如,对于 (x0=8)和(y0=6,我们得到以下图(在平面plane  Q~r中):

我们只考虑(r<0)和这样的点。

  1. 我们可以对图像中的所有点执行上述相同的操作。如果两个不同点的曲线在平面 Q~r中相交,则表示两个点属于同一条直线。例如,按照上面的例子,再画两个点的图:X1=4,y1=9 和x2=12,y2=3,我们得到:

这三个图在一个点(0.925,9.6)相交,这些坐标是参数(Q,r)或(x0,y0)和(x1,y1)所在的线。

  1. 以上所有内容是什么意思?这意味着通常可以通过查找曲线之间的交点数来检测一条线。相交的曲线越多,意味着该相交所表示的直线具有更多的点。通常,我们可以定义检测一条线所需的最小交叉点数的阈值
  2. 这就是 Hough Line Transform 的作用。它跟踪图像中每个点的曲线之间的交点。如果交点数高于某个阈值,则将其声明为具有交点参数(Q,r0)的线。

标准和概率 Hough 线变换

OpenCV 实现了两种类型的 Hough 线变换:

a. 标准 Hough 变换

  • 它几乎包含我们在上一节中解释的内容。结果,它给你一个夫妻向量 (Q,r0)
  • 在 OpenCV 中,它是使用函数 HoughLines()实现的

b. 概率霍夫线变换

  • 更高效地实现 Hough 线变换。它给出检测到的行的极值(x0,y0,x1,y1)
  • 在 OpenCV 中,它是使用函数 HoughLinesP()实现的

这个程序是做什么的?

  • 加载图像
  • 应用标准 Hough 线变换概率线变换
  • 在三个窗口中显示原始图像和检测到的线条。

C++代码

们将要解释的示例代码可以从这里下载。可以在此处找到一个稍微花哨的版本(它显示了 Hough 标准和概率,带有用于更改阈值的跟踪栏)。

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
 
using namespace cv;
using namespace std;
 
int main(int argc, char** argv)
{
 // Declare the output variables
 Mat dst, cdst, cdstP;
 
 const char* default_file = "sudoku.png";
 const char* filename = argc >=2 ? argv[1] : default_file;
 
 // Loads an image
 Mat src = imread( samples::findFile( filename ), IMREAD_GRAYSCALE );
 
 // Check if image is loaded fine
 if(src.empty()){
 printf(" Error opening image\n");
 printf(" Program Arguments: [image_name -- default %s] \n", default_file);
 return -1;
 }
 
 // Edge detection
 Canny(src, dst, 50, 200, 3);
 
 // Copy edges to the images that will display the results in BGR
 cvtColor(dst, cdst, COLOR_GRAY2BGR);
 cdstP = cdst.clone();
 
 // Standard Hough Line Transform
 vector<Vec2f> lines; // will hold the results of the detection
 HoughLines(dst, lines, 1, CV_PI/180, 150, 0, 0 ); // runs the actual detection
 // Draw the lines
 for( size_t i = 0; i < lines.size(); i++ )
 {
 float rho = lines[i][0], theta = lines[i][1];
 Point pt1, pt2;
 double a = cos(theta), b = sin(theta);
 double x0 = a*rho, y0 = b*rho;
 pt1.x = cvRound(x0 + 1000*(-b));
 pt1.y = cvRound(y0 + 1000*(a));
 pt2.x = cvRound(x0 - 1000*(-b));
 pt2.y = cvRound(y0 - 1000*(a));
 line( cdst, pt1, pt2, Scalar(0,0,255), 3, LINE_AA);
 }
 
 // Probabilistic Line Transform
 vector<Vec4i> linesP; // will hold the results of the detection
 HoughLinesP(dst, linesP, 1, CV_PI/180, 50, 50, 10 ); // runs the actual detection
 // Draw the lines
 for( size_t i = 0; i < linesP.size(); i++ )
 {
 Vec4i l = linesP[i];
 line( cdstP, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
 }
 
 // Show results
 imshow("Source", src);
 imshow("Detected Lines (in red) - Standard Hough Line Transform", cdst);
 imshow("Detected Lines (in red) - Probabilistic Line Transform", cdstP);
 
 // Wait and Exit
 waitKey();
 return 0;
}

代码片段解释


加载图像:

 const char* default_file = "sudoku.png";
 const char* filename = argc >=2 ? argv[1] : default_file;
 
 // Loads an image
 Mat src = imread( samples::findFile( filename ), IMREAD_GRAYSCALE );
 
 // Check if image is loaded fine
 if(src.empty()){
 printf(" Error opening image\n");
 printf(" Program Arguments: [image_name -- default %s] \n", default_file);
 return -1;
 }

 使用 Canny 检测器检测图像的边缘:

 // Edge detection
 Canny(src, dst, 50, 200, 3);

现在我们将应用 Hough 线变换。我们将解释如何使用可用于此目的的两个 OpenCV 函数。

标准 Hough 线变换:

首先,应用转换:

 // Standard Hough Line Transform
 vector<Vec2f> lines; // will hold the results of the detection
 HoughLines(dst, lines, 1, CV_PI/180, 150, 0, 0 ); // runs the actual detection
  • 使用以下参数:
    • dst:边缘检测器的输出。它应该是灰度图像(尽管实际上它是二进制图像)
    • lines:将存储检测到的线的参数的向量(r,Q)
    • rho :参数的分辨率,单位为r像素。我们使用 1 个像素。
    • theta:参数的分辨率,单位为Q弧度。我们使用 1 度 (CV_PI/180)
    • threshold:要“检测*”一条线的最小交叉点数
    • srn 和 stn:默认参数为零。有关详细信息,请查看 OpenCV 参考。

然后通过绘制线条来显示结果。

 // Draw the lines
 for( size_t i = 0; i < lines.size(); i++ )
 {
 float rho = lines[i][0], theta = lines[i][1];
 Point pt1, pt2;
 double a = cos(theta), b = sin(theta);
 double x0 = a*rho, y0 = b*rho;
 pt1.x = cvRound(x0 + 1000*(-b));
 pt1.y = cvRound(y0 + 1000*(a));
 pt2.x = cvRound(x0 - 1000*(-b));
 pt2.y = cvRound(y0 - 1000*(a));
 line( cdst, pt1, pt2, Scalar(0,0,255), 3, LINE_AA);
 }

概率 Hough 线变换

首先,应用转换:

 // Probabilistic Line Transform
 vector<Vec4i> linesP; // will hold the results of the detection
 HoughLinesP(dst, linesP, 1, CV_PI/180, 50, 50, 10 ); // runs the actual detection
  • 带有参数:
    • dst:边缘检测器的输出。它应该是灰度图像(尽管实际上它是二进制图像)
    • lines:将存储检测到的线的参数的向量(xstart,ystart,xend,yend)
    • rho :参数的分辨率,单位为r像素。我们使用 1 个像素。
    • theta:参数的分辨率,单位为Q弧度。我们使用 1 度 (CV_PI/180)
    • threshold:要“检测*”一条线的最小交叉点数
    • minLineLength:可以形成一条线的最小点数。小于此点数的线将被忽略。
    • maxLineGap:在同一条直线上要考虑的两点之间的最大间隙。

然后通过绘制线条来显示结果。

 // Draw the lines
 for( size_t i = 0; i < linesP.size(); i++ )
 {
 Vec4i l = linesP[i];
 line( cdstP, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
 }

显示原始图像和检测到的线:

 // Show results
 imshow("Source", src);
 imshow("Detected Lines (in red) - Standard Hough Line Transform", cdst);
 imshow("Detected Lines (in red) - Probabilistic Line Transform", cdstP);

等到用户退出程序

 // Wait and Exit
 waitKey();
 return 0;

结果

注意

下面的结果是使用我们在代码部分提到的稍微花哨的版本获得的。它仍然实现与上述相同的内容,只是为阈值添加了跟踪栏。使用输入图像,例如数独图像。我们通过使用标准 Hough 线变换得到以下结果:

通过使用概率 Hough 线变换:

您可能会发现,在更改阈值时,检测到的行数会发生变化。解释是显而易见的:如果建立更高的阈值,则检测到的行将减少(因为您将需要更多的点来声明检测到的行)。 

参考文献:

1、《Hough Line Transform》-----Ana Huamán

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

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

相关文章

YASKAWA安川机器人DX100轴板维修故障细节分享

随着科技的日新月异&#xff0c;机器人在工业生产中扮演的角色愈发重要。而作为机器人的“大脑”——电路板&#xff0c;其稳定运作对整个系统的可靠性至关重要。面对可能出现的YASKAWA安川机器人DX100轴板故障&#xff0c;如何快速、准确地诊断问题并予以解决呢&#xff1f;下…

数据结构之常见排序算法

目录 一、排序中的概念 二、常见排序算法--升序 1、插入排序 &#xff08;1&#xff09;直接插入排序 &#xff08;2&#xff09;希尔排序 2、选择排序 &#xff08;1&#xff09;单指针选择排序 &#xff08;2&#xff09;双指针选择排序 &#xff08;3&#xff09;堆…

日志集中审计系列(5)--- LogAuditor接收USG设备日志

日志集中审计系列(5)--- LogAuditor接收USG设备日志 前言拓扑图设备选型组网需求配置思路操作步骤结果验证前言 近期有读者留言:“因华为数通模拟器仅能支持USG6000V的防火墙,无法支持别的安全产品,导致很多网络安全的方案和产品功能无法模拟练习,是否有真机操作的实验或…

文旅强势复苏 苏州金龙新V系客车助力湖北“文旅升级”

2024年4月24日&#xff0c;苏州金龙携多款新V系客车登陆素有九省通衢之称的湖北武汉&#xff0c;在当地文旅行业&#xff0c;刮起一场客运品质升级之风。作为“五一”出行热门城市、自然人文资源丰富的旅游大省&#xff0c;武汉乃至湖北旅游市场堪称客运产品的试金石&#xff0…

赵磊老师:共同的利益和文化理念契合才是两项留人的重要法宝

优秀人才对企业的发展与影响毋庸置疑&#xff0c;优秀人才的流失往往直接带来业绩的损失&#xff0c;甚至导致企业从此一蹶不振&#xff0c;当然一个组织也需要大量的执行者&#xff0c;通过执行者的辛劳工作&#xff0c;使其为客户创造价值的想法变成产品&#xff0c;变成产生…

shellshock题解思路分享

shellshock 考查bash远程任意代码执行漏洞。 可以看到含有bash文件&#xff0c;使用以下命令测试bash是否受shellshock影响 env x() { :;}; echo test ./bash -c:test受影响&#xff0c;执行bash远程任意代码执行漏洞 env x() { :;}; /bin/cat flag ./shellshock具体可以看…

海南封关怎么看?win战略会任志雄解析

今年海南自由贸易港建设也进入了新阶段:将在2025年年底前适时启动全岛封关运作,封关后的海南将以全新姿态迎接更广泛的发展机遇。 封关在即,企业有何感受?还有哪些准备工作?封关后的海南将呈现怎样的状态?近日,红星资本局记者深入实地了解海南自贸港如何成型起势。 利好当…

劳保工具佩戴监测识别摄像机

随着工业生产技术的不断进步和劳动保护意识的提高&#xff0c;劳保工具的佩戴已成为维护工人安全健康的重要环节。为了更好地监测和识别工人是否正确佩戴劳保工具&#xff0c;以及工作场所是否存在安全隐患&#xff0c;智能劳保工具佩戴监测识别摄像机应运而生。这种摄像机结合…

嵌入式Linux driver开发实操(十八):Linux音频ALSA开发

应用程序程序员应该使用库API,而不是内核API。alsa库提供了内核API 100%的功能,但增加了可用性方面的主要改进,使应用程序代码更简单、更美观。未来的修复程序或兼容性代码可能会放在库代码中,而不是放在内核驱动程序中。 使用ALSA API和libasound进行简单的声音播放: /*…

遥控车模的电机控制器

一、项目简介 基于CH32V103单片机结合RTT开发一套无刷电机无感矢量控制器&#xff0c;使用无感矢量控制无刷电机具有噪音小、控制线性度好、电机效率高等优点。使用三相全桥电路将直流电转换为交流电驱动无刷电机&#xff0c;利用串联电阻和差分采样电路采集UV两相的电流信号。…

智慧码头港口:施工作业安全生产AI视频监管与风险预警平台方案

一、建设思路 随着全球贸易的快速发展&#xff0c;港口作为连接海洋与内陆的关键节点&#xff0c;其运营效率和安全性越来越受到人们的关注。为了提升港口的运营效率和安全性&#xff0c;智慧港口视频智能监控系统的建设显得尤为重要。 1&#xff09;系统架构设计 系统应该采…

[计算机效率] 网站推荐:其它类(找台词、表格转换)

4.9 其它 4.9.1 找台词 找台词网&#xff08;http://www.zhaotaici.cn/&#xff09;是一个专为电影电视剧爱好者打造的台词搜索引擎网站。它的核心功能是帮助用户快速查找特定电影或电视剧中的台词&#xff0c;并提供详细的上下文信息。 在使用找台词网时&#xff0c;用户只需…

docker的默认路径存储不足

docker的默认路径存储不足 添加磁盘 [rootlocalhost ~]# fdisk -l磁盘 /dev/sda&#xff1a;42.9 GB, 42949672960 字节&#xff0c;83886080 个扇区 Units 扇区 of 1 * 512 512 bytes 扇区大小(逻辑/物理)&#xff1a;512 字节 / 512 字节 I/O 大小(最小/最佳)&#xff1a…

一网打尽 Rust 语法

❝ 悲观者永远正确&#xff0c;而乐观者永远前行 ❞ 大家好&#xff0c;我是「柒八九」。一个「专注于前端开发技术/Rust及AI应用知识分享」的Coder 前言 在之前的Rust学习专栏中&#xff0c;由于受制与文章的脉络&#xff0c;我们只能从概念到使用场景进行事无巨细的解释。相当…

伪分布Hadoop下安装Hive

一、下载并安装Mysql &#xff08;1&#xff09;下载mysql安装包&#xff08;mysql-8.0.26-1.el7.x86_64.rpm-bundle.tar&#xff09; 下载官网&#xff1a;MySQL :: Download MySQL Community Server (Archived Versions)https://downloads.mysql.com/archives/community/ &…

【大模型书籍】从零开始大模型开发与微调:基于PyTorch与ChatGLM(附PDF)

哈喽各位&#xff0c;今天又来给大家分享大模型学习书籍了&#xff0c;今天是这本<从零开始大模型开发与微调&#xff1a;基于PyTorch与ChatGLM 书籍PDF分享>&#xff0c;大模型是深度学习自然语言处理皇冠上的一颗明珠&#xff0c;也是当前AI和NLP研究与产业中最重要的方…

解决IDEA中Tomcat控制台乱码问题(包括sout输出乱码)

文章目录 前言一、控制台直接输出乱码二、sout输出内容在控制台显示乱码 前言 今天在使用Tomcat的时候发现控制台输入出现了乱码问题&#xff0c;其实之前就出现过一次&#xff0c;解决了&#xff0c;但是新创建一个项目后又会出现sout的内容在控制台输出的乱码问题&#xff0…

【论文复现|智能算法改进】融合正余弦策略的算术优化算法

目录 1.算法原理2.改进策略3.结果展示4.参考文献 1.算法原理 【智能算法】算术优化算法&#xff08;AOA&#xff09;原理及实现 2.改进策略 基于适应度的自适应 MOA 策略 正弦余弦策略 3.结果展示 4.参考文献 [1] 黄学雨,罗华.融合正余弦策略的算术优化算法[J].计算机工…

分布式版本控制工具 Git 的使用方式

文章目录 Git简介下载安装基本使用起始配置Git 的三个区域基本操作流程查看仓库状态删除&#xff08;撤销暂存区&#xff09;差异对比查看版本日志版本回退修改提交日志分支概念&#xff1a;创建分支与切换分支合并分支&#xff08;快速合并&#xff09;合并分支&#xff08;提…

Linux的FTP服务

目录 1.什么是FTP服务&#xff1f; 2.FTP的工作原理和流程 1 主动模式 2 被动模式 3.搭建和配置FTP服务 1 下载服务包、备份配置文件 2 修改配置文件​编辑 3 匿名访问测试 4 设置黑白命令 1.什么是FTP服务&#xff1f; FTP&#xff08;file Transfer Protocol&#…