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

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

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

      还是老步骤,整理笔记

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

一、引言

二、霍夫变换概述

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

三、霍夫线性变换学习【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑---笔记_第2张图片

1、HoughLines( )函数示例代码

#include
#include


#include
#include
#include

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 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;
}

原图:

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

canny检测的边缘图:

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

对应的HoughLines变换的效果图:

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

补充部分: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 和 θ的值。 这两个值只能确定直线,而不能确定线段是从哪开始到哪结束。学习【OpenCV入门教程之十四】OpenCV霍夫变换:霍夫线变换,霍夫圆变换合辑---笔记_第6张图片

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

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
#include
#include
#include

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 lines;//定义一个矢量结构lines用于存放得到的线段矢量集合(vec4i)整型
	HoughLinesP(mid,lines,1,CV_PI/180,40,20,3);

	//依次在图中绘制出每条线段
	for (int i = 0; i

原图:

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

canny检测边缘图:

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

HoughLinesP变换效果图:

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

四、霍夫圆变换

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

HoughCircles( )函数示例代码

#include
#include

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所以
	vector circles;
	//第4,5个参数需要反复测试,不然检测出来的圆个数会很多
	HoughCircles(mid,circles,CV_HOUGH_GRADIENT,1.5,60,200,100,0,0);
	//依次在图中绘制出圆
	for (int i = 0; i < circles.size(); i++)
	{
		//遍历每个圆轨的圆心center
		Point center(cvRound(circles[i][0]),cvRound(circles[i][1]));
		//遍历每个圆轨迹的半径r
		int 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;

}
原图:

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

HoughCircles变换效果图:

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

五、综合案例

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

代码如下:

#include
#include

using namespace cv;
using namespace std;

//原始图、中间图和效果图
Mat src,dst,mid;
//定义一个矢量结构lines用于存放得到的线段矢量集合
vector lines;
//变量接收的TrackBar位置参数
int HoughLinesP_value=100;

//回调函数
void HoughLinesP_on(int,void*)
{
	//定义局部变量储存全局变量  
	Mat mid_p=mid.clone();
	Mat dst_p=dst.clone();
	vector 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;
}

原图:

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

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

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

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

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

你可能感兴趣的:(Opencv)