已知一幅图像中的n个点,假设我们希望找到这些点中位于直线上的子集。一种可能的解决方法是,首先找到由每对点确定的所有直线,然后寻找靠近特定直线的那些点的所有子集。这种方法涉及寻找n(n-1)/2~n2条直线,然后将每个点与所有直线执行n(n(n-1))/2~n3次比较。在大多数应用中,这都是一项困难的计算任务。

原理

Hough提出了一种替代方法,通常称为霍夫变换。令(xi,yi)表示xy平面上的一点,并考虑一条直线的斜截式的通用公式yi=axi+b。过点(xi,yi)的直线有无数条,并且对于a和b的不同值,它们都满足公式yi=axi+b。然而,将该个公式写为b=-axi+yi,并考虑ab平面(也称为参数空间),将得到固定点(xi,yi)的单条直线的公式。此外,第二个点(xj,yj)在ab平面也有一条与之相关联的直线,它在ab平面中与(xi,yi)相关的直线在某个点(a',b')相交,其中a'是斜率,b'是包含xy平面中(xi,yi)和(xj,yj)的直线的截距(当然,我们假定这些直线不平行)。事实上,这条直线上的所有点在参数空间中都有相交于点(a',b')的直线。

理论上,我们可以画出对应xy平面中的所有点(xk,yk)的参数空间直线,并且平面中的主要直线可以通过标志参数空间中大量直线相交的那些点来找到。然而,这种方法的一个难点是,当直线趋近于垂直方向时,a(直线的斜率)趋于无穷大。解决这个难点的方法之一是使用极坐标系

水平直线有θ=0°,ρ等于正x截距。类似地,垂直直线有θ=90°,ρ等于正y截距;或者有θ=-90°,ρ等于负y截距。下图b中每条正弦曲线表示过xy平面中某点(xk,yk)的直线族。交点(ρ',θ')对应于图a中过点(xi,yi)和(xj,yj)的直线。

步骤

霍夫变换计算上的优点是可将ρθ参数空间划分为多个累加单元,如上图c所示,其中(ρmin, ρmax)和(θmin, θmax)是期望的参数范围:-90°≤θ≤90°和-D≤ρ≤D,D是图像中对角之间的最大距离。坐标(i,j)处具有累加值A(i,j)的单元对应于与参数空间坐标(ρij)相关联的方格。具体步骤为:

(1)将这些单元设置为零;

(2)对xy平面的每个非背景点(xk,yk),令等于轴上每个允许的细分值,同时用方程ρ=xkcosθ+yksinθ解对应的ρ;

(3)将得到的值四舍五入到轴上最接近的允许单元值。若选择一个θq值后得到解ρ,则令A(p,q)+=1

循环(1)-(3)步,直至遍历完xy平面所有点,此时单元A(i,j)的k值意味着有k个点位于直线xkcosθ+yksinθ=ρ上。ρθ平面的细分数量决定能够这些点共线的精度。这种方法的计算次数与xy平面中非背景点的数量n成线性关系。

示例:下图为101×101像素的图,带有5个白点

#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv; void drawLine(Mat& markImg, int theta, int p) {
Point p1 = Point(int(p / sin(theta * CV_PI / 180)),0);
Point p2 = Point( int((p- (markImg.cols-1)*cos(theta * CV_PI / 180)) / sin(theta * CV_PI / 180)), markImg.cols - 1);
line(markImg, p1, p2, Scalar(0, 255, 0));
} int main() {
int arr[180][142]={0};
Mat src = imread("./9.bmp", 0);
Mat markImg;
cvtColor(src, markImg, COLOR_GRAY2BGR);
for (int i = 0; i < src.rows; i++) {
for (int j = 0; j < src.cols; j++) {
if (src.at<uchar>(i, j) == 255) {
for (int theta = 0; theta < 180; theta++) {
int p = (int)round(i*cos(theta*CV_PI / 180)+j*sin(theta*CV_PI / 180)) ;
arr[theta][p] += 1;
}
}
}
}
for (int i = 0; i < 180; i++) {
for (int j = 0; j < 142; j++) {
if (arr[i][j] > 2)
drawLine(markImg, i, j);
}
}
imshow("src", src);
imshow("dst", markImg);
waitKey(0);
return 0;
}

cv::HoughLinesP

Opencv实现了以下三种霍夫线变换:

1.标准霍夫变换

提供一组参数对(ρij)的积极和来表示检测到的直线,在opencv中通过函数HoughLines实现。

2.多尺度霍夫变换

3.累积概率霍夫变换

执行起来效率更高,输出检测到的直线的端点(x0,y0,x1,y1),在opencv中通过函数HoughLinesP实现。

void HoughLinesP( InputArray image,
OutputArray lines,
double rho, // rho 的步长
double theta, // 角度的步长,单位是度
int threshold, // 阈值
double minLineLength=0, // 线段的最小长度
double maxLineGap=0 ); // 线段之间的最小距离

示例:机场航拍图像找跑道

#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv; int main() {
Mat src = imread("./9.tif", 0);
Mat markImg,gauImg, cannyImg;
cvtColor(src, markImg, COLOR_GRAY2BGR);
GaussianBlur(src, gauImg, Size(5, 5), 0);
Canny(gauImg, cannyImg, 120, 260, 3); // 标准霍夫变换,直线检测
vector<Vec4i> lines;
HoughLinesP(cannyImg, lines, 1, CV_PI / 180.0, 100, 120, 20);
for (int i = 0; i < lines.size(); i++)
{
line(markImg, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3]), Scalar(0, 255, 0), 1, 8, 0);
} imshow("src", src);
imshow("dst", markImg);
waitKey(0);
return 0;
}

  

