一、霍夫线变换 
霍夫线变换是OpenCv中一种寻找直线的方法,输入图像为边缘二值图。

原理:

一条直线在图像二维空间可由两个变量表示, 例如: 
1、在 笛卡尔坐标系: 可由参数: (m,b) 斜率和截距表示。 
2、在 极坐标系: 可由参数: 极径和极角表示。 
 
对于霍夫变换,我们将用 极坐标系 来表示直线。 因此,直线的表达式可为: 
化简后得:

一般来说对于点 , 我们可以将通过这个点的一族直线统一定义为: 
 
这就意味着每一对 代表一条通过点  的直线。

如果对于一个给定点 我们在极坐标对极径极角平面绘出所有通过它的直线,将得到一条正弦曲线。例如,对于给定点  and 我们可以绘出下图 (在平面 \theta - r): 
 
只绘出满足下列条件的点 and 

我们可以对图像中所有的点进行上述操作. 如果两个不同点进行上述操作后得到的曲线在平面 - r 相交, 这就意味着它们通过同一条直线. 例如, 接上面的例子我们继续对点:  和点  绘图,得到下图: 
 
这三条曲线在  - r 平面相交于点 (0.925, 9.6), 坐标表示的是参数对 (, r) 或者是说点 , 点  和点  组成的平面内的的直线。

那么以上的材料要说明什么呢? 这意味着一般来说, 一条直线能够通过在平面 - r 寻找交于一点的曲线数量来 检测. 越多曲线交于一点也就意味着这个交点表示的直线由更多的点组成. 一般来说我们可以通过设置直线上点的 阈值 来定义多少条曲线交于一点我们才认为 检测 到了一条直线.

这就是霍夫线变换要做的. 它追踪图像中每个点对应曲线间的交点. 如果交于一点的曲线的数量超过了 阈值, 那么可以认为这个交点所代表的参数对 在原图像中为一条直线。

在OpenCV中霍夫线变换分为两种: 
1、标准霍夫线变换 
原理在上面的部分已经说明了. 它能给我们提供一组参数对  的集合来表示检测到的直线 
在OpenCV 中通过函数 HoughLines 来实现 
2、统计概率霍夫线变换 
这是执行起来效率更高的霍夫线变换. 它输出检测到的直线的端点  
在OpenCV 中它通过函数 HoughLinesP 来实现

实现:

1、标准霍夫线变换

函数为:

void HoughLines( InputArray image, OutputArray lines,
double rho, double theta, int threshold,
double srn = 0, double stn = 0,
double min_theta = 0, double max_theta = CV_PI );

第一个参数为输入图像,应该为灰度图,

第二个参数为输出的检测到的直线的容器 
第三个参数为以参数极径单位的分辨率 
第四个是以弧度为单位的分辨率 
第五个为一条直线所需最少的的曲线交点

int main()
{
RNG rng(12345);
Mat a = imread("1RT05508-0.jpg");
imshow("原图", a);
cvtColor(a, a, CV_RGB2GRAY); //转为灰度图
Canny(a, a, 100, 300, 3); //进行边缘检测
Mat bbb;
cvtColor(a, bbb, CV_GRAY2BGR);
vector<Vec2f> lines;
HoughLines(a, lines, 1, CV_PI / 180, 100); //检测
for (size_t i = 0; i < lines.size(); i++) //开始划线
{
float rho = lines[i][0], theta = lines[i][1];
Point pt1, pt2;
double a = cos(theta), b = sin(theta);
double x0 = a*rho, y0 = b*rho;
pt1.x = cvRound(x0 + 1000 * (-b));
pt1.y = cvRound(y0 + 1000 * (a));
pt2.x = cvRound(x0 - 1000 * (-b));
pt2.y = cvRound(y0 - 1000 * (a));
line(bbb, pt1, pt2, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 3, CV_AA); //实现随机颜色
}
imshow("效果图", bbb);
cvWaitKey(10000); }

效果图: 
 
各参数的作用和标准霍夫变换相同

2、统计概率霍夫线变换 
函数为:

