一、霍夫线变换 
霍夫线变换是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. nginx模块之ngx_http_upstream_module

    ngx_http_upstream_module 示例: http上下文: upstream upservers{ ip_hash; //根据客户端IP进行调度,每个客户端ip地址访问时每个ip生成一 ...

  2. 【3】Python中的广播

    Python-numpy中有一种很高效的方法:广播.  下面介绍一下广播. 实例:对于这个矩阵,如果想求每列元素的和,怎么才能不用for循环? (1,4)指的是一行四列的矩阵:axis决定了是横向(行 ...

  3. a++ 和 ++a

    //a++ 先赋值,后加 var a = 1 console.log(a++);//1 console.log(a) //2 //++a 先赋值,后加 var a = 1 console.log(++ ...

  4. SpringBoot整合ActiveMQ开启持久化

    1.开启队列持久化 只需要添加三行代码 jmsTemplate.setDeliveryMode(2); jmsTemplate.setExplicitQosEnabled(true); jmsTemp ...

  5. VS打包程序步骤

    1.下载打包的程序 2.在你的程序里面安装打包的项目 3.添加项目输出 4.为项目添加必要的文件 双击前面建立好的主输出 一般文件为一些配置文件(如使用Nlog写日志,需要添加Nlog的配置文件)和图 ...

  6. git flow开发分支管理模型

    Git Flow 是什么 Git Flow是构建在Git之上的一个组织软件开发活动的模型,是在Git之上构建的一项软件开发最佳实践.Git Flow是一套使用Git进行源代码管理时的一套行为规范和简化 ...

  7. Java多线程之synchronized和volatile

    概述 用Java来开发多线程程序变得越来越常见,虽然Java提供了并发包来简化多线程程序的编写,但是我们有必要深入研究一下,才能更好的掌握这块知识. 本文主要对Java提供的底层原语synchroni ...

  8. KMP(模板)

    算法讲解: KMP算法最浅显易懂 模板来源: 从头到尾彻底理解KMP 首先:KMP的模板为: void get_next(char *a, int *nex) { nex[] = ; , j = ; ...

  9. Pikachu-File Inclusion(文件包含漏洞)

    File Inclusion(文件包含漏洞)概述 文件包含,是一个功能.在各种开发语言中都提供了内置的文件包含函数,其可以使开发人员在一个代码文件中直接包含(引入)另外一个代码文件. 比如 在PHP中 ...

  10. java - CAS及CAS底层原理

    CAS是什么? CAS的全称为Compare-And-Swap它是一条CPU并发原语,也就是在CPU硬件层面上来说比较并且判断是否设置新值这段操作是原子性的,不会被其他线程所打断.在JAVA并发包ja ...