霍夫变换检测直线

图片经过边缘检测及二值化处理后是黑色的底,白色的线。把图片中每个白色像素点设为(Xi,Yi)。定理:对于直角坐标系中的每一个点,在极坐标中有一条曲线ρ=Xicosθ+Yisinθ与其对应。分别使θ等于0,△θ,2△θ……π,便可求出对应的ρ值。将ρ也分成许多小段△ρ,这样极坐标就被分成了许多以(△ρ,△θ)为单元的小块。计算每一条曲线落在各小段中的次数。所有数据点变换完成后,对小单元进行检测,这样,落入次数较多的单元,说明此点为较多曲线的公共点,而这些曲线对应的(X,Y)平面上的点可以认为是共线的。
     其实我就是需要极坐标中相交次数最多的交点坐标(ρ,θ)中的θ值……

我自己的理解:原本直线方程是:y=kx+b; 现在把它化为在极坐标下的形式:ρ=Xicosθ+Yisinθ。注意其中的x,y是直接坐标下的像素点。然后θ和ρ分段离散化取值,θ取值对应不同的ρ,这样在直角坐标系中的一个值(x,y)在极坐标下就对应一条曲线,其实,注意ρ,θ就是相当于直角坐标系中的k,b,ρ=Xicosθ+Yisinθ。就是用计算机运算速度快的原理算出ρ,θ。上面还没讲完,直角坐标系中的一个值(x,y)在极坐标下就对应一条曲线。那么,原本在直角坐标系中的直线上的像素点一一对应极坐标一条条曲线,他们会相交于一点。对应的(ρ,θ)就是我们需要的k和b。当然,具体的细节还需要查看源码,投票次数啊,具体的分割ρ,θ。。投票次数就是在(ρ,θ)平面相交的同一点的次数,当大于某个阈值时就说明是一条直线了取出(ρ,θ)就是对应的直线参数系数

图中曲线是(50,30)对应的在(ρ,θ)平面的曲线

图中的曲线是(50,30),(30,10)2条曲线相交,当把直接坐标系中的直线像素点一一映射到(ρ,θ)平面,应该都会相交于同一个(ρ,θ),当达到某个阈值时就说明可以了

下面是论文中的hough检测直线步骤:

下面是书上的代码:

//LineFinder.h
#include"opencv2/imgproc/imgproc.hpp"
#include"opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
#include<iostream>
//#include <math.h>
//#include <cmath>
using namespace std;
using namespace cv;
#define PI 3.141592
class LineFinder{
private:
	Mat img;
	vector<Vec4i>lines;
	double deltaRho;
	double deltaTheta;
	int minVote;
	double minLength;
	double maxGap;
public:
	LineFinder():deltaRho(1),deltaTheta(PI/180),minVote(10),minLength(0.),maxGap(0.){}
	void setAccResolution(double dRho,double dTheta)
	{
		deltaRho=dRho;
		deltaTheta=dTheta;
	}
	void setMinVote (int minv)
	{
		minVote=minv;
	}
	void setLineLengAndGap(double length,double gap)
	{
		minLength=length;
		maxGap=gap;
	}
	vector<Vec4i> findLines(Mat &binary)
	{
		lines.clear();
		HoughLinesP(binary,lines,deltaRho,deltaTheta,minVote,minLength,maxGap);
		return lines;
	}

	void drawDetectedLines(Mat &image,Scalar color=Scalar(255,255,255))
	{
		vector<Vec4i>::const_iterator it2=lines.begin();
		while (it2!=lines.end())
		{
			Point pt1((*it2)[0],(*it2)[1]);
			Point pt2((*it2)[2],(*it2)[3]);
			line(image,pt1,pt2,color);
			++it2;
		}

	}

};
//main
#include "LineFinder.h"
void main()
{
	Mat img=imread("C:\\Users\\Administrator\\Desktop\\工作\\testp\\road.jpg",0);
   Mat out1;
	Canny(img,out1,125,350);
	Mat img1;
	img1=img.clone();
	vector<Vec2f> lines;
	HoughLines(out1,lines,1,PI/180,60);
	vector<Vec2f>::const_iterator it=lines.begin();
	while (it!=lines.end())
	{
		float rho=(*it)[0];
		float theta=(*it)[1];
		if (theta<PI/4.||theta>3.*PI/4.)
		{
			Point pt1(rho/cos(theta),0);
			Point pt2((rho-out1.rows*sin(theta))/cos(theta),out1.rows);
			line(img1,pt1,pt2,Scalar(255),1);
		}
		else
		{
			Point pt1(0,rho/sin(theta));
			Point pt2(out1.cols,(rho-out1.cols*cos(theta))/sin(theta));
			line(img1,pt1,pt2,Scalar(255),1);
		}
		++it;
	}

	LineFinder finder;
	finder.setLineLengAndGap(100,20);
	finder.setMinVote(60);
	finder.findLines(out1);
	finder.drawDetectedLines(img);

	imshow("houghlinep",img);
	imshow("original",img1);
	imshow("out",out1);
	waitKey(0);

}

