【OpenCV图像处理】二十四、霍夫(Hough)检测
来源:互联网 发布:掌上电力提示网络异常 编辑:程序博客网 时间:2024/05/14 19:52
霍夫变换:
通常图像中直线对应重要的边缘信息,在计算机视觉中直线检测是一项具有重要意义的技术。由于直线具有特定的特征,因此提取方法也不同于一般的边缘检测方法。
一、霍夫变换直线检测
Hough变换直线检测是一种参数空间提取直线的方法,它将直线上点的坐标变换到过点的系数域,利用了共线点与直线相交之间的关系,将直线检测问题转换为技术问题。这种方法的主要优点是受直线中间隙和噪声的影响较小。
主要思想原理如下:
在O-xy平面内,直线的斜截式方程为:y=ux+v,其中u为斜率,v为截距
→对于给定的一条直线,对应一个数对(u,v),反之,给定一个数对(u,v),就对应一条直线 y= ux+v
→因此,O-xy平面上的直线y=ux+v与O-uv平面上的(u,v)一一对应,这个关系也就是Hough变换的基本原理
→同理,O-xy平面上任意一点(x,y)与O-uv平面的一条直线u=-xv+y也一一对应,也就是说,对于O-xy平面上的直线y=ux+v,直线上的没一点(x,y)都对应O-uv平面上的一条直线,并且这些直线交于一点(u,v)
→Hough变换就是利用这个性质检测共线点,从而提取出直线
(1)极坐标中Hough变换的实现
→由于直线的斜率可能存在无限大, 因此为了使变换域有意义,通常采用直线的极坐标方程表示为:
ρ=xcosθ + ysinθ
上式中,数对(ρ,θ)定义了从原点到直线距离的向量,这个向量与直线垂直,ρ表示的是向量的长度,θ表示向量方向,如下图所示:
所以,O-xy平面上的直线ρ=xcosθ + ysinθ与O-ρθ平面上的数对(ρ,θ)一一对应。
同理,O-xy平面上的一点与O-ρθ平面上一条正弦曲线也是一一对应的关系。具体关系是O-xy平面上的共线点对应于O-ρθ平面上的正弦曲线相交于一点。
为了寻找共线点对应所构成的直线,将O-ρθ平面量化为小格,参数空间中每一个小格对应与一个数对(ρ,θ)以及对应一个计数累加器A(ρ,θ)。
→对于O-xy平面上的点(x,y),由ρ=xcosθ + ysinθ 计算各个量化θ对应的ρ值并进行量化,然后将相应的计数累加器A(ρ,θ)进行加1操作
→将所有的点(x,y)变换到参数空间后,对各个小格对应的计数累加器进行统计,落入同一小格的O-xy平面上个点接近于共线,假设图像中存在n条待检测的直线,选择前n个最大计数值得小格,利用最小二成你和计算落在每一个小格中各点所在的直线方程。
→参数ρ和θ量化步长对共线点的检测有很大影响,
→→若太粗,则非共线点有可能落在参数空间内同一小格,由于野点的存在,导致ρ和θ估计不准确
→→若太细,则共线点落入参数空间中的多个小格内
(2)OpenCV中Hough直线检测的使用
首先需要说明的是,在OpenCV中的霍夫变换有下面三种
(a.标准霍夫变换,由HoughLines函数进行调用
(b.多尺度霍夫变换,由HoughLines函数进行调用
(c.累计概率霍夫变换,由HoughLinesP函数进行调用
下面首先介绍标准霍夫变换
(a.标准霍夫变换,HoughLines()函数
这个函数的作用是找出采用标准霍夫变换的二值图像线条。函数的原型如下:
void HoughLines( InputArray image, OutputArray lines,double rho, double theta, int threshold, double srn=0, double stn=0 );
第一个参数是InputArray类型的图像image,表示输入图像,也就是源图像,需要是8位单通道的二进制图像,可以将任意源图像载入进来,再使用函数修改成这个格式后,再填到这里。
第二个参数是InputArray类型的lines,经过调用HoughLines函数后存储了活肤变换检测到线条的输出矢量。每一条线具有两个元素的矢量(ρ,θ)表示,其中,ρ表示的是距离坐标原点(左上角点)的距离,θ是弧度线条旋转角度。
第三个参数是double类型的rho,表示的是一像素为单位的距离精度。另一种表述方式是直线搜索时的进步尺寸的单位半径
第四个参数是double类型的theta,表示以弧度为单位的角度精度。另一种标书方式是直线搜索时的进步尺寸的单位角度
第五个参数是int类型的threshold,表示累加平面的阈值参数,也就是识别某部分为图中一条直线时它在累加平面中必须达到的值,大于阈值threshold的线段才可以被检测通过并返回到结果中。
第六个参数是double类型的srn,有默认值0,对于多尺度的火狐变换,这是第三个参数进步尺寸rho的除数距离。粗略的累加器进步尺寸直接是第三个参数rho,而精确的累加器进步尺寸为rho/srn。
第七个参数是double累心的stn,有默认值0,对于多尺度霍夫变换,stn表示第四个参数进步尺寸的单位角度theta的除数距离。且如果srn和stn同时为0,就表示使用景点的霍夫变换,否则,这两个参数都应该是正数。
下面是使用这个函数的具体程序实例:
//霍夫变换直线检测#include <iostream>#include <opencv2\core\core.hpp>#include <opencv2\highgui\highgui.hpp>#include <opencv2\imgproc\imgproc.hpp>using namespace cv;using namespace std;int main(){Mat srcImage = imread("building.jpg");if (!srcImage.data){cout << "读入图片错误!" << endl;system("pause");return 0;}Mat tempImage, dstImage;//进行边缘检测并转换为灰度图Canny(srcImage, tempImage,50, 200, 3);cvtColor(tempImage, dstImage, CV_GRAY2BGR);//进行霍夫变换vector<Vec2f>lines;//定义一个矢量结构lines用于存放得到的线段矢量集合HoughLines(tempImage, lines, 1, CV_PI / 180, 150, 0, 0);//在图中依次绘制出每条线段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 + 100 * (-b));pt1.y = cvRound(y0 + 100 * (a));pt2.x = cvRound(x0 - 100 * (-b));pt2.y = cvRound(y0 - 100 * (a));line(dstImage, pt1, pt2, Scalar(0, 0, 255), 1, CV_AA);}//显示原始图imshow("原始图像", srcImage);//显示边缘检测图像imshow("边缘检测图像", tempImage);//显示直线检测图像imshow("直线检测图像", dstImage);waitKey();return 0;}
(b.累积概率霍夫变换:HoughLinesP()函数
这个函数在HoughLines函数的基础上,在末尾加了一个代表Probabilistic(概率)的P,表明它可以采用累积概率霍夫变换(PPHT)来找出二值图像中的直线。
函数的原型如下所示:
void HoughLinesP( InputArray image, OutputArray lines,double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 );第一个参数表示输入图像,也就是源图像,需要是8位的单通道二进制图像。
第二个参数是lines,表示经过调用这个函数后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1,x_2,y_2)表示,其中(x_1,y_1)和(x_2,y_2)是每个检测到的线段的结束点
第三个参数是double类型的rho,一像素为单位的距离精度。另一种标书方法是直线搜索是的进步尺寸的单位半径。
第四个参数是double类型的theta,表示的是以弧度为单位的角度精度。另一种标书方式是直线搜索时进步尺寸的单位角度。
第五个参数是int类型的threshold,表示累加平面的阈值参数,也就是识别某部分为图中一条直线时它在累加平面中必须达到的值,大于阈值threshold的线段才可以被检测通过并返回到结果中。
第六个参数是double类型的minLineLength,有默认值0,表示最低线段的长度,比这个参数短的线段就不能被检测出来。
第七个参数是double类型的maxLineGap,有默认参数0,表示将同一行点与点之间连接起来的最大距离
具体使用实例如下所示:
//霍夫变换直线检测#include <iostream>#include <opencv2\core\core.hpp>#include <opencv2\highgui\highgui.hpp>#include <opencv2\imgproc\imgproc.hpp>using namespace cv;using namespace std;int main(){Mat srcImage = imread("building.jpg");if (!srcImage.data){cout << "读入图片错误!" << endl;system("pause");return 0;}Mat tempImage, dstImage;//进行边缘检测并转换为灰度图Canny(srcImage, tempImage,50, 200, 3);cvtColor(tempImage, dstImage, CV_GRAY2BGR);//进行霍夫变换vector<Vec4i>lines;//定义一个矢量结构lines用于存放得到的线段矢量集合HoughLinesP(tempImage, lines, 1, CV_PI / 180, 80, 50, 10);//在图中依次绘制出每条线段for (size_t i = 0; i < lines.size(); i++){Vec4i l = lines[i];line(dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 1, CV_AA);}//显示原始图imshow("原始图像", srcImage);//显示边缘检测图像imshow("边缘检测图像", tempImage);//显示直线检测图像imshow("直线检测图像", dstImage);waitKey();return 0;}
一、霍夫变换圆形检测
霍夫变换适用于形式为的任何函数,其中x为坐标向量,c为参数向量
→二维空间中的圆函数有三个未知参数,圆的标准方程为:
→其中(α,β)是圆心,r是半径,这三个参数构成三维参数空间的技术累加器,根据O-xy平面上每一个点(x,y)递增α和β的值,计算相应的r值并进行量化,同事,将相应的技术累加器A(α,β,r)加1
→霍夫变换检测的复杂度随着参数个数的增加呈几何增长
→通常利用Hough变换进行圆形检测时,预先估计处圆的半径,从而可以将参数向量降低到二维
→在二维空间中,Hough变换圆形检测复杂度与直线检测复杂度相同
原理:
O-xy平面上一个圆与O-αβ平面上一个点(圆心)是一一对应关系,同理,O-xy平面上一个点与O-αβ平面上一个圆也是一一对应关系
对于O-xy平面上固定半径为r的圆,圆上每一个点对应于O-αβ平面上一个圆。这些圆形交于一点(α,β)
当圆形的半径估计过大或过小时,均无法正确确定(α,β)
→在已知圆半径时,参数空间尺寸为原图像行宽和列宽分别加上2r,
→在参数空间照片那个是将上以图像中每一个点为圆心进行画圆。
在OpenCV中可以利用HoughCircles函数检测处灰度图像中的圆。它相比之前的霍夫函数,一个比较明显的区别是不需要源图像是二值图像
函数原型如下所示:
void HoughCircles( InputArray image, OutputArray circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0 );第一个参数image表示输入图像,也就是源图像,需要是8位的灰度单通道图像
第二个参数circles表示经过调用这个函数后存储的检测到的圆的输出矢量,每个矢量由包含了3个元素的浮点矢量(x,y,radius)表示
第三个参数是int类型的method,表示的是使用的检测方法,目前OpenCV中只有霍夫梯度法这一种方法可以使用,标识符是CV_HOUGH_GRADIENT,在这里使用这个标识符即可。
第四个参数是double类型的dp,用来检测圆心的累加器图像的分辨率与输入图像之比的倒数,而且这个参数允许创建一个比输入图像分辨率低的累加器。
→→dp=1,累加器和输入图像具有一样的分辨率,如果dp=2,累加器有输入图像一半大的宽度和高度
第五个参数是double类型的minDist,是霍夫变换检测到的圆的圆心之间的最小距离
第六个参数是double类型的param1,有默认值100,它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法,它表示传递给canny边缘检测算子高阈值,而低阈值为高阈值的一半
第七个参数double类型的param2,也有默认值100,这个参数越小,就可以检测到更多根本不存在的圆,它越大,能通过检测的圆就更加接近完美的圆形
第八个参数是int类型的minRadius,有默认值0,表示圆半径的最小值
第九个参数是int类型的maxRadius,有默认值0,表示圆半径的最大值
→→需要注意的是:
使用这个函数可以很容易的检测处圆形的圆心,但是它可能找不到合适的半径,我们可以通过第八个参数和第九个参数进行指定圆的半径,来辅助进行圆形检测
相关实例如下所示:
//Hough变换圆形检测#include <iostream>#include <opencv2\core\core.hpp>#include <opencv2\highgui\highgui.hpp>#include <opencv2\imgproc\imgproc.hpp>using namespace cv;using namespace std;int main(){Mat srcImage = imread("circle.jpg");Mat grayImage, dstImage;//显示原始图像imshow("原始图像", srcImage);//转换为灰度图像并进行平滑cvtColor(srcImage, grayImage, CV_BGR2GRAY);GaussianBlur(grayImage, grayImage, Size(9, 9), 2, 2);//进行霍夫圆形变换vector<Vec3f>circles;HoughCircles(grayImage, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);//在图中绘制出圆形for (size_t i= 0; i < circles.size(); i++){//参数定义Point center(cvRound(circles[i][0]), circles[i][1]);int radius = cvRound(circles[i][2]);//绘制圆心circle(srcImage, center, 3, Scalar(0, 255, 0), -1, 8, 0);//绘制圆形轮廓circle(srcImage, center, radius, Scalar(0, 0, 255), 3, 8, 0);}imshow("效果图", srcImage);waitKey();return 0;}
- 【OpenCV图像处理】二十四、霍夫(Hough)检测
- 【OpenCV图像处理】二十二、图像边缘检测(上)
- 【OpenCV图像处理】二十三、图像边缘检测(下)
- 图像处理(八):线段检测之Hough变换
- OpenCV图像处理篇之Hough变换
- Opencv图像识别从零到精通(22)-----hough变换检测直线与圆
- 【OpenCV图像处理】十四、图像金字塔
- 【opencv】圆检测(非hough)
- 【OpenCV】Hough检测
- 【OpenCV】图像处理(二)图像形态学
- 【OpenCV图像处理】二十五、角点检测
- 图像处理————霍夫(HOUGH)变换
- 图像处理之_霍夫(Hough)变换
- 图像处理 C语言 hough变换 检测直线
- 图像处理 C语言 hough变换 检测直线
- openCV学习笔记(二)------图像平滑处理和边缘检测
- OpenCV入门(二) 图像平滑处理
- OPENCV图像处理提高(二):模糊
- jsp九大隐式对象中最重要的一个对象pageContext
- tmpfs在嵌入式linux中的使用
- Struts2 表单和非表单标签
- 【嵌入式Linux+ARM】硬件相关基础知识(门电路_UART_I2C_SPI)
- java--数组遍历
- 【OpenCV图像处理】二十四、霍夫(Hough)检测
- vue.js删除动态绑定的radio的指定项
- Java四种线程池的使用
- spring获取webapplicationcontext,applicationcontext几种方法详解
- python写算法题:leetcode: 5. Longest Palindromic Substring
- key数字时的json对象(形如:{001:{name:zhangsan,age:19},002:{name:lisi,age:29}}),在js或jsp中读取value的方法
- whoosh使用简述
- JsonPath的使用
- Ubuntu 14.04下host文件修改格式