霍夫变换原理及实现(Opencv C++)
已知一幅图像中的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)的单元对应于与参数空间坐标(ρi,θj)相关联的方格。具体步骤为:
(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.标准霍夫变换
提供一组参数对(ρi,θj)的积极和来表示检测到的直线,在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(所有图片可在链接中下载)
3. 【youcans 的 OpenCV 例程200篇】157. 霍夫变换直线检测
霍夫变换原理及实现(Opencv C++)的更多相关文章
- 提取肤色信息原理及操作——opencv
网上也有很多的资料,讲述怎么提取肤色的,大致有5种方法.这几种方法转载http://blog.csdn.net/augusdi/article/details/8865275 第一种:RGB colo ...
- 『OpenCV3』霍夫变换原理及实现
霍夫变换常用于检测直线特征,经扩展后的霍夫变换也可以检测其他简单的图像结构. 在霍夫变换中我们常用公式 ρ = x*cosθ + y*sinθ 表示直线,其中ρ是圆的半径(也可以理解为原点到直线的距离 ...
- OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波
http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...
- OpenCV编程入门目录
第一部分 快速上手OpenCV 第1 章 邂逅OpenCV 图像处理.计算机视觉与OpenCV OpenCV 概述 起源及发展 应用概述 .2OpenCV 基本架构分析 .3OpenCV3 带来了什么 ...
- 基于查表的整数霍夫变换方法实现(matlab)
暂时先用matlab把算法弄一下,这是基于查表的整数霍夫变换方法实现及解释. 接着再实现FPGA的霍夫变换. 霍夫变换原理和算法这里不多说,可参考以下链接: http://blog.csdn.net/ ...
- Python使用opencv
Python配置opencv 原理 Python调用opencv的原理是:opencv编译出共享库文件,python把这个共享库文件作为一个模块加载并使用. 通俗点就是,编译opencv的时候开启py ...
- Python图像处理丨基于OpenCV和像素处理的图像灰度化处理
摘要:本篇文章讲解图像灰度化处理的知识,结合OpenCV调用cv2.cvtColor()函数实现图像灰度操作,使用像素处理方法对图像进行灰度化处理. 本文分享自华为云社区<[Python图像处理 ...
- OpenCV-Python 中文教程
OpenCV-Python 中文教程 目录 I 走进 OpenCV 关于 OpenCV-Python 教程 在 Windows 上安装 OpenCV-Python 在 Fedora 上安装 OpenC ...
- Meanshift filter实现简单图片的卡通化效果
利用Meanshift filter和canny边缘检测的效果,可以实现简单的图片的卡通化效果.简单的说,就是用Meanshift filter的结果减去canny算法的结果得到卡通化的效果. ...
- SURF算法与源码分析、下
上一篇文章 SURF算法与源码分析.上 中主要分析的是SURF特征点定位的算法原理与相关OpenCV中的源码分析,这篇文章接着上篇文章对已经定位到的SURF特征点进行特征描述.这一步至关重要,这是SU ...
随机推荐
- lin-view-ui Vue 2.0 组件库
lin-view-ui 是一款基于 Vue.js 2.0 的前端 UI 组件库,主要集成了平时在开发中使用到的 UI 组件. 特性 基于 Vue 开发的 UI 组件 使用 npm + webpack ...
- iLogtail社区版使用入门 - 采集MySQL Binlog
简介: MySQL Binlog记录了MySQL的变更日志,业界也有一些方案来同步Binlog的数据,如Canal.MaxWell.DTS等.不同的工具可以实现不同的目标,iLogtail也提供了便捷 ...
- MySQL统计信息不准导致的性能问题
简介: 统计信息不准导致错误的执行计划,引发性能问题 表的统计信息错误导致优化器选择错误的执行计划. 一个客户的性能优化案例: 没有修改数据库实例的任何配置参数以及业务代码没有变更的情况下,一条 sq ...
- 阿里云日志服务SLS,打造云原生时代智能运维
2021年10月21日,阿里云针对企业运维难题,在云栖大会为大家带来了一场<智能运维论坛>的主题演讲.在会上,阿里云资深技术专家.日志服务技术负责人简志提出"云原生时代,企业业 ...
- [FAQ] 英文字母输入时变成了胖体
如下,在输入法上右键,切换为 "半角" 即可. Link:https://www.cnblogs.com/farwish/p/17513598.html
- [Go] 注意 go build -o <output> 选项的准确含义
-o <output> 选项强制执行把构建的可执行文件写入到目标文件或者目标目录中. 如果 output 是已存在的目录,那么所有构建好的文件都将写入到该目录中. 注意:如果目录不存在的话 ...
- WPF 简单判断主线程界面是否卡顿的方法
本文来告诉大家如何使用简单的代码判断当前的软件的 UI 线程或界面是否卡顿 在后台线程调用如下代码即可用来判断是否卡顿 private static async Task<bool> Ch ...
- 2019-8-31-C#-转换类型和字符串
title author date CreateTime categories C# 转换类型和字符串 lindexi 2019-08-31 16:55:58 +0800 2018-2-13 17:2 ...
- 《Effective C++》第三版-1. 让自己习惯C++(Accustoming Yourself to C++)
目录 条款01:视C++为一个语言联邦(View C++ as a federation of languages) 条款02:尽量以const.enum.inline替换#define(Prefer ...
- 51k+ Star!动画图解、一键运行的数据结构与算法教程!
大家好,我是 Java陈序员. 我们都知道,<数据结构与算法> -- 是程序员的必修课. 无论是使用什么编程语音,亦或者是前后端开发,都需要修好<数据结构与算法>这门课! 在各 ...