霍夫变换原理及实现(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 ...
随机推荐
- sql 语句系列(字符串之裂开)[八百章之第十三章]
创建分割列表 一张表: 先查询出来的效果是这样的: mysql: select emp_copy.deptno,GROUP_CONCAT(emp_copy.emps SEPARATOR ',') fr ...
- redis 简单整理——redis 的有序集合基本结构和命令[六]
前言 简单介绍一下redis的有序集合的基本结构和命令. 正文 有序集合相对于哈希.列表.集合来说会有一点点陌生,但既然叫有序 集合,那么它和集合必然有着联系,它保留了集合不能有重复成员的特性, 但不 ...
- 力扣166(java)-分数到小数(中等)
题目: 给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以 字符串形式返回小数 . 如果小数部分为循环小数,则将循环的部分括在括号内. 如果存在多个答案,只需返回 ...
- 深入理解高级加密标准(Advanced Encryption Standard)
title: 深入理解高级加密标准(Advanced Encryption Standard) date: 2024/4/23 20:04:36 updated: 2024/4/23 20:04:36 ...
- 几种常见的MySQL/PolarDB-MySQL回收表空间方法对比
简介: 当我们频繁的删除表中的数据后,碎片就会变多,有经验的DBA就会回收表空间,回收表空间有好几种方式,我们要选择哪一种呢? 背景 为什么需要回收表空间?任何一个存储或您购买的实例规格都有容量限制, ...
- EasyNLP带你玩转CLIP图文检索
简介: 本文简要介绍CLIP的技术解读,以及如何在EasyNLP框架中玩转CLIP模型. 作者:熊兮.章捷.岑鸣.临在 导读 随着自媒体的不断发展,多种模态数据例如图像.文本.语音.视频等不断增长,创 ...
- 各位 PHPer,Serverless 正当时
简介:PHP 作为一个开发群体的很大的语言其应用范围相当广泛,Serverless 的理念和 PHP 语言的理念都是让开发者最大精力集中在自己的业务价值.那么 PHP 遇见 Serverless 会 ...
- 双引擎驱动Quick BI十亿数据0.3秒分析,首屏展示时间缩短30%
简介:在规划中,Quick BI制定了产品竞争力建设的三大方向,包括Quick(快)能力.移动端能力和集成能力.针对其中的产品"报表查看打开慢""报表开发数据同步慢&q ...
- 模仿Spring实现一个类管理容器
简介: 项目的初衷是独立作出一个成熟的有特色的IOC容器,但由于过程参考Spring太多,而且也无法作出太多改进,于是目的变为以此项目作为理解Spring的一个跳板,与网上的一些模仿Spring的框 ...
- [Caddy2] URL访问路径的重定向和重写规则 (redir/rewrite 指令)
当我们在规划网站路径时,为了保留搜索引擎收录 避免404的同时做到升级,常用到重定向跳转和URL重写. 重定向(redirect) 在 Caddy 中为 redir 指令. https://caddy ...