学习【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑---笔记

来源:互联网 发布:网页数据采集器 编辑:程序博客网 时间:2024/05/20 18:45

本文参考@浅墨_毛星云 文章链接: http://blog.csdn.net/poem_qianmo/article/details/26977557

         今天学习了教程【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑,表示对霍夫线变换如何由概念转化为代码,理解了很久,坐标图都画了好几页,因为是小白,理论知识不清楚,所以遇到一些问题,可能对有些人很基础,但对于我来说,还是难理解,不过终于明白,代码是怎么来的了,一定要好好记录一下,以免日后忘记~

      还是老步骤,整理笔记

     OpenCV中霍夫变换相关的知识点,以及了解了OpenCV中实现霍夫线变换的HoughLines、HoughLinesP函数的使用方法,实现霍夫圆变换的HoughCircles函数的使用方法。

一、引言

二、霍夫变换概述

三、霍夫线性变换

1、HoughLines( )函数示例代码

#include<opencv2\core\core.hpp>#include<opencv2\highgui\highgui.hpp>#include<opencv2\imgproc\imgproc.hpp>#include<opencv2\opencv.hpp>#include<iostream>using namespace cv;using namespace std;int main(){//载入原始图和Mat变量定义Mat src=imread("img/line1.png",1);Mat dst,mid;//进行边缘检测和转化为灰度图Canny(src,mid,50,200,3);//进行一此canny边缘检测cvtColor(mid,dst,CV_GRAY2BGR);//转化边缘检测后的灰度图转化为三通道图//进行霍夫线变换 vector<Vec2f> lines;//定义一个矢量结构lines用于存放得到的线段矢量集合HoughLines(mid,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;//为什么这样?有配套的图片解释见下面效果图之后的补充部分,1000表示点(x0,y0),在直线,向上,向下1000的距离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(dst,pt1,pt2,Scalar(100,200,100),1,CV_AA);}//显示原始图imshow("1",src);//边缘检测后的图imshow("2",mid);//显示效果图imshow("3",dst);waitKey(0);return 0;}

原图:


canny检测的边缘图:


对应的HoughLines变换的效果图:


补充部分:pt1.x=cvRound(x0+1000*(-b));有些不理解?

pt1与pt2点的计算方法 。 这里已知下图中的rh0 和θ,现在只需要求图中“任意”两点, 就能用cvLine画出pt1 -> pt2的直线 。 看看下页图, 就明白这里1000什么的是为什么了。

这里是取了点(x0,y0)在直线上上下1000的距离,那么用cvLine画出来的线段就是从pt1 -> pt2的了。那么pt1->pt2的直线距离就是2000。可以取其他的距离,不一定去1000,如600也可以。1.这个地方也许会出现检测出来的线段长度比pt1->pt2还大,即包含了我们画的线段 , 这是肯定的。2. 还会出现本来线段没有pt1->pt2这么长,那么我们画的就会过长了。 也是肯定会出现的情况。因为:CV_HOUGH_STANDARD方法 只能得出rh0 和 θ的值。 这两个值只能确定直线,而不能确定线段是从哪开始到哪结束。

通过上面的关系,可以推导出下面的式子成立:

pt1.x=cvRound(x0+1000*(-b));

pt1.y=cvRound(y0+1000*(a));

pt2.x=cvRound(x0-1000*(-b));

pt2.y=cvRound(y0-1000*(a));

2、HoughLinesP( )函数示例代码