void HoughLinesP( InputArray image, OutputArray lines,
double rho, double theta, int threshold,
double minLineLength = 0, double maxLineGap = 0 );
int main()
{
RNG rng(12345);
Mat a = imread("1RT05508-0.jpg");
imshow("原图", a);
cvtColor(a, a, CV_RGB2GRAY); //转为灰度图
Canny(a, a, 100, 300, 3); //边缘检测
Mat bbb;
cvtColor(a, bbb, CV_GRAY2BGR);
vector<Vec4i> lines;
HoughLinesP(a, lines, 1, CV_PI / 180, 50, 50, 10); //检测
for (size_t i = 0; i < lines.size(); i++) //划线
{
Vec4i l = lines[i];
line(bbb, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 3, CV_AA); //用的是随机颜色
}
imshow("效果图", bbb);
cvWaitKey(10000); }

效果图: 

二、霍夫圆变换 
是OpenCv中用于检测圆的一种方法,使用 HoughCircles函数。 
原理: 
霍夫圆变换的基本原理和霍夫线变换类似, 只是点对应的二维极径极角空间被三维的圆心点x, y还有半径r空间取代。

对直线来说, 一条直线能由参数极径极角 (r, ) 表示. 而对圆来说, 我们需要三个参数来表示一个圆, 如上文所说现在原图像的边缘图像的任意点对应的经过这个点的所有可能圆是在三维空间有下面这三个参数来表示了,其对应一条三维空间的曲线. 那么与二维的霍夫线变换同样的道理, 对于多个边缘点越多这些点对应的三维空间曲线交于一点那么他们经过的共同圆上的点就越多,类似的我们也就可以用同样的阈值的方法来判断一个圆是否被检测到, 这就是标准霍夫圆变换的原理, 但也正是在三维空间的计算量大大增加的原因, 标准霍夫圆变化很难被应用到实际中:

这里的 表示圆心的位置 (下图中的绿点) 而 r 表示半径, 这样我们就能唯一的定义一个圆了。

实现:

函数为:

void HoughCircles( InputArray image, OutputArray circles,
int method, double dp, double minDist,
double param1 = 100, double param2 = 100,
int minRadius = 0, int maxRadius = 0 );

src_gray: 输入图像 (灰度图) 
circles: 存储下面三个参数: x_{c}, y_{c}, r 集合的容器来表示每个检测到的圆. 
CV_HOUGH_GRADIENT: 指定检测方法. 现在OpenCV中只有霍夫梯度法 
dp = 1: 累加器图像的反比分辨率 
min_dist = src_gray.rows/8: 检测到圆心之间的最小距离 
param_1 = 200: Canny边缘函数的高阈值 
param_2 = 100: 圆心检测阈值. 
min_radius = 0: 能检测到的最小圆半径, 默认为0. 
max_radius = 0: 能检测到的最大圆半径, 默认为0

int main()
{
RNG rng(12345);
Mat a = imread("8907540_150847495169_2.jpg");
a.resize(350);
imshow("原图", a);
cvtColor(a, a, CV_RGB2GRAY); //转为灰度图
vector<Vec3f> circles;
HoughCircles(a, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0); //检测
cvtColor(a, a, CV_GRAY2BGR);
for (size_t i = 0; i < circles.size(); i++) //开始画圆
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]); //绘制圆心
circle(a, center, 3, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), -1, 8, 0); //绘制圆
circle(a, center, radius, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 3, 8, 0); //依旧是随机颜色
}
imshow("效果图", a);
cvWaitKey(10000); }

效果图: 