参考:

1. 冈萨雷斯《数字图像处理(第四版)》Chapter 9(所有图片可在链接中下载)

2. 实战:基于霍夫变换进行线检测

3. 【youcans 的 OpenCV 例程200篇】157. 霍夫变换直线检测

霍夫变换原理及实现(Opencv C++)的更多相关文章

  1. 提取肤色信息原理及操作——opencv

    网上也有很多的资料,讲述怎么提取肤色的,大致有5种方法.这几种方法转载http://blog.csdn.net/augusdi/article/details/8865275 第一种:RGB colo ...

  2. 『OpenCV3』霍夫变换原理及实现

    霍夫变换常用于检测直线特征,经扩展后的霍夫变换也可以检测其他简单的图像结构. 在霍夫变换中我们常用公式 ρ = x*cosθ + y*sinθ 表示直线,其中ρ是圆的半径(也可以理解为原点到直线的距离 ...

  3. OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波

    http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...

  4. OpenCV编程入门目录

    第一部分 快速上手OpenCV 第1 章 邂逅OpenCV 图像处理.计算机视觉与OpenCV OpenCV 概述 起源及发展 应用概述 .2OpenCV 基本架构分析 .3OpenCV3 带来了什么 ...

  5. 基于查表的整数霍夫变换方法实现(matlab)

    暂时先用matlab把算法弄一下,这是基于查表的整数霍夫变换方法实现及解释. 接着再实现FPGA的霍夫变换. 霍夫变换原理和算法这里不多说,可参考以下链接: http://blog.csdn.net/ ...

  6. Python使用opencv

    Python配置opencv 原理 Python调用opencv的原理是:opencv编译出共享库文件,python把这个共享库文件作为一个模块加载并使用. 通俗点就是,编译opencv的时候开启py ...

  7. Python图像处理丨基于OpenCV和像素处理的图像灰度化处理

    摘要:本篇文章讲解图像灰度化处理的知识,结合OpenCV调用cv2.cvtColor()函数实现图像灰度操作,使用像素处理方法对图像进行灰度化处理. 本文分享自华为云社区<[Python图像处理 ...

  8. OpenCV-Python 中文教程

    OpenCV-Python 中文教程 目录 I 走进 OpenCV 关于 OpenCV-Python 教程 在 Windows 上安装 OpenCV-Python 在 Fedora 上安装 OpenC ...

  9. Meanshift filter实现简单图片的卡通化效果

        利用Meanshift filter和canny边缘检测的效果,可以实现简单的图片的卡通化效果.简单的说,就是用Meanshift filter的结果减去canny算法的结果得到卡通化的效果. ...

  10. SURF算法与源码分析、下

    上一篇文章 SURF算法与源码分析.上 中主要分析的是SURF特征点定位的算法原理与相关OpenCV中的源码分析,这篇文章接着上篇文章对已经定位到的SURF特征点进行特征描述.这一步至关重要,这是SU ...

随机推荐

  1. RabbitMQ总体介绍

    历史-从开始到现在 RabbitMQ是一个Erlang开发的AMQP(Advanced Message Queuing Protocol )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求, ...

  2. Kafka 线上性能调优

    Kafka 线上性能调优是一项综合工程,不仅仅是 Kafka 本身,还应该从硬件(存储.网络.CPU)以及操作系统方面来整体考量,首先我们要有一套生产部署方案,基于这套方案再进行调优,这样就有了可靠的 ...

  3. ArcPy自动绘制大量地图并设置地图要素:Python

      本文介绍基于Python语言中ArcPy模块,实现ArcMap自动批量出图,并对地图要素进行自定义批量设置的方法. 1 任务需求   首先,我们来明确一下本文所需实现的需求.   现有通过Pyth ...

  4. DC-1渗透靶场实战速通版

    "感谢您阅读本篇博客!如果您觉得本文对您有所帮助或启发,请不吝点赞和分享给更多的朋友.您的支持是我持续创作的动力,也欢迎留言交流,让我们一起探讨技术,共同成长!谢谢!" 文章为速通 ...

  5. 力扣682(java)-棒球比赛(简单)

    题目: 你现在是一场采用特殊赛制棒球比赛的记录员.这场比赛由若干回合组成,过去几回合的得分可能会影响以后几回合的得分. 比赛开始时,记录是空白的.你会得到一个记录操作的字符串列表 ops,其中 ops ...

  6. 搭建Hadoop环境

    搭建Hadoop环境 一.虚拟机的安装 二. 安装JDK 1.下载jdk wget https://download.java.net/openjdk/jdk8u41/ri/openjdk-8u41- ...

  7. 高德AR驾车导航解决方案

    简介: 高德从2018年首创了车载AR导航后,已经先后在后视镜.智能车盒.前装整车厂.后装车机产品.行车记录仪等众多场景落地应用,搭建了非常完整的AR导航生态. 日前,高德地图最新发布了v10.60新 ...

  8. [GPT] php查询mongo,触发了 operation exceeded time limit

      "operation exceeded time limit"错误通常意味着查询所需的时间超过了MongoDB实例配置的操作超时限制. 这可以是由于查询需要处理大量数据或没有正 ...

  9. GitHub Action 新上线 WPF .NET Core 自动构建模板

    在很土豪的微软免费给大家提供 GitHub 的构建服务器受到了小伙伴们的一堆好评之后,微软最近推出了 WPF 的 .NET Core 版本的模板,可以快速上手 WPF 项目的自动构建,支持自动进行单元 ...

  10. 2019-10-14-云之幻-UWP-视频教程

    title author date CreateTime categories 云之幻 UWP 视频教程 lindexi 2019-10-14 21:8:26 +0800 2019-10-14 21: ...