已知一幅图像中的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. sql 语句系列(月份的第一个星期的星期一和最后一个星期的星期一)[八百章之第二十一章]

    mysql select y.first_monday,CASE MONTH(ADDDATE(y.first_monday,28)) when mth then ADDDATE(y.first_mon ...

  2. JavaSE开发基础--包机制&JavaDoc&Scanner&循环结构&方法&数组

    包机制 如果文件在包中需要 在文件首行添加 package 地址 package pkg1.pkg2.pkg3 import package1 JavaDoc /** * @author作者名 * @ ...

  3. lattice的ipexpress异常,解决办法

    最近ip服务器可能会遇到问题,建议客户把更新检查关掉.我们有对应的IP下载链接. https://www.latticesemi.com/ispupdate/ipexpress/ https://ra ...

  4. 高云GOWIN下载出现No devices found咋办

    在使用GOWIN下载器下载会出现该类问题 No devices found错误. 原因如下: A . Windows10 系统会出现下载器通道顺序错误,所以要确保在 A 通道上. B.有一些 USB ...

  5. ASP.NET MVC5.0 筑基到炼气大圆满一篇就搞定

    一.ASP.NET MVC 过滤器 ASP.NET MVC框架支持四种不同类型的过滤器: 授权过滤器 - 实现IAuthorizationFilter属性. 动作过滤器 - 实现IActionFilt ...

  6. 力扣1668(java&python)-最大重复子字符串(简单)

    题目: 给你一个字符串 sequence ,如果字符串 word 连续重复 k 次形成的字符串是 sequence 的一个子字符串,那么单词 word 的 重复值为 k .单词 word 的 最大重复 ...

  7. 力扣172(java)-阶乘后的零(中等)

    题目: 给定一个整数 n ,返回 n! 结果中尾随零的数量. 提示 n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1 示例 1: 输入:n = 3输出:0解释: ...

  8. 阿里云荣获可信云容器安全能力先进级认证, ACK/ACR为企业级安全护航

    阿里云关注企业级用户的Kubernetes生产落地痛点,结合企业生产环境的大量实践,全面帮助企业真正落地云原生架构.安全侧问题,是众多大中型或金融领域企业的核心关注点. 端到端云原生安全架构 早在20 ...

  9. 万物有灵,萌物Luka机器人如何让故事点缀童年

    ​简介:未来的十年将会是AI影响教育的十年.物灵科技正是基于在AI+教育未来趋势前瞻性的把握,不断将人格化属性和关系式交互体验赋予更多人工智能产品,启发儿童语言培养阶段的学习兴趣.依托阿里云技术,物灵 ...

  10. 超详攻略!Databricks 数据洞察 - 企业级全托管 Spark 大数据分析平台及案例分析

    简介: 5分钟读懂 Databricks 数据洞察 ~ 更多详细信息可登录 Databricks 数据洞察 产品链接:https://www.aliyun.com/product/bigdata/sp ...