OpenCV中的霍夫线变换和霍夫圆变换的更多相关文章

  1. 【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑

    http://blog.csdn.net/poem_qianmo/article/details/26977557 本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog ...

  2. 学习 opencv---(13)opencv霍夫变换:霍夫线变换,霍夫圆变换

    在本篇文章中,我们将一起学习opencv中霍夫变换相关的知识点,以及了解opencv中实现霍夫变换的HoughLines,HoughLinesP函数的使用方法,实现霍夫圆变换的HoughCircles ...

  3. 【OpenCV新手教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/26977557 作者:毛星云(浅墨) ...

  4. opencv —— HoughLines、HoughLinesP 霍夫线变换原理(标准霍夫线变换、多尺度霍夫线变换、累积概率霍夫线变换)及直线检测

    霍夫线变换的原理 一条直线在图像二维空间可由两个变量表示,有以下两种情况: ① 在笛卡尔坐标系中:可由参数斜率和截距(k,b)表示. ② 在极坐标系中:可由参数极经和极角(r,θ)表示. 对于霍夫线变 ...

  5. python数字图像处理(15):霍夫线变换

    在图片处理中,霍夫变换主要是用来检测图片中的几何形状,包括直线.圆.椭圆等. 在skimage中,霍夫变换是放在tranform模块内,本篇主要讲解霍夫线变换. 对于平面中的一条直线,在笛卡尔坐标系中 ...

  6. 图像变换 - 霍夫线变换(cvHoughLines2)

    霍夫变换是一种在图像中寻找直线.圆及其他简单形状的方法,霍夫线变换是利用Hough变换在二值图像中找到直线. 利用CV_HOUGH_PROBABILISTIC,对应PPHT(累计概率霍夫变换)?这个算 ...

  7. OpenCV-Python 霍夫线变换 | 三十二

    目标 在这一章当中, 我们将了解霍夫变换的概念. 我们将看到如何使用它来检测图像中的线条. 我们将看到以下函数:cv.HoughLines(),cv.HoughLinesP() 理论 如果可以用数学形 ...

  8. OpenCV 霍夫线变换

    #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #i ...

  9. opencv-霍夫直线变换与圆变换

    转自:https://blog.csdn.net/poem_qianmo/article/details/26977557 一.引言 在图像处理和计算机视觉领域中,如何从当前的图像中提取所需要的特征信 ...

随机推荐

  1. H5_0021:判断平台和微信

    1,跳网站: <script>eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c ...

  2. ng-简介

    Angular 是什么 Angular(读音['æŋgjʊlə])是一套用于构建用户界面的 JavaScript 框架.由 Google 开发和维护,主要被用来开发单页面应用程序. 类似于 Vue.j ...

  3. CF1093E Intersection of Permutations [分块 +bitset]

    大家好, 我非常喜欢暴力数据结构, 于是就用分块A了此题 分块题,考虑前缀和 \(b_i\) 表示 bitset 即 \(0\) ~ $i $ 出现过的数字,然后考虑直接暴力复制块然后前缀和,修改也很 ...

  4. 订阅消息---由于微信小程序取消模板消息,限只能开发订阅消息

    订阅消息开发步骤: 1.小程序管理后台添加订阅消息的模板 2.小程序前端编写调用(拉起)订阅授权 wx.requestSubscribeMessage({ tmplIds: ['34fwe1211xx ...

  5. Qt Gui 第六章布局管理

    1.QRadioButton之间如何互斥 其中一种方法是将各个QRadioButton控件放在同一个toolbarsLayout或者toolbarsGroupBox即可:如下所示 toolbarsGr ...

  6. .NetCore3.0短网址项目

    Wei.TinyUrl 基于.NetCore3.0 + Mysql开发的短网址项目 项目地址:https://github.com/a34546/Wei.TinyUrl 演示效果: 快速开始 1. 修 ...

  7. P5048 [[Ynoi2019模拟赛]Yuno loves sqrt technology III]

    为什么我感觉这题难度虚高啊-- 区间众数的出现次数- 计算器算一下 \(\sqrt 500000 = 708\) 然后我们发现这题的突破口? 考虑分块出来[L,R]块的众数出现个数 用 \(\text ...

  8. var s=+newDate();

    var s=+newDate(); 解释如下:=+是不存在的; +new Date()是一个东西; +相当于.valueOf(); 看到回复补充一下.getTime()这个也是得到毫秒数 //4个结果 ...

  9. Windows下MongoDB的配置及其远程连接

    基本操作MongoDB的基本安装https://blog.csdn.net/heshushun/article/details/77776706启动和配置MongoDB服务参考博客https://bl ...

  10. Coursera 吴恩达 机器学习 学习笔记

    Week 1 机器学习笔记(一)基本概念与单变量线性回归 Week 2   机器学习笔记(二)多元线性回归 机器学习作业(一)线性回归——Matlab实现 机器学习作业(一)线性回归——Python( ...