检测圆::

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
void main()
{
	Mat img=imread("C:\\Users\\Administrator\\Desktop\\工作\\testp\\chariot.jpg",0);
	Mat img1;
	GaussianBlur(img,img1,Size(5,5),1.5);
vector<Vec3f>circles;
HoughCircles(img1,circles,CV_HOUGH_GRADIENT,2,50,200,100,25,100);
vector<Vec3f>::const_iterator itc=circles.begin();
while(itc!=circles.end())
{
	circle(img1,Point((*itc)[0],(*itc)[1]),(*itc)[2],Scalar(255),5);
	++itc;
}

	imshow("original",img);
	imshow("img1",img1);
	waitKey(0);

}

点集的直线拟合:

#include "LineFinder.h"
void main()
{
	Mat img=imread("C:\\Users\\Administrator\\Desktop\\工作\\testp\\road.jpg",0);
   Mat out1;
	Canny(img,out1,125,350);
	Mat img1;
	img1=img.clone();
	vector<Vec2f> lines;
	HoughLines(out1,lines,1,PI/180,60);
	vector<Vec2f>::const_iterator it=lines.begin();
	while (it!=lines.end())
	{
		float rho=(*it)[0];
		float theta=(*it)[1];
		if (theta<PI/4.||theta>3.*PI/4.)
		{
			Point pt1(rho/cos(theta),0);
			Point pt2((rho-out1.rows*sin(theta))/cos(theta),out1.rows);
			line(img1,pt1,pt2,Scalar(255),1);
		}
		else
		{
			Point pt1(0,rho/sin(theta));
			Point pt2(out1.cols,(rho-out1.cols*cos(theta))/sin(theta));
			line(img1,pt1,pt2,Scalar(255),1);
		}
		++it;
	}

	LineFinder finder;
	finder.setLineLengAndGap(100,20);
	finder.setMinVote(60);
	finder.findLines(out1);
	finder.drawDetectedLines(img);

	vector<Vec4i>lines111=finder.findLines(out1);
	int n=0;
	Mat oneline(out1.size(),CV_8U,Scalar(0));
	line(oneline,Point(lines111[n][0],lines111[n][1]),Point(lines111[n][2],lines111[n][3]),Scalar(255),3);
	bitwise_and(out1,oneline,oneline);
	//threshold(oneline,oneline,100,255,THRESH_BINARY_INV);
	vector<Point>points;
	for (int y=0;y<oneline.rows;y++)
	{
		uchar *rowPtr=oneline.ptr<uchar>(y);
		for (int x=0;x<oneline.cols;x++)
		{
			if (rowPtr[x])
			{
				points.push_back(Point(x,y));
			}
		}
	}
	Vec4f line12;
	fitLine(points,line12,CV_DIST_L2,0,0.01,0.01);
	int x0=line12[2];
	int y0=line12[3];
	int x1=x0+100*line12[0];
	int y1=y0+100*line12[1];

	line(img,Point(x0,y0),Point(x1,y1),Scalar(0),3);

	imshow("src",img);

	imshow("oneline",oneline);
	waitKey(0);

时间: 2024-10-12 20:08:30

霍夫变换检测直线的相关文章

opencv笔记(十七)——使用霍夫变换检测直线

一般我们在检测物体轮廓的时候,会有检测直线的需求,这时可以用到OpenCV当中的霍夫变换实现. 霍夫变换的原理的简单阐述见:http://docs.opencv.org/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html#hough-lines 简单来讲,对于单个像素来说,它可能是由许多直线经过的,我们通过一个点可以构造无数条直线. 对于一个像素的位置(x, y),从笛卡尔坐标和极坐标两个角度,我们可以有      进而得到 上

OpenCV2学习笔记(八):使用霍夫变换检测直线和圆

在研究一幅图像时,常常会遇到一些平面或线性问题,直线在图像中频繁可见.这些富有意义的特征在物体识别等图像处理过程中扮演着重要的角色.本节主要记录一种经典的检测直线算法--霍夫变换(Hough Transform),用Hough变换检测图像中的直线和圆,开发平台为Qt5.3.2+OpenCV2.4.9. 一:Hough变换检测图像的直线 1.基础Hough变换 在霍夫变换中,直线用以下方程表示: 其中,参数表示一条直线到图像原点(左上角)的距离, 表示与直线垂直的角度.如下图所示,直线1的垂直线的

python+opencv实现霍夫变换检测直线

python+opencv实现高斯平滑滤波 python+opencv实现阈值分割 (2016-5-10)到OpenCV-Python Tutorials's documentation可以下载 功能: 创建一个滑动条来控制检测直线的长度阈值,即大于该阈值的检测出来,小于该阈值的忽略 注意:这里用的函数是HoughLinesP而不是HoughLines,因为HoughLinesP直接给出了直线的断点,在画出线段的时候可以偷懒 代码: # -*- coding: utf-8 -*- import

OpenCV笔记(十八)——使用霍夫变换检测圆圈

这些笔记的最初,我是以接近于源码分析的形式来梳理自己学习OpenCV的过程. 然而写下来,一是执行力,二是时间的问题,确实越写越马虎了.用我老师的话:观其大略了. 但是,暂时就这么写着吧. 在笔记<十七>中,我们简单地谈到了霍夫变换检测直线的原理,就是判断相邻像素点的值(x, y)对应的r-theta曲线是否能够相交,如果有足够多的相邻的像素点的曲线相交,我们就认为这些相邻的像素点构成一条直线. 圆圈亦然,只是把直线的方程替换成了圆的方程.除了极坐标的r,多了两个变量:Xcenter和Ycen

Opencv图像识别从零到精通(22)-----hough变换检测直线与圆

今天要看的是霍夫变换,常用用来检测直线和圆,这里是把常见的笛卡尔坐标系转换成极坐标下,进行累计峰值的极大值,确定.HoughLines,HoughLinesP,HoughCircles,三个函数,首先先看看原理,最后会用漂亮的matlab图,来回归一下,霍夫直线变换. 霍夫线变换: 众所周知, 一条直线在图像二维空间可由两个变量表示. 例如: 在 笛卡尔坐标系: 可由参数:  斜率和截距表示. 在 极坐标系: 可由参数:  极径和极角表示 对于霍夫变换, 我们将用 极坐标系 来表示直线. 因此,

hough变换检测直线

hough变换检测直线原理: 假设在图像中存在一条直线y=k*x+b(此时k,b未知).取直线上的任意两点进行说明,设为(x0,y0),(x1,y1). 所有经过点(x0,y0)的直线满足:-x0*k+y0=b ---式1,那么以k.b为直角坐标轴做式1对应直线: 所有经过点(x1,y1)的直线满足:-x1*k+y1=b ---式2,那么以k.b为直角坐标轴做式2对应直线: 两直线交于一点(kk,bb),此时该交点对应的直线y=kk*x+bb就是(x0,y0),(x1,y1)所确定的直线. 在h

Python下opencv使用笔记(十一)(详解hough变换检测直线与圆)

在数字图像中,往往存在着一些特殊形状的几何图形,像检测马路边一条直线,检测人眼的圆形等等,有时我们需要把这些特定图形检测出来,hough变换就是这样一种检测的工具. Hough变换的原理是将特定图形上的点变换到一组参数空间上,根据参数空间点的累计结果找到一个极大值对应的解,那么这个解就对应着要寻找的几何形状的参数(比如说直线,那么就会得到直线的斜率k与常熟b,圆就会得到圆心与半径等等). 关于hough变换,核心以及难点就是关于就是有原始空间到参数空间的变换上.以直线检测为例,假设有一条直线L,

图像处理之霍夫变换(直线检測算法)

图像处理之霍夫变换(直线检測算法) 霍夫变换是图像变换中的经典手段之中的一个,主要用来从图像中分离出具有某种同样特征的几何 形状(如,直线,圆等).霍夫变换寻找直线与圆的方法相比与其他方法能够更好的降低噪 声干扰.经典的霍夫变换经常使用来检測直线,圆,椭圆等. 霍夫变换算法思想: 以直线检測为例,每一个像素坐标点经过变换都变成都直线特质有贡献的统一度量,一个简单 的样例例如以下:一条直线在图像中是一系列离散点的集合,通过一个直线的离散极坐标公式, 能够表达出直线的离散点几何等式例如以下: X *

opencv 检测直线 线段 圆 矩形

转自:http://blog.csdn.net/byxdaz/archive/2009/12/01/4912136.aspx 检测直线:cvHoughLines,cvHoughLines2 检测圆:cvHoughCircles 检测矩形:opencv中没有对应的函数,下面有段代码可以检测矩形,是通过先找直线,然后找到直线平行与垂直的四根线. 检测直线代码: /* This is a standalone program. Pass an image name as a first paramet