已知一幅图像中的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. NG 转发配置

    ng的用途就不用说了,反向代理么,都知道,不过以前一直不太理解怎没配,现在终于理解点了 1.下载ng,如图: 2.先解压,解压后的路径不建议有空格和中文,其次配置环境变量,加到系统path 3.启动n ...

  2. python异步正则字符串替换,asyncio异步正则字符串替换re

    自然语言处理经常使用re正则模块进行字符串替换,但是文本数量特别大的时候,需要跑很久,这就需要使用asyncio异步加速处理 import pandas as pd import re import ...

  3. easyx的使用

    本操作集根据B站学习,借鉴: 视频链接:[C/C++/EasyX]学编程,做游戏,小白快速入门图形编程,零基础入门到精通,学习就是这么快乐_哔哩哔哩_bilibili 初始化时要进行的操作: 记得调用 ...

  4. 力扣197(MySQL)-上升的温度(简单)

    题目: 表: Weather 编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 id . 返回结果 不要求顺序 . 查询结果格式如下例. 解题思路: 方法一:使用窗口函数la ...

  5. ModelScope初探:一行代码调用成熟AI模型。

    简介: 如何用一行代码调用成熟AI模型?试试ModelScope,让AI开发者解放生产力! ModelScope是阿里推出的下一代开源的模型即服务共享平台,为泛AI开发者提供灵活.易用.低成本的一站式 ...

  6. 一文详解 Nacos 高可用特性

    简介: 我今天介绍的 Nacos 高可用,是 Nacos 为了提升系统稳定性而采取的一系列手段.Nacos 的高可用不仅仅存在于服务端,同时也存在于客户端,以及一些与可用性相关的功能特性中,这些点组装 ...

  7. WPF 框架开发 调试和开发 XAML 构建过程的 PresentationBuildTasks 方法

    阅读本文,你可以了解如何编写开发和调试 XAML 构建为 Baml 和 g.cs 文件的过程和工具.本文也适合想要了解 WPF 的 XAML 构建过程的开发者阅读,本文提供了可以断点调试 WPF 的 ...

  8. vue首次缓存判断

    在向本地缓存存值前,判断localstory是否已经存在某个属性,没有就正常存,有就替换掉 created(){ if(localStorage.getItem("属性名") != ...

  9. C++ 中 Concept-Model 概念模型

    此文档参考自:https://gracicot.github.io/conceptmodel/2017/09/13/concept-model-part1.html ,觉得很有趣,就翻译过来了 一.C ...

  10. Python——基本输入和输出

    Python提供了基本的输入和输出功能,这些功能通常是通过内置的input()函数(用于输入)和print()函数(用于输出)来实现的.以下是这两个函数的详细描述和示例: 1. print() 函数( ...