#include<opencv2\imgproc\imgproc.hpp>#include<opencv2\opencv.hpp>#include<opencv2\opencv.hpp>#include<iostream>using namespace cv;using namespace std;int main(){Mat src,dst,mid;src=imread("img/line2.png",1);//进行边缘检测和转化为灰度图Canny(src,mid,80,200,3);///进行一次canny边缘检测cvtColor(mid,dst,CV_GRAY2BGR);//将边缘检测后的灰度图转化为BRG三通道图//进行霍夫线变换vector<Vec4i> lines;//定义一个矢量结构lines用于存放得到的线段矢量集合(vec4i)整型HoughLinesP(mid,lines,1,CV_PI/180,40,20,3);//依次在图中绘制出每条线段for (int i = 0; i<lines.size(); i++){Vec4i ll=lines[i];line(dst,Point(ll[0],ll[1]),Point(ll[2],ll[3]),Scalar(100,200,100),1,CV_AA);}imshow("1",src);imshow("2",mid);imshow("3",dst);waitKey(0);return 0;}

原图:


canny检测边缘图:


HoughLinesP变换效果图:

四、霍夫圆变换


HoughCircles( )函数示例代码

#include<opencv2\opencv.hpp>#include<iostream>using namespace cv;using namespace std;int main(){Mat src,dst,mid;src=imread("img/circle.png");imshow("1",src);//转为灰度图,进行GaussianBlur图像平滑cvtColor(src,mid,CV_BGR2GRAY);GaussianBlur(mid,mid,Size(9,9),0,0);//进行霍夫圆变换,每个向量中包含3个值,x,y,r所以<Vec3f>vector<Vec3f> circles;//第4,5个参数需要反复测试,不然检测出来的圆个数会很多HoughCircles(mid,circles,CV_HOUGH_GRADIENT,1.5,60,200,100,0,0);//依次在图中绘制出圆for (int i = 0; i < circles.size(); i++){//遍历每个圆轨的圆心centerPoint center(cvRound(circles[i][0]),cvRound(circles[i][1]));//遍历每个圆轨迹的半径rint r=cvRound(circles[i][2]); //绘制圆心  当第5个参数为负数时,表示填充,当为正数时,表示画圆的粗细circle(src,center,3,Scalar(0,0,100),-1,8,0);//绘制圆轮廓  circle(src,center,r,Scalar(10,100,30),2,8,0);}imshow("2",src);waitKey(0);return 0;}
原图:


HoughCircles变换效果图:

五、综合案例

的HoughLinesP函数的基础上,为其添加了用于控制其第五个参数阈值threshold的滚动条。能通过调节滚动条,改变阈值,动态地控制霍夫线变换检测的线条多少。

代码如下:

#include<opencv2\opencv.hpp>#include<iostream>using namespace cv;using namespace std;//原始图、中间图和效果图Mat src,dst,mid;//定义一个矢量结构lines用于存放得到的线段矢量集合vector<Vec4i> lines;//变量接收的TrackBar位置参数int HoughLinesP_value=100;//回调函数void HoughLinesP_on(int,void*){//定义局部变量储存全局变量  Mat mid_p=mid.clone();Mat dst_p=dst.clone();vector<Vec4i> mylines; //调用HoughLinesP函数  HoughLinesP(mid_p,mylines,1,CV_PI/180,HoughLinesP_value+1,50,10); //循环遍历绘制每一条线段  for (int i = 0; i < mylines.size(); i++){Vec4i ll=mylines[i];Point p1(ll[0],ll[1]),p2(ll[2],ll[3]);line(dst_p,p1,p2,Scalar(100,200,100),1,8);} //显示图像  imshow("效果图",dst_p);}int main(){src=imread("img/line1.png",1);imshow("原图",src);//进行边缘检测和转化为灰度图 Canny(src,mid,50,200,3);cvtColor(mid,dst,CV_GRAY2BGR);   //创建滚动条  namedWindow("效果图",1);createTrackbar("阈值","效果图",&HoughLinesP_value,200,HoughLinesP_on);//调用一次回调函数,调用一次HoughLinesP函数  HoughLinesP_on(HoughLinesP_value,0);HoughLinesP(mid,lines,1,CV_PI/180,80,50,10);imshow("效果图",dst);waitKey(0);return 0;}

原图:


不同阈值对应的HoughLinesP霍夫变换效果图:


阅读全文
0 0
原创粉丝点击