一、霍夫直线的原理
(1)本部分大部分学习来自《OpenCV3编程入门》,另外有一些自己的理解
如上图所以,将一条直线由截距是表示为在极坐标系下
化简为
(2)对于一个点(x0,y0)来说,可以通过这个点的一族直线统一定义为
每一对 代表一条通过点(x0,y0)的直线。
(3)如果对于一个给定点(x0,y0),我们在极坐标对极径极角平面绘制出所有通过它的直线,将会得到一条正弦曲线。例如x0=8,y0=6的曲线如下所示:
上图是r>0 theta(0,2*PI)
(4)对图像中所有的点进行上述操作,如果两个点在一条直线上,那么两条正弦曲线将会交于一点
上图所有的三个点在一条直线上
(5)一条直线能够通过在平面theta-r寻找交于一点的曲线数量来检测, 越多的 曲线交于一点就意味着这个交点表示的直线由更多的点组成,通过设置交于一点的曲线数的阈值来决定是否检测到一条直线。
(6)霍夫变换即追踪图像中每个点对应曲线间的交点,如果 交点数量超过了阈值,那么可以认为这个交点所代表的参数为原图像中的一条直线。
二、霍夫直线的代码
#include
#include
int main(){
cv::Mat src=cv::imread("../2.jpg");
cv::Mat dst,mid;
cv::Canny(src,mid,50,200,3);
cv::cvtColor(mid,dst,cv::COLOR_GRAY2BGR);
std::vectorlines;
cv::HoughLines(mid,lines,1,CV_PI/180,100,0,0);
for(size_t t=0;t
三、霍夫圆的原理
霍夫变换检测圆形的原理跟检测直线的原理是一样的。圆的表达式为 (x-a)2+(y-b)2=r2 , 把问题转换成在求解经过像素点最多的 (a,b,r) 参数对。这里会发现(a,b,r)的参数空间特别大,计算量特别大。我们一般使用霍夫梯度法来解决圆的变换。
如上图所示,如果我们对一个圆求梯度,那么圆上所有的点的梯度的方向均朝向圆心
基于此有如下原理:
(1)首先对图像应用边缘检测,比如用canny边缘检测
(2)使用sobel算子计算所有像素的梯度
(3)遍历canny之后的所有非0的像素点,沿着梯度方向画线,每个点有是一个累加器,有一个线经过该点,累加器加1,对所有累加器进行排序,根据阈值找到所有可能的圆心
(4)计算canny图像中所有的非0像素点距离圆心的距离,距离从小到大排序,选取合适的半径
(5)对选取的半径设置累加器,对于满足半径r的累加器+1
(6)统计所有可能的半径
四、霍夫圆的代码
#include
#include
int main(){
cv::Mat src=cv::imread("../3.png");
cv::Mat gray;
cv::namedWindow("src",cv::WINDOW_AUTOSIZE);
cv::imshow("src",src);
cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
cv::namedWindow("gray",cv::WINDOW_AUTOSIZE);
cv::imshow("gray",gray);
std::vectorcircles;
cv::HoughCircles(gray,circles,cv::HOUGH_GRADIENT,2,10,200,100,85,0);
for(size_t t=0;t