Hough变换实例

合集下载

膨胀与腐蚀radonhough变换(1)

膨胀与腐蚀radonhough变换(1)

(a) 图像3-16(a)的一部分,即有字母b的那部分,图3-17左边的一部分数据
(b) 图(a)使用Q膨胀后的部分结果,即3-18(d)的放大。 图3-19 二值图像膨胀运算规则
其他算子的运算规则都与上面所述相同。运算结果与原图像有关,算子形状与图像的邻域情况决定了运算结果。 另外,从上面描述情况看,二值图像膨胀运算本质上是逻辑运算。 数学上,二值图像膨胀运算可以用集合定义如下:
(a) 原图像 (b) 腐蚀后的图像 (c) 膨胀后的图像 图3-21 二值图像腐蚀与膨胀比较
函数strel是专门用来生成算子模板的,strel('diamond',3)生成的算子模板为: 0 0 0 1 0 0 0 0 0 1 1 1 0 0 0 1 1 1 1 1 0 1 1 1 1 1 1 1 0 1 1 1 1 1 0 0 0 1 1 1 0 0 0 0 0 1 0 0 0 函数strel还可以生成‘square’、‘line’、‘disk’、‘periodicline’、‘pair’、‘octagon’等模板。
图3-20 二值图像腐蚀运算
程序中的函数imerode是用来进行腐蚀运算的。腐蚀运算后,原来图像一般会变细变小。
【例3-18】对二值图像实施腐蚀运算,并且与膨胀运算进行比较。 设计下面程序: A = imread('0370.bmp'); B=im2bw(A); B=~B; M=strel('diamond',3); C1=imerode(B,M); C2=imdilate(B,M); subplot(1,3,1); imshow(B) subplot(1,3,2); imshow(C1) subplot(1,3,3); imshow(C2) 程序运行结果如图3-21所示。

Hough变换

Hough变换
2)对边界上的每一个点(xi,yi),将 的所有量化 值代入式(8-71),计算相应的,并且将累加器加1, M(,)=M(,)+1。
3)将全部(xi,yi)处理后,分析M(,),如果 M(,)T,就认为存在一条有意义的线段,是该线段
的拟合参数。T是一个非负整数,由图像中景物的先 验知识决定。
y

(xi,yi)
图8-14 点的Houghx变换的极坐标形式
y
0=xcos0+ysin0 (xi,yi)
(0,0)
图8-15 共线点Houxgh变换的极坐标形式
数字图像处理与分析基础
算法
1)将(,)空间量化,得到二维矩阵M(,), M(,)是一个累加器,初始值为0,M(,)=0。
直线。对于(x,y)空间的任意一点(xi,yi),采用
极坐标(,)作为变换空间,其变换方程为:
=xicos+y间的一点(xi,yi)对应于(,)空
间的一条正弦曲线,其相位和幅值由xi、yi决定。
数字图像处理与分析基础
(x,y)空间的同一条直线上的点在(,)空间的正弦 曲线都会相交于点(0, 0),0为这条直线到原点的 距离, 0为直线的法线与轴的夹角,
边缘连接——Hough变换
Hough变换[Hough,1962]是一种基于图像全局分割 结果的边缘连接技术,它抗干扰能力强,能检测出 任意形状的曲线,即使线上有许多的断裂,因此在 图像分析的预处理中获得广泛应用。下面只介绍检 测直线的经典方法。
设图像空间(x,y)中的一条直线的方程为:
y=u0x+v0 式中u0为斜率,v0为截距。那么对于直线上的任意 一点pi(xi,yi),它在由斜率和截距组成的变换空间
(u,v)中将满足方程式:

Hough变换检测直线

Hough变换检测直线

Hough 变换检测直线实验报告一,实验要求用hough 算法检测图像中的直线算法。

使用这一算法来求一幅图像中的所有大于规定长度的直线段,设规定的长度为20点。

二,Hough 变换简介Hough 变换是图像处理中从图像中识别几何形状的基本方法之一。

Hough 变换的基本原理在于利用点与线的对偶性,将原始图像空间的给定的曲线通过曲线表达形式变为参数空间的一个点。

这样就把原始图像中给定曲线的检测问题转化为寻找参数空间中的峰值问题。

图1 Hough 变换)sin(sin cos 00θαθθρ+=+=A y x如上图所示,在图像空间,直线上一点),(00y x 转换到参数空间就是一条曲线,而且,图像空间同一直线上的点转换到参数空间的曲线一定相交于一点,即参数空间各曲线的交点对应着图像空间的一条直线,这样,检测参数空间曲线交点就检测出了图像空间的直线。

三,实验过程和结果分析用Hough 变换之前, 首先要对图像进行边缘检测的处理,也即霍夫线变换的直接输入只能是边缘二值图像。

本实验基于VS2008和OPENCV 来实现。

实验的步骤如下:(1)读入图像,转换成灰度图像OPENCV 中用cvLoadImage 函数来读取图像,函数原型:IplImage* cvLoadImage( const char* filename, int flags=CV_LOAD_IMAGE_COLOR );filename :要被读入的文件的文件名(包括后缀);flags :指定读入图像的颜色和深度;例如:cvLoadImage( fileame, -n1 ); //默认读取图像的原通道数cvLoadImage( filename, 0 ); //强制转化读取图像为灰度图 cvLoadImage( filename, 1 ); //读取彩色图(2)进行边缘检测本实验选择Canny算子的边缘检测,OPENCV中用Canny函数来进行Canny 算子的边缘检测,函数原型为:void cvCanny( const CvArr* image, CvArr* edges, double threshold1, double threshold2, int aperture_size=3 );image:单通道输入图像edges:单通道存储边缘的输出图像threshold1 :第一个阈值threshold2 :第二个阈值aperture_size :算子内核大小3,对检测出的二值图像进行Hough变换OPENCV中用cvHoughLines2函数来进行Hough变换,函数原型为:CvSeq* cvHonghLines2(CvArr* image,void* line_storage,int mehtod,double rho,double theta,int threshold,double param1 =0,double param2 =0);Image:输入8-比特、单通道(二值)图像line_storage:检测到的线段存储仓Method:Hough 变换变量,是下面变量的其中之一CV_HOUGH_STANDARD ——传统或标准Hough 变换CV_HOUGH_PROBABILISTIC——概率Hough 变换CV_HOUGH_MULTI_SCALE ——传统Hough 变换多尺度变种Rho:以象素为单位的距离精度,一般取1Theta:以弧度为单位角度精度,一般取CV_PI/180Threshold:阈值参数,当在一条直线上的像素点数大于threshold时,才将该直线作为检测结果显示出来,该值越大,得到直线越少。

用Hough变换检测二值图像中的圆

用Hough变换检测二值图像中的圆

用Hough变换检测二值图像中的圆Hough 变换简介Hough变换是实现图像边缘检测的一种有效方法,其基本思想是将测量空间的一点变换到参量空间中的一条曲线或一个曲面,而具有同一参量特征的点交换后在参量空间中相交,通过判断交点处的积累程度来完成特征曲线的检测,基于参量性质的不同,Hough变换可以检测直线、圆、椭圆、双曲线、抛物线等。

同时,将概率论、模糊集理论、分层迭代的思想和级联的方法应用于Hough变换的过程中,大大地提高了Hough变换的效率,改善了Hough变换的性能。

实验主要使用的函数MATLAB内部常数pi:圆周率p(=3.1415926...)MATLAB常用基本数学函数:abs(x):纯量的绝对值或向量的长度;round(x):四舍五入至最近整数;floor(x):地板函数,即舍去正小数至最近整数;MATLAB常用三角函数sin(x):正弦函数cos(x):余弦函数;向量的常用函数max(x):向量x的元素的最大值。

MATLAB图像类型转换函数:rgb2gray:将一副真彩色图像转换成灰度图像;im2bw:通过设定高度阈值将真彩色,索引色,灰度图转换成二值图像;MATLAB图形图像文件的读取和显示函数imread(filename);MATLAB二进制图像及其显示imshow(f1)。

用double对二值图像双精度化图形处理:sobel算子检测边缘hough变换检测圆分别显示灰度图像:figure;subplotSobel:算子边缘检测图像hough变换检测后的图像实验相关代码I=imread('*.jpg');f=rgb2gray(I);f1=im2bw(f,200/255);BW1=double(f1);BW=edge(BW1,'sobel',0.4);r_max=50;r_min=10;step_r=10;step_angle=pi/12;p=0.7;[m,n]=size(BW);size_r=round((r_max-r_min)/step_r)+1;size_angle=round(2*pi/step_angle);hough_space=zeros(m,n,size_r);[rows,cols]=find(BW);ecount=size(rows);for i=1:ecountfor r=1:size_rfor k=1:size_anglea=round(rows(i)-(r_min+(r-1)*step_r)*cos(k*step_angle));b=round(cols(i)-(r_min+(r-1)*step_r)*sin(k*step_angle));if(a>0&&a<=m&&b>0&&b<=n)hough_space(a,b,r)=hough_space(a,b,r)+1;endendendendmax_para=max(max(max(hough_space)));index=find(hough_space>=max_para*p);length=size(index);hough_circle=false(m,n);for i=1:ecountfor k=1:lengthpar3=floor(index(k)/(m*n))+1;par2=floor((index(k)-(par3-1)*(m*n))/m)+1;par1=index(k)-(par3-1)*(m*n)-(par2-1)*m;if((rows(i)-par1)^2+(cols(i)-par2)^2<(r_min+(par3-1)*step_r)^2+5&&...(rows(i)-par1)^2+(cols(i)-par2)^2>(r_min+(par3-1)*step_r)^2-5)hough_circle(rows(i),cols(i))=true;endendendfor k=1:lengthpar3=floor(index(k)/(m*n))+1;par2=floor((index(k)-(par3-1)*(m*n))/m)+1;par1=index(k)-(par3-1)*(m*n)-(par2-1)*m;par3=r_min+(par3-1)*step_r;fprintf(1,'Center%d%d radius%d\n',par1,par2,par3);para(:,k)=[par1,par2,par3];endsubplot(221),imshow(f);subplot(222),imshow(BW);subplot(223),imshow(hough_circle)图像读取图像处理的第一步就是对所采集的图像进行读入,本次研究采集的图像是24位真彩色的JPG 格式的图像。

OpenCV函数cvHoughLines2进行Hough变换

OpenCV函数cvHoughLines2进行Hough变换

OpenCV函数cvHoughLines2进行Hough变换OpenCV函数cvHoughLines2进行Hough变换霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,它通过一种投票算法检测具有特定形状的物体。

该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。

霍夫变换于1962年由Paul Hough 首次提出[53],后于1972年由Richard Duda和Peter Hart推广使用[54],经典霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆。

Hough变换用来在图象中查找直线。

它的原理很简单:假设有一条与原点距离为s,方向角为θ的一条直线,如图7.6所示。

直线上的每一点都满足方程我们知道,一条直线在直角坐标系下可以用y=kx+b表示, 霍夫变换的主要思想是将该方程的参数和变量交换,即用x,y作为已知量k,b作为变量坐标,所以直角坐标系下的直线y=kx+b在参数空间表示为点(k,b),而一个点(x1,y1)在直角坐标系下表示为一条直线y1=x1·k+b,其中(k,b)是该直线上的任意点。

为了计算方便,我们将参数空间的坐标表示为极坐标下的s和θ。

因为同一条直线上的点对应的(s,θ)是相同的,因此可以先将图片进行边缘检测,然后对图像上每一个非零像素点,在参数坐标下变换为一条直线,那么在直角坐标下属于同一条直线的点便在参数空间形成多条直线并内交于一点。

因此可用该原理进行直线检测。

在Opencv中已经有了利用Hough变换在二值图中找到直线的接口了,这里就直接调用,下面是我的实例:[cpp] view plaincopy#include<cv.h>#include<highgui.h><P> </P><P>#pragma comment(lib, "cv.lib") #pragmacomment(lib, "cxcore.lib")#pragma comment(lib, "highgui.lib")</P>int main(){IplImage* pImgSrc = NULL; //源图像IplImage* pImg8u = NULL; //灰度图IplImage* pImgCanny = NULL; //边缘检测后的图IplImage* pImgDst = NULL; //在图像上画上检测到的直线后的图像CvSeq* lines = NULL;CvMemStorage* storage = NULL;/*边缘检测*/pImgSrc = cvLoadImage ("1.jpg", 1);pImg8u = cvCreateImage (cvGetSize(pImgSrc),IPL_DEPTH_8U, 1);pImgCanny = cvCreateImage (cvGetSize(pImgSrc),IPL_DEPTH_8U, 1);pImgDst = cvCreateImage (cvGetSize(pImgSrc),IPL_DEPTH_8U, 1);cvCvtColor (pImgSrc, pImg8u, CV_BGR2GRAY);cvCanny (pImg8u, pImgCanny, 20, 200, 3);/*检测直线*/storage = cvCreateMemStorage (0);lines = cvHoughLines2 (pImgCanny, storage,CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 80, 200, 10);pImgDst = cvCreateImage (cvGetSize(pImgSrc),IPL_DEPTH_8U, 3);cvCvtColor (pImg8u, pImgDst, CV_GRAY2BGR);/*在pImgDst上画出检测到的直线*/for (int i = 0; i < lines->total; i++){CvPoint* line = (CvPoint*)cvGetSeqElem (lines, i); cvLine (pImgDst, line[0], line[1], CV_RGB(255,0,0), 3, 8);}cvNamedWindow ("src",1);cvNamedWindow ("canny", 1);cvNamedWindow ("hough", 1);cvShowImage ("src", pImgSrc);cvShowImage ("canny", pImgCanny);cvShowImage ("hough", pImgDst);cvWaitKey (0);cvReleaseImage (&pImgSrc);cvReleaseImage (&pImg8u);cvReleaseImage (&pImgCanny);cvReleaseImage (&pImgDst); cvReleaseMemStorage (&storage);return 0;}结果如下:源图:Canny算子进行边缘检测结果:Hough变换检测直线:。

hough变换 matlab例程

hough变换 matlab例程

以下是一个简单的MATLAB例程,演示如何使用Hough变换来检测图像中的直线。

假设你已经有一个名为`image.jpg`的图像文件,你可以使用以下代码来进行Hough变换:读取图像I = imread('image.jpg');将图像转换为灰度图Igray = rgb2gray(I);执行边缘检测BW = edge(Igray, 'canny');执行Hough变换[H,theta,rho] = hough(BW);找到峰值P = houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));找到直线lines = houghlines(BW,theta,rho,P,'FillGap',5,'MinLength',7);绘制图像和检测到的直线figure, imshow(I), hold onfor k = 1:length(lines)xy = [lines(k).point1; lines(k).point2];plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');% 为每条直线绘制端点plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');end在这个例程中,我们首先读取图像,然后将其转换为灰度图像,并执行Canny边缘检测。

接下来,我们使用Hough变换来检测直线,并找到其中的峰值。

最后,我们使用`houghlines`函数找到图像中的直线,并将其绘制在原始图像上。

Hough变换算法及过程

Hough变换算法及过程

Hough 变换Hough 变换是1962年由Hough 提出来的,用于检测图像中直线、圆、抛物线、椭圆等且其形状能够用一定函数关系描述的曲线,它在影像分析、模式识别等很多领域中得到了成功的应用:其基本原理是将影像空间中的曲线(包括直线)变换到参数空间中,通过检测参数空间中的极值点,确定出该曲线的描述参数,从而提取影像中的规则曲线。

直线Hough 变换通常采用的直线模型为θθρsin cos y x +=其中ρ是从原点引到直线的垂线长度;θ是垂线与x 轴正向的夹角(如图)。

对于影像空间直线上任一点(x ,y),Hough 变换将其映射到参数空间()ρθ,的一条正弦曲线上。

由于影像空间内的一条直线由一对参数()00ρθ,唯一地确定,因而该直线上的各点变换到参数空间的各正弦曲线必然都经过点()00ρθ,,在参数平面(或空间)中的这个点的坐标就代表了影像空间这条直线的参数。

这样,检测影像中直线的问题就转换为检测参数空间中的共线点的问题。

由于存在噪声及特征点的位置误差,参数空间中所映射的曲线并不严格通过一点,而是在一个小区域中出现一个峰,只要检测峰值点,就能确定直线的参数。

其过程为(1)对影像进行预处理,提取特征并计算其梯度方向;(2)将()ρθ,参数平面量化,设置二维累计矩阵()j i H ρθ,;(3)边缘细化,即在边缘点的梯度方向上保留极值点,剔除那些非极值点;(4)对每一边缘点,以其梯度方向ψ为中心,设置一小区间[]00,θψθψ+-,其中0θ为经验,一般可取 10~5,在此小区间上以θ∆为步长,按式(2—3—37)对每一个区间中的θ量化值计算相应的ρ值,并给相应的累计矩阵元素增加一个单位值;(5)对累计矩阵进行阈值检测,将大于阈值的点作为备选点;(6)取累计矩阵(即参数空间)中备选点中的极大值点为所需的峰值点,这些点所对应的参数空间的坐标即所检测直线的参数。

利用Hough 变换也可以提取圆和抛物线:()()222R r y c x =-+- c bx ax y ++=2但此时参数空间是三维空间,因而计算量相当大。

hough变换

hough变换

什么是hough变换Hough变换利用图像空间和Hough参数空间的点-线对偶性,把图像空间中的检测问题转换到参数空间。

通过在参数空间里进行简单的累加统计,然后在Hough参数空间寻找累加器峰值的方法检测直线。

例如,图1(a)中的九条线段对应于如图1(b)所示的其Hough参数空间的九个累加器峰值。

图1(b)中,Hough参数空间的横纵坐标分别为直线极坐标方程:ρ=x×cos(θ) + y×sin(θ) 的两个参数ρ和θ。

九个峰值的ρ和θ值唯一的确定其对应线段所在直线的两个参数。

并且线段的长度决定坐标(ρ,θ)处的累加值的大小。

应用领域理论与实践向来是形影不离,相辅相成,Hough变换之所以有如此长足的发展,主要原因还是在于实践应用上的广泛需求;而在实践中所暴露出的不足又进而促进了它的发展,循环往复,就如同生命的演化。

现枚举其主要应用领域如下:生物医学Hough变换已被成功应用于基于人工智能的专家诊断系统;X射线人体照片和CT图像的处理和判读;光学显微镜和电子显微镜中的细胞核自动分析系统;从超声波诊断中提取三维动脉特征,等等。

自动化、机器人视觉Hough变换已被用于产品部件的自动监视、缺陷诊断、生产过程的自动监控、计算机辅助制造(CAM)等。

例如基于Hough变换的机械零件检测和定位系统;基于Hough变换采用直线、圆弧等作为基本特征的工业产品检查系统。

空间技术、军事防御Hough变换已被用于运动目标轨迹的检测与识别,高空侦察机、间谍卫星和军事雷达等目标自动识别系统的特征提取。

例如应用Hough变换对战斗机的外形特征进行提取和自动识别;应用Hough变换辅以信号检测理论解决并行多运动目标的跟踪问题。

办公自动化Hough变换在许多应用系统中得到了很好的应用。

例如采用Hough变换进行英文字符特征提取并自动识别,其对印刷体字符识别率为99.6%,对手写体字符的平均识别率也达到了86.9%,并已成功应用于邮政信件的自动分拣、文件处理等。

《霍夫变换Hough》课件

《霍夫变换Hough》课件

未来发展方向
随着计算机算力的提升, 人工智能技术的发展,霍 夫变换Hough将在更多领 域得到变换[M]. 阳泉: 山西科技师范学院学报, 2009. • Duda R O, Hart P E. Use of the Hough transformation to detect lines and curves in
for circles[J]. IEEE Transactions on Image Processing, 2014, 23(12): 5338-5347.
pictures[J]. Communications of the ACM, 1972, 15(1): 11-15. • Zhu J, Ji X, Zhang Y, et al. A computationally efficient approach to the Hough transform
霍夫变换可用于许多领域,例如检测道路标线、检测医学影像中的对象、自然场景分析 等。
3 霍夫变换Hough的优点和缺点
霍夫变换具有鲁棒性好、适用范围广等优点,但是计算量较大、可能存在误检、漏检等 缺点。
霍夫变换Hough的原理
什么是霍夫空间?
霍夫空间是一种由极坐标系 建立起来的坐标系,它是描 述一条直线或圆的数学形式。
如何检测图像中的直线?利用霍夫变换进行直线检测,步骤包括边缘检测、霍夫 空间生成、投票计算和参数选取。
2
霍夫圆变换
如何检测图像中的圆?利用霍夫变换进行圆检测,步骤包括边缘检测、霍夫空间 生成、投票计算和参数选取。
案例分析
直线检测案例
圆检测案例
案例描述:利用霍夫变换检测道路标线。实现步 骤:边缘检测、霍夫空间生成、投票计算和参数 选取。实现结果展示:检测出图像中的道路标线。

数字图像处理—Hough变换直线检测,matlab实现

数字图像处理—Hough变换直线检测,matlab实现

数字图像处理—Hough变换直线检测,matlab实现实验八 Hough变换直线检测一、实验目的理解Hough变换的原理,了解其应用;掌握利用Hough变换进行直线检测的处理过程及编程方法。

二、实验内容利用Hough变换检测直线通常先进行边缘检测,得到只包含边缘的二值图像。

再通过Hough变换,在参数空间检测图像共线点的数量得到直线参数,从而实现直线检测。

1、读入图像(图像需有直线或直线性边缘)2、进行图像边缘,得到二值图像3、实现Hough变换,检测出图像中的直线方程4、输出结果三、实验要求1、编写代码,完成各项实验内容2、总结实验中遇到问题及解决方案,书写实验报告%Hough变换clc;clear;close all f=imread('line.bmp'); %若是彩色图片转灰度化if length(size(f))>2f=rgb2gray(f);end%figure(1)subplot(121);imshow(f); %利用edge函数进行边缘检测j=edge(f,'Sobel');subplot(122);imshow(j); [row,col]=size(j);pinfang=round((row*row+col*col)^0.5);A=zeros(2*pinfang,180);for m=1:rowfor n=1:colif j(m,n)>0for thera=1:180r=thera/180*pi; %角度转弧度rho=round(m*cos(r)+n*sin(r));%ρ=cosθ+sinθrho=rho+pinfang+1;%-l:l转换到1:2l+1A(rho,thera)=A(rho,thera)+1;endendendend[rho,thera]=find(A>40);%交点超过60条线的点,ma,na为参数空间的坐标点nma=length(rho);for i=1:nmahold onm=1:row;%rho=ma(i)-1;r=thera(i)/180*pi;n=(rho(i)-pinfang-m*cos(r))/(0.00001+sin(r));plot(n,m,'r'); end。

opencvhough变换实现曲线断点连接

opencvhough变换实现曲线断点连接

标题:opencvhough变换实现曲线断点连接一、概述对于图像处理和计算机视觉领域的研究者和从业者来说,曲线的连接是一个常见且具有挑战性的问题。

尤其在边缘检测和目标识别中,曲线的断点连接对于准确地检测和识别目标具有重要意义。

而opencvhough变换作为图像处理中的经典算法之一,能够很好地解决曲线断点连接的问题。

本文将介绍opencvhough变换的原理和应用,以及如何利用opencvhough变换实现曲线断点连接。

二、opencvhough变换的原理opencvhough变换是一种经典的直线检测算法,最早由Paul Hough 于1962年提出。

该算法的基本原理是通过将像素点映射到参数空间中,然后在参数空间中找到共线的像素点组成直线。

具体来说,opencvhough变换首先将直角坐标系中的一条直线表示为极坐标系中的一个点,这个点的极坐标是$r$和$\theta$,其中$r$表示直线与原点的距离,$\theta$表示直线与$x$轴的夹角。

opencvhough变换在参数空间中进行累加,最后找到累加值最大的点即为检测到的直线。

三、opencvhough变换的应用opencvhough变换广泛应用于图像处理和计算机视觉领域,例如边缘检测、目标识别、车道线检测等。

在边缘检测中,opencvhough变换可以帮助检测图像中的直线和曲线,从而辅助目标识别和物体定位。

在目标识别中,opencvhough变换可以帮助检测图像中的目标轮廓,进而实现目标的识别和跟踪。

在车道线检测中,opencvhough 变换可以帮助检测图像中的车道线,从而实现自动驾驶系统对车道的识别和跟踪。

四、opencvhough变换实现曲线断点连接在实际的图像处理和计算机视觉应用中,曲线断点连接是一个比较常见的问题。

一般来说,曲线可能由多个曲线段组成,而这些曲线段之间可能存在断点。

为了准确地识别和跟踪整条曲线,需要对这些曲线段进行断点连接。

边缘检测与Hough变换实验报告Matlab

边缘检测与Hough变换实验报告Matlab

边缘检测与Hough变换实验目的:写一段代码实现一幅图像,其中分为以下两个步骤1.使用Matlab中的canny算子进行边缘检测,可以让使用者交互式的输入不同的Sigma的值实现边缘检测。

2.运用Hough变换来找到最突出的边缘,在图像中找到并画出最长的直线。

实验原理:canny算子边缘检测的基本原理是:采用二维高斯函数的任一方向上的一阶方向导数为噪声滤波器,通过与图像f(x,y)卷积进行滤波,然后对滤波后的图像寻找图像梯度的局部极大值,以确定图像边缘。

Canny边缘检测算子是一种最优边缘检测算子。

其实现步骤如下:1)用高斯滤波器平滑图像2)计算滤波后图像梯度的幅值和方向3)对梯度幅值应用非极大值抑制,其过程为找出图像梯度中的局部极大值点,把其他非局部极大值置零,以得到细化的边缘;4)再用双阈值算法检测和连接边缘;使用canny算子的edge函数调用格式为BW=edge(I,'canny');BW=edge(I,'canny',thresh,sigma);BW=edge(I,'canny',thresh);[BW,threshold]=edge(I,'canny',…);2.Hough变换时最常用的直线提取方法,它的基本思想是:将直线上每一个数据点变换为参数平面中的一条直线或曲线,利用共线的数据点对应的参数曲线相交于参数空间中一点的关系,使得直线提取问题转化为计数问题。

Hough变换提取直线的主要优点是受直线中的间隙和噪声影响较小。

Hough检测直线的Matlab实现:在Matlab图像处理工具箱中提供了3个与Hough变换有关的函数,分别为hough函数,houghpeaks函数和houghlines函数。

hough函数的调用格式为[H,theta,rho]=hough(BW);其中BW为二值图像,H为Hough变换矩阵,theta为变换轴间隔θ,rho为元素个数。

Houghpeaks函数是用来提取Hough变换后参数平面上的峰值点。

用Hough变换检测直线和圆

用Hough变换检测直线和圆

特殊图像变换1、HoughLines功能:利用Hough 变换在二值图像中找到直线格式:CvSeq* cvHoughLines2( CvArr* image, void* line_storage, int method, double rho, double theta, int threshold,double param1=0, double param2=0 );参数:image:输入8-比特、单通道(二值) 图像,其内容可能被函数所改变line_storage:检测到的线段存储仓. 可以是内存存储仓(此种情况下,一个线段序列在存储仓中被创建,并且由函数返回),或者是包含线段参数的特殊类型(见下面)的具有单行/单列的矩阵(CvMat*)。

矩阵头为函数所修改,使得它的cols/rows将包含一组检测到的线段。

如果line_storage是矩阵,而实际线段的数目超过矩阵尺寸,那么最大可能数目的线段被返回(线段没有按照长度、可信度或其它指标排序).method:Hough 变换变量,是下面变量的其中之一:∙CV_HOUGH_STANDARD- 传统或标准Hough 变换. 每一个线段由两个浮点数(ρ, θ) 表示,其中ρ 是点与原点(0,0) 之间的距离,θ 线段与x-轴之间的夹角。

因此,矩阵类型必须是CV_32FC2 type.∙CV_HOUGH_PROBABILISTIC - 概率Hough 变换(如果图像包含一些长的线性分割,则效率更高). 它返回线段分割而不是整个线段。

每个分割用起点和终点来表示,所以矩阵(或创建的序列)类型是CV_32SC4.∙CV_HOUGH_MULTI_SCALE- 传统Hough 变换的多尺度变种。

线段的编码方式与CV_HOUGH_STANDARD 的一致。

rho:与象素相关单位的距离精度theta:弧度测量的角度精度threshold:阈值参数。

如果相应的累计值大于threshold,则函数返回的这个线段.param1:第一个方法相关的参数:∙对传统Hough 变换,不使用(0).∙对概率Hough 变换,它是最小线段长度.∙对多尺度Hough 变换,它是距离精度rho的分母(大致的距离精度是rho而精确的应该是rho / param1 ).param2:第二个方法相关参数:∙对传统Hough 变换,不使用(0).∙对概率Hough 变换,这个参数表示在同一条直线上进行碎线段连接的最大间隔值(gap), 即当同一条直线上的两条碎线段之间的间隔小于param2时,将其合二为一。

史上最详细的Hough直线检测

史上最详细的Hough直线检测

史上最详细的Hough 直线检测所以这⾥再次回顾⼀下检测直线的算法之——Hough变换。

Hough 直线检测1.直线坐标参数空间在图像x −y坐标空间中,经过点(,)的直线表⽰为:其中,参数a为斜率,b为截矩。

通过点(,)的直线有⽆数条,且对应于不同的a和b值。

如果将和视为常数,⽽将原本的参数a和b看作变量,则式⼦(1)可以表⽰为:这样就变换到了参数平⾯a −b。

这个变换就是直⾓坐标中对于(,)点的Hough变换。

该直线是图像坐标空间中的点(,)在参数空间的唯⼀⽅程。

考虑到图像坐标空间中的另⼀坐标(,),它在参数空间中也有相应的⼀条直线,表⽰为:这条直线与点(,)在参数空间的直线相交于⼀点(,),如图所⽰:图像坐标空间中过点(,)和点(,)的直线上的每⼀点在参数空间a −b上各⾃对应⼀条直线,这些直线都相交于点,⽽a0、b0就是图像坐标空间x −y中点(,))和点(,)所确定的直线的参数。

反之,在参数空间相交于同⼀点的所有直线,在图像坐标空间都有共线的点与之对应。

根据这个特性,给定图像坐标空间的⼀些边缘点,就可以通过Hough变换确定连接这些点的直线⽅程。

具体计算时,可以将参数空间视为离散的。

建⽴⼀个⼆维累加数组A(a,b),第⼀维的范围是图像坐标空间中直线斜率的可能范围,第⼆维的范围是图像坐标空间中直线截矩的可能范围。

开始时A(a,b)初始化为0,然后对图像坐标空间的每⼀个前景点(xi,yi),将参数空间中每⼀个a的离散值代⼊式⼦(2)中,从⽽计算出对应的b值。

每计算出⼀对(a,b),都将对应的数组元素A(a,b)加1,即A(a,b)=A(a,b)+1。

所有的计算结束之后,在参数计算表决结果中找到A(a,b)的最⼤峰值,所对应的a0、b0就是原图像中共线点数⽬最多(共A(a,b)个共线点)的直线⽅程的参数;接下来可以继续寻找次峰值和第3峰值和第4峰值等等,它们对应于原图中共线点略少⼀些的直线。

Hough变换讲解

Hough变换讲解

%Hough变换 clc;clear;close all f=imread('D:\dj.jpg');%若是彩色图片转灰度化 if length(size(f))>2 f=rgb2gray(f); end %figure(1)subplot(121);imshow(f);%利用edge函数进行边缘检测 j=edge(f,'Sobel');subplot(122);imshow(j); [row,col]=size(j); pinfang=round((row*row+col*col)^0.5); A=zeros(2*pi nfang,180);for m=1:row for n=1:col if j(m,n)>0for thera=1:180r=thera/180*pi; %角度转弧度rho=round(m*cos(r)+n*sin(r));%ρ=cosθ+sinθ rho=rho+pinfang+1;%-l:l转换到1:2l+1 A(rho,thera)=A(rho,thera)+1; end end end end[rho,thera]=find(A>40);%交点超过60条线的点,ma,na为参数空间的坐标点 nma=length(rho); for i=1:nma hold onm=1:row; %rho=ma(i)-1; r=thera(i)/180*pi;n=(rho(i)-pinfang-m*cos(r))/(0.00001+sin(r)); plot(n,m,'r'); end%Hough变换 clc;clear;close all f=imread('D:\dj.jpg');%若是彩色图片转灰度化 if length(size(f))>2 f=rgb2gray(f); end %figure(1)subplot(121);imshow(f);%利用edge函数进行边缘检测 j=edge(f,'Sobel');subplot(122);imshow(j); [row,col]=size(j); pinfang=round((row*row+col*col)^0.5); A=zeros(2*pi nfang,180);for m=1:row for n=1:col if j(m,n)>0for thera=1:180r=thera/180*pi; %角度转弧度rho=round(m*cos(r)+n*sin(r));%ρ=cosθ+sinθ rho=rho+pinfang+1;%-l:l转换到1:2l+1 A(rho,thera)=A(rho,thera)+1; end end end end[rho,thera]=find(A>40);%交点超过60条线的点,ma,na为参数空间的坐标点 nma=length(rho); for i=1:nma hold onm=1:row; %rho=ma(i)-1; r=thera(i)/180*pi;n=(rho(i)-pinfang-m*cos(r))/(0.00001+sin(r)); plot(n,m,'r'); endclc;clear; %% 录入图像并显示f=imread('D:\dj2.jpg');%读入彩色图像,注意不能使用灰度图像f=rgb2gray(f);%将彩色图像转换为灰度图像, f=im2double(f); figure();subplot(2,2,1);imshow(f);title('原图'); %% 提取图像边缘 [m,n]=size(f);%得到图像矩阵行数m,列数n for i=3:m-2for j=3:n-2%处理领域较大,所以从图像(3,3)开始,在(m-2,n-2)结束 l(i,j)=-f(i-2,j)-f(i-1,j-1)-2*f(i-1,j)-f(i-1,j+1)-f(i,j-2)-2*f(i,j-1)+16*f(i,j)-2*f(i,j+1)-f(i,j+2)-f(i+1,j -1)-2*f(i+1,j)-f(i+1,j+1)-f(i+2,j);%LoG算子 end endsubplot(2,2,2);imshow(l);title('LoG算子提取图像边缘'); %% 滤波 [m,n]=size(l); for i=2:m-1 for j=2:n-1y(i,j)=l(i-1,j-1)+l(i-1,j)+l(i-1,j+1)+l(i,j-1)+l(i,j)+l(i,j+1)+l(i+1, j-1)+l(i+1,j)+l(i+1,j+1);y(i,j)=y(i,j)/9; %LoG算子提取边缘后,对结果进行均值滤波以去除噪声,为下一步hough变换提取直线作准备 end endsubplot(2,2,3);imshow(y);title('均值滤波器处理后') %% 二值化 q=im2uint8(y); [m,n]=size(q); for i=1:m for j=1:nif q(i,j)>80; %设置二值化的阈值为80q(i,j)=255; %对图像进行二值化处理,使图像边缘更加突出清晰 else q(i,j)=0; end end subplot(2,2,4);imshow(q);title('二值化处理后'); %% 检测直线%Hough变换检测直线,使用(a,p)参数空间,a∈[0,180],p∈[0,2d] a=180; %角度的值为0到180度d=round(sqrt(m^2+n^2)); %图像对角线长度为p的最大值 s=zeros(a,2*d); %存储每个(a,p)个数z=cell(a,2*d); %用元胞存储每个被检测的点的坐标 for i=1:mfor j=1:n%遍历图像每个点if(q(i,j)==255)%只检测图像边缘的白点,其余点不检测 for k=1:ap = round(i*cos(pi*k/180)+j*sin(pi*k/180));%对每个点1到180度遍历一遍,取得经过该点的所有直线的p值(取整)if(p > 0)%若p大于0,则将点存储在(d,2d)空间s(k,d+p)=s(k,d+p)+1;%(a,p)相应的累加器单元加一 z{k,d+p}=[z{k,d+p},[i,j]'];%存储点坐标 elseap=abs(p)+1;%若p小于0,则将点存储在(0,d)空间 s(k,ap)=s(k,ap)+1;%(a,p)相应的累加器单元加一 z{k,ap}=[z{k,ap},[i,j]'];%存储点坐标 end end end end end for i=1:afor j=1:d*2 %检查每个累加器单元中存储数量 if(s(i,j) >70) %将提取直线的阈值设为70 lp=z{i,j};%提取对应点坐标for k=1:s(i,j)%对满足阈值条件的累加器单元中(a,p)对应的所有点进行操作 o(lp(1,k),lp(2,k),1)=255; %每个点R分量=255,G分量=0,B分量=0 o(lp(1,k),lp(2,k),2)=0; o(lp(1,k),lp(2,k),3)=0; %结果为在原图上对满足阈值要求的直线上的点赋红色 end end end endfigure,imshow(o);title('hough变换提取直线'); rotf = imrotate(f,33,'crop');%ͼÏñÌ«´ó£¬²Ã¼ô BW = edge(rotf,'canny'); [H,T,R] = hough(BW); imshow(H,[],'XData',T,'YData',R,'InitialMagnification','fit'); xlabel('\theta'), ylabel('\rho'); axis on, axis normal, hold on;P = houghpeaks(H,7,'threshold',ceil(0.3*max(H(:)))); x = T(P(:,2)); y = R(P(:,1));plot(x,y,'s','color','white');% Find lines and plot themlines = houghlines(BW,T,R,P,'FillGap',5,'MinLength',7); figure, imshow(rotf), hold on max_len = 0;for k = 1:length(lines)xy = [lines(k).point1; lines(k).point2];plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green'); % plot beginnings and ends of linesplot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow'); plot(xy(2,1),xy(2,2),'x','LineWidth',2,' Color','red'); % determine the endpoints of the longest line segment len = norm(lines(k).point1 - lines(k).point2); if ( len > max_len) max_len = len; xy_long = xy; end end% highlight the longest line segmentplot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','cyan');f=imread('D:\dj.jpg');%读入彩色图像,注意不能使用灰度图像 o=f; %保留彩色原图f=rgb2gray(f);%将彩色图像转换为灰度图像, f=im2double(f); figure();subplot(2,2,1);imshow(o);title('原图');[m,n]=size(f);%得到图像矩阵行数m,列数n for i=3:m-2 for j=3:n-2%处理领域较大,所以从图像(3,3)开始,在(m-2,n-2)结束l(i,j)=-f(i-2,j)-f(i-1,j-1)-2*f(i-1,j)-f(i-1,j+1)-f(i,j-2)-2*f(i,j-1)+16*f(i,j)-2*f(i,j+1)-f(i,j+2)-f(i+1,j-1) -2*f(i+1,j)-f(i+1,j+1)-f(i+2,j);%LoG算子end endsubplot(2,2,2);imshow(l);title('LoG算子提取图像边缘');[m,n]=size(l); for i=2:m-1 for j=2:n-1y(i,j)=l(i-1,j-1)+l(i-1,j)+l(i-1,j+1)+l(i,j-1)+l(i,j)+l(i,j+1)+l(i+1,j-1)+l(i+1,j)+l(i+1,j+1);y(i,j)=y(i,j)/9; %LoG算子提取边缘后,对结果进行均值滤波以去除噪声,为下一步hough变换提取直线作准备 end endsubplot(2,2,3);imshow(y);title('均值滤波器处理后')q=im2uint8(y); [m,n]=size(q); for i=1:m for j=1:nif q(i,j)>80; %设置二值化的阈值为80q(i,j)=255; %对图像进行二值化处理,使图像边缘更加突出清晰 elseq(i,j)=0; end end endsubplot(2,2,4);imshow(q);title('二值化处理后'); %Hough变换检测直线,使用(a,p)参数空间,a∈[0,180],p∈[0,2d] a=180; %角度的值为0到180度d=round(sqrt(m^2+n^2)); %图像对角线长度为p的最大值 s=zeros(a,2*d); %存储每个(a,p)个数z=cell(a,2*d); %用元胞存储每个被检测的点的坐标 for i=1:mfor j=1:n%遍历图像每个点if(q(i,j)==255)%只检测图像边缘的白点,其余点不检测 for k=1:a p = round(i*cos(pi*k/180)+j*sin(pi*k/180));%对每个点从1到180度遍历一遍,取得经过该点的所有直线的p值(取整)if(p > 0)%若p大于0,则将点存储在(d,2d)空间s(k,d+p)=s(k,d+p)+1;%(a,p)相应的累加器单元加一 z{k,d+p}=[z{k,d+p},[i,j]'];%存储点坐标 elseap=abs(p)+1;%若p小于0,则将点存储在(0,d)空间 s(k,ap)=s(k,ap)+1;%(a,p)相应的累加器单元加一 z{k,ap}=[z{k,ap},[i,j]'];%存储点坐标 end end end end endfor i=1:afor j=1:d*2 %检查每个累加器单元中存储数量 if(s(i,j) >70) %将提取直线的阈值设为70 lp=z{i,j};%提取对应点坐标for k=1:s(i,j)%对满足阈值条件的累加器单元中(a,p)对应的所有点进行操作o(lp(1,k),lp(2,k),1)=255; %每个点R分量=255,G分量=0,B分量=0o(lp(1,k),lp(2,k),2)=0;o(lp(1,k),lp(2,k),3)=0; %结果为在原图上对满足阈值要求的直线上的点赋红色end end end endfigure,imshow(o);title('hough变换提取直线');clc;clear;i=imread('D:\dj.jpg');imshow(i)figurei=rgb2gray(i);i_hight=size(i,1);i_width=size(i,2);% i_edge=edge(i,'robert');i_hough=zeros(600,360);for y=1:i_hightfor x=1:i_widthif i(y,x)==0 %坐标系转换for l=1:360r=x*cos(l*pi/180)+y*sin(l*pi/180);w=fix(r)+300; %修正为正整数i_hough(w,l)=i_hough(w,l)+1;endendendendm=max(max(i_hough));i_hough=(i_hough./m); %亮度调整threshold=0.75; %设置直线亮度阈值ih_hight=size(i_hough,1);ih_width=size(i_hough,2);temp=zeros(20,20);count=0;for y=1:ih_hight %找那些亮度高的直线for x=1:ih_width/2if i_hough(y,x)>thresholdcount = count+1;temp(count,1) = x;temp(count,2) = y;endendendimshow(i)hold onfor i=1:count %画呀话% y=kx+bk = tan(temp(i,1)*pi/180);b = (temp(i,2)-300)/sin(temp(i,1)*pi/180);for j=1:360x(j)=j;y(j)=-x(j)/k+b;endplot(x,y)hold onendaxis equalfigureimshow(i_hough)clc;clear;img=imread('D:\dj.jpg');% imshow(img)% figureimg=rgb2gray(img);i_hight=size(img,1);i_width=size(img,2);% i_edge=edge(img,'robert');% figure% imshow(img)i_hough=zeros(800,360);for y=1:i_hightfor x=1:i_widthif img(y,x)==0 %坐标系转换for l=1:360r=x*cos(l*pi/180)+y*sin(l*pi/180);w=fix(r)+400; %修正为正整数i_hough(w,l)=i_hough(w,l)+1;endendendendm=max(max(i_hough));i_hough=(i_hough./m); %亮度调整figureimshow(i_hough)threshold=0.50; %---------------------------设置直线亮度阈值ih_hight=size(i_hough,1);ih_width=size(i_hough,2);temp=zeros(100,2);count=0;for y=1:ih_hight %找那些亮度高的直线for x=1:ih_width/2if i_hough(y,x)>thresholdcount = count+1;temp(count,1) = x;temp(count,2) = y;endendend% 调和高亮点while(1)flag = 0;for i=1:countif flag==0for j=i+1:countdis = sqrt((temp(i,1)-temp(j,1))^2 + (temp(i,2)-temp(j,2))^2);if dis<50 %---------------------------调和半径flag = 1;temp(i,1)=(temp(i,1)+temp(j,1))/2;temp(i,2)=(temp(i,2)+temp(j,2))/2;temp(j,:)=[];count = count-1;break;endendendendif flag == 0break;endendfigureimshow(img)hold onfor i=1:count %画呀话% y=kx+bk = tan(temp(i,1)*pi/180);b = (temp(i,2)-400)/sin(temp(i,1)*pi/180); %-400是为了反修正for j=1:360x(j)=j;y(j)=-x(j)/k+b;endplot(x,y)hold onendaxis equalaxis([0,400,0,400]);function Img_hough = hough_s(‘D:\Img, jpg’)%该函数实现hough变换提取直线的功能。

pythonhough变换检测直线的实现方法

pythonhough变换检测直线的实现方法

pythonhough变换检测直线的实现⽅法1 原理2 检测步骤将参数空间(ρ,θ) 量化成m*n(m为ρ的等份数,n为θ的等份数)个单元,并设置累加器矩阵,初始值为0;对图像边界上的每⼀个点(x,y)带⼊ρ=xcosθ+ysinθ,求得每个θ对应的ρ值,并在ρ和θ所对应的单元,将累加器加1,即:Q(i,j)=Q(i,j)+1;检验参数空间中每个累加器的值,累加器最⼤的单元所对应的ρ和θ即为直⾓坐标系中直线⽅程的参数。

3 接⼝image:⼆值图像,canny边缘检测输出。

这⾥是result。

rho: 以像素为单位的距离精度,这⾥为1像素。

如果想要检测的线段更多,可以设为0.1。

theta:以弧度为单位的⾓度精度,这⾥为numpy.pi/180。

如果想要检测的线段更多,可以设为0.01 * numpy.pi/180。

threshod: 阈值参数,int类型,超过设定阈值才被检测出线段,这⾥为10。

minLineLength:线段以像素为单位的最⼩长度。

maxLineGap:同⼀⽅向上两条线段判定为⼀条线段的最⼤允许间隔。

4 代码及结果import osimport numpy as npimport cv2from PIL import Image, ImageEnhanceimport mathdef img_processing(img):# 灰度化gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)# canny边缘检测edges = cv2.Canny(binary, 50, 150, apertureSize=3)return edgesdef line_detect(img):img = Image.open(img)img = ImageEnhance.Contrast(img).enhance(3)# img.show()img = np.array(img)result = img_processing(img)# 霍夫线检测lines = cv2.HoughLinesP(result, 1, 1 * np.pi/180, 10, minLineLength=10, maxLineGap=5)# print(lines)print("Line Num : ", len(lines))# 画出检测的线段for line in lines:for x1, y1, x2, y2 in line:cv2.line(img, (x1, y1), (x2, y2), (255, 0, 0), 1) passimg = Image.fromarray(img, 'RGB')img.show()if __name__ == "__main__":line_detect("1.jpg")pass原图如下:检测结果:以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

霍夫变换(Hough)

霍夫变换(Hough)

霍夫变换(Hough)⼀、霍夫变换(Hough) A-基本原理⼀条直线可由两个点A=(X1,Y1)和B=(X2,Y2)确定(笛卡尔坐标)另⼀⽅⾯,也可以写成关于(k,q)的函数表达式(霍夫空间):对应的变换可以通过图形直观表⽰:变换后的空间成为霍夫空间。

即:笛卡尔坐标系中⼀条直线,对应霍夫空间的⼀个点。

反过来同样成⽴(霍夫空间的⼀条直线,对应笛卡尔坐标系的⼀个点):再来看看A、B两个点,对应霍夫空间的情形:⼀步步来,再看⼀下三个点共线的情况:可以看出如果笛卡尔坐标系的点共线,这些点在霍夫空间对应的直线交于⼀点:这也是必然,共线只有⼀种取值可能。

如果不⽌⼀条直线呢?再看看多个点的情况(有两条直线):其实(3,2)与(4,1)也可以组成直线,只不过它有两个点确定,⽽图中A、B两点是由三条直线汇成,这也是霍夫变换的后处理的基本⽅式:选择由尽可能多直线汇成的点。

看看,霍夫空间:选择由三条交汇直线确定的点(中间图),对应的笛卡尔坐标系的直线(右图)。

到这⾥问题似乎解决了,已经完成了霍夫变换的求解,但是如果像下图这种情况呢?k=∞是不⽅便表⽰的,⽽且q怎么取值呢,这样不是办法。

因此考虑将笛卡尔坐标系换为:极坐标表⽰。

在极坐标系下,其实是⼀样的:极坐标的点→霍夫空间的直线,只不过霍夫空间不再是[k,q]的参数,⽽是的参数,给出对⽐图:是不是就⼀⽬了然了?给出霍夫变换的算法步骤:对应code:1 function [ Hough, theta_range, rho_range ] = naiveHough(I)2 %NAIVEHOUGH Peforms the Hough transform in a straightforward way.3 %4 [rows, cols] = size(I);56 theta_maximum = 90;7 rho_maximum = floor(sqrt(rows^2 + cols^2)) - 1;8 theta_range = -theta_maximum:theta_maximum - 1;9 rho_range = -rho_maximum:rho_maximum;1011 Hough = zeros(length(rho_range), length(theta_range));12for row = 1:rows13for col = 1:cols14if I(row, col) > 0 %only find: pixel > 015 x = col - 1;16 y = row - 1;17for theta = theta_range18 rho = round((x * cosd(theta)) + (y * sind(theta))); %approximate19 rho_index = rho + rho_maximum + 1;20 theta_index = theta + theta_maximum + 1;21 Hough(rho_index, theta_index) = Hough(rho_index, theta_index) + 1;22 end23 end24 end25 end其实本质上就是:交点怎么求解呢?细化成坐标形式,取整后将交点对应的坐标进⾏累加,最后找到数值最⼤的点就是求解的,也就求解出了直线。

hough变换提取椭圆

hough变换提取椭圆

hough变换提取椭圆任意椭圆方程表达式| x 二a cos :cos 二-b sin :sin = p y = a cos a sin 日+ b sin 。

cos 日+ q步骤:1、读入图片(图片大小为256沢256 ),将图片二值化并提取边缘(用edge);2、设置一个5维的参数空间并使初值为0;3、对边缘点集中的每一点进行hough变换,如果p、q在图像范围内,则hough_space(p, q, a, b,日)=hough_space(p, q, a, b,日)十 1 ;4、在参数空间中寻找超过阈值的p, q, a, b^,就是椭圆的参数;5、再对椭圆参数进行求精;(直接讲下面的程序复制到.m文件里,再改a、b、theta参数运行)程序:椭圆提取(图片大小256*256)f1=imread('你的图片.JPG' ); % 读入要提取椭圆的图片imshow(fl)f2=im2bw(f1,0.72); %二值化f3=im2ui nt8(f2);figureimshow(f3)BW=edge (f3, 'ca nn y' ,[0,0.7],0.9); %提取边缘figureimshow(BW)size_a = round((a_max-a_min)/step_a)+1;size_b = round((b_max-b_min)/step_b)+1; size_theta=round((theta_max-theta_min)/step_theta)+1; size_angle = round(2*pi/step_angle);hough_space = zeros(m,n,size_a,size_b,size_theta); % 初值为 0 [cols,rows] = find(BW); ecount = size(rows);% Hough%图像空间 (x,y) 对应到参数空间 (a,b,p 、q 、 theta)% p = x-a*cos(angle)*cos(theta)+b*sin(angle)*sin(theta) % q = y-a*cos(angle)*sin(theta)-b*sin(angle)*cos(theta) %rows(i) 行坐标for i=1:ecountfor a=1:size_afor b=1:size_bfor theta=1:size_thetafor k=1:size_angle%hough 变换p = round(rows(i)-(a_min+(a-1)*step_a)*cos(k*step_angle)*cos(theta_min+(t heta-1)*step_theta)+(b_min+(b-1)*step_b)*sin(k*step_angle)*sin(theta_ min+(theta-1)*step_theta));q = round(cols(i)-(a_min+(a-1)*step_a)*cos(k*step_angle)*sin(theta_min+(t heta-1)*step_theta)-(b_min+(b-1)*step_b)*sin(k*step_angle)*cos(theta_ min+(theta-1)*step_theta));if (p>0&p<=m&q>0&q<=n)hough_space(p,q,a,b,theta) = [n,m] = size(BW); a_max=80;a_min=70;b_max=50; %b b_min=40; step_a=2; %step_b=2;theta_min=-pi/18; %theta theta_max=pi/9; step_theta=pi/60; step_angle=1; yz =0.82; % %a 为椭圆长轴,范围需要自己根据图片中的椭圆形状确定 为椭圆短轴 卜【/■ 步长 倾斜角 阈值(自己定)设定 5维的参数空间并使%find —找出非零元素的索引hough_space(p,q,a,b,theta)+1;endendendendendend% 搜索超过阈值的聚焦点max_para = max(max(max(max(max(hough_space)))));index = find(hough_space>max_para*yz); %find —找出hough_space 值的缩引并存入index中大于阈length = size(index);hough_circle1=zeros(m,n); %确定为椭圆上的点的坐标hough_circle2=zeros(m,n);%找出峰值对应的参数空间坐标for k=1:lengthpar5 = floor((index(k)-1)/(m*n*size_a*size_b))+1;%theta 增量par4 = floor((index(k)-(par5-1)*(m*n*size_a*size_b))/(m*n*size_a))+1;%b增量par3 = floor((index(k)-(par5-1)*(m*n*size_a*size_b)-(par4-1)*(m*n*size_a))/( m*n))+1; %a 增量par2 = floor((index(k)-(par5-1)*(m*n*size_a*size_b)-(par4-1)*(m*n*size_a)-(par3-1)*(m* n))/m)+1; %p增量par1 = index(k)-(par5-1)*(m*n*size_a*size_b)-(par4-1)*(m*n*size_a)-(par3-1)* (m* n)-(par2-1)*m; %q 增量par5=theta_min+(par5-1)*step_theta;par4 = b_min+(par4-1)*step_b;par3 = a_min+(par3-1)*step_a;theta(k)=par5;b(k)=par4;a(k)=par3;q(k)=par2;p(k)=par1;end %求出两圆参数平均值[row1 col1]=size(p); count=1; theta=sort(theta); p=sort(p);q=sort(q); a=sort(a); b=sort(b); THETA(count)=theta(1); P(count)=p(1); A(count)=a(1);B(count)=b(1); Q(count)=q(1); for t=1:1:col1 if abs(P(count)-p(t))<=10THETA(count)=(theta(t)+THETA(count))/2; A(count)=(a(t)+A(count))/2;B(count)=(b(t)+B(count))/2; P(count)=(p(t)+P(count))/2; Q(count)=(q(t)+Q(count))/2;elsecount=count+1;THETA(count)=theta(t);A(count)=a(t);B(count)=b(t);P(count)=p(t);Q(count)=q(t);endendTHETAABPQ%绘制椭圆TYZ=zeros(1,2);TYY=zeros(1,2);ct_z=1;ct_y=1;for i=1:ecountifrou nd(((rows(i)-P(1))*cos (THETA(1))+(cols(i)-Q(1))*si n( THETA(1))f2/(A⑴A2)+(-(rows(i)-P(1))*si n(T HETA(1))+(cols(i)-Q(1))*cos(THETA(1)))A 2/(B(1)A2))<1.5 ... & rou nd(((rows(i)-P(1))*cos (THETA(1))+(cols(i)-Q(1))*si n( THETA(1))f2/ (A(1f2)+(-(rows(i)-P(1))*si n(THETA⑴)+(cols(i)-Q(1))*cos (THETA(1))) A2/(B(1)A2))>0.5TYY(ct_y,1)=rows(i);TYY(ct_y,2)=cols(i); hough_circle1(cols(i),rows(i))=1;ct_y=ct_y+1;endif round(((rows(i)-P(2))*cos(THETA(2))+(cols(i)-Q(2))*sin(THETA(2)))A2/( A(2)A2)+(-(rows(i)-P(2))*sin(THETA(2))+(cols(i)-Q(2))*cos(THETA(2)))A 2/(B(2)A2))<1.5 ...&round(((rows(i)-P(2))*cos(THETA(2))+(cols(i)-Q(2))*sin(THETA(2)))A2/ (A(2)A2)+(-(rows(i)-P(2))*sin(THETA(2))+(cols(i)-Q(2))*cos(THETA(2))) A2/(B(2)A2))>0.5TYZ(ct_z,1)=rows(i);TYZ(ct_z,2)=cols(i); hough_circle2(cols(i),rows(i))=1;ct_z=ct_z+1;endendfigureimshow(hough_circle1),title( '? i 2a? a 1?')figureimshow(hough_circle2),title( '? i 2a?a 1?' )%分别计算两个椭圆的参数[row_TYZ,col_TYZ]=size(TYZ);for i1=1:1:row_TYZWTZ(i1,:)=[TYZ(i1,1)A2 TYZ(i1,1)*TYZ(i1,2) TYZ(i1,2)A2 TYZ(i1,1) TYZ(i1,2) 1; ];end[v_z1,d_z1]=svd(WTZ'*WTZ); v_z1=vpa(v_z1,8) d_z1=double(d_z1);[row_TYY,col_TYY]=size(TYY);for j1=1:1:row_TYYWTY(j1,:)=[TYY(j1,1)A2 TYY(j1,1)*TYY(j1,2) TYY(j1,2)A2 TYY(j1,1) TYY(j1,2) 1; ]; end[v_y1,d_y1]=svd(WTY'*WTY); v_y1=vpa(v_y1,8)d_y1=double(d_y1);在原图上绘制拟合椭圆,以查看拟合精度f1=imread( ' 你的图片.JPG' );f2=im2bw(f1,0.72);f3=im2uint8(f2);BW=edge (f3, 'canny' ,[0,0.7],0.9);%绘制左边椭圆for i2=1:1:256for j2=1:1:256if0<double(.25527789e-4*i2A2-.62429860e-5*i2*j2+.52621684e-4*j2A2-.86887797e-2*i2-.78888347e-2*j2+.99993113) ...&double(.25527789e-4*i2A2-.62429860e-5*i2*j2+.52621684e-4*j2A2-.86887797e-2*i2-.78888347e-2*j2+.99993113)<0.01f1(j2,i2)=0;f2(j2,i2)=0;BW(j2,i2)=1;endendend%绘制右边椭圆for i3=1:1:256for j3=1:1:256if0<double(.46540784e-4*i3A2+.19567656e-4*i3*j3+.10878161e-3*j3A2-.91806184e-2*i3-.20209638e-1*j3+.99975361) ...&double(.46540784e-4*i3A2+.19567656e-4*i3*j3+.10878161e-3*j3A2-.91806 184e-2*i3-.20209638e-1*j3+.99975361)<0.01f1(j3,i3)=0;f2(j3,i3)=0;BW(j3,i3)=1;endend endfigure imshow(fl) figure imshow(f2) figure imshow(BW)最后效果。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验内容1.拍摄一张包含硬币、橡皮等物品的照片,通过Hough 变换检测出圆形的硬币个数并区分不同半径的硬币。

最终计算出照片中的总钱数。

解:Hough 变换的实质是对图像进行坐标的变换,将图像空间的线条变为参数空间的聚集点,从而将原始图像中检测给定形状的曲线问题,变成寻找参数空间中的峰点的问题。

它不仅可以检测直线,而且可以很方便地检测圆、椭圆和抛物线等形状。

由于这里需要检测圆形的硬币,所以下面给出检测圆的具体方法:因为圆的图像空间方程为:222()()x a y b r -+-=,我们需要通过Hough 变换,将图像空间(,)x y 对应到参数空间(,,)a b r ,然后对其进行累加完成检测。

但是显然这种方法的计算量是非常大的,所以一般都是先对灰度图像进行边缘提取,利用边界像素的灰度梯度信息估计出下式中的角度θ,以此来降低计算量:cos cos a x r b y r θθ=-*⎧⎨=-*⎩ (1)一般在检测过程中需要对图像进行预处理,使得检测更加准确和容易。

检测过程如下所示:○1真彩色图像转为灰度图像; ○2去除噪声,进行中值滤波; ○3转为二值图像,利用边缘算子进行图像边缘提取; ○4最后进行图像的平滑和填充。

这里处理的图像并没有太多噪声,所以处理的时候略去了中值滤波的步骤,直接对边缘提取后的图像进行Hough 变换检测圆形。

根据式(1),我们需要对半径r 和角度θ进行搜索,所以这里应该首先设置半径和角度方向的搜索步长step_r 和step_angle ,接着给出半径搜索的最大和最小值,当然这两个数值需要根据经验来自己确定。

最后就可以根据这些确定半径和角度的最大搜索次数。

由于Hough 变换需要用到稀疏矩阵,也即首先得找到图像矩阵中的非零量,针对这些非零量进行进一步的处理。

这个操作可以直接通过Matlab 中的find 语句来实现:>> [rows, cols] = find(BW); %找出矩阵中的非零值接着只需要根据式(1)计算出对应参数空间的参数a b和,根据,a b的范围确定hough空间累加器hough_adder是否自增。

由于这里的图像中不止一个圆形,所以不能直接利用hough_adder中的最大值来确定半径,需要设置一定的阈值thre来确定一定半径的圆,当阈值设置合理后才可以找出图像中的圆。

接着对阈值范围内的点进行搜索,当满足圆周内外各5个像素点时,该点可以认为是我们搜寻的圆上的点。

对其相应的坐标赋1即可。

经过上述的步骤,便通过hough变换的思想将图像的中的圆给检测出来了。

并且可以将圆心坐标和圆的半径都显示出来。

那接下来按照题目的意思是需要我们计算总的钱数,所以首先需要区分一元和五角的硬币,也就是区分圆的半径。

由于这里我们设置搜索出来的圆的半径是逐渐递增的,所以只需要判断在两个相邻点之间圆的半径是否存在跳变即可。

因为如果是不同的一元硬币,那么他们的半径即使相差一点也不会很多。

这样我们便可以得出首先将圆分成两类(这里只考虑一元和五角的两种情况),然后在每一类中再寻找半径相似的圆位于不同坐标的个数,也就是同样面值的硬币的个数了。

可以通过如下代码实现:是不同的硬币了。

接着在相同的硬币中,通过循环搜索当前半径和之前像素点的半径,当横纵坐标相差都小于10的时候可以认为是同一个点,也即是同一个硬币,否则将硬币数加一。

最后通过统计得到的总硬币数计算出总钱数。

下面先给出具体代码:clc,clear allImage = imread('final.bmp');imshow(Image),title('原始图像');Gray = rgb2gray(Image);bw = im2bw(Gray); % 先转为二值图像BW = edge(bw); % 然后提取边缘figureimshow(BW),title('图像边缘);step_r = 1; % 设定半径搜索步长step_angle = 0.1; % 设定角度搜索步长r_min = 50; % 最小半径和最大半径,确定搜索范围r_max = 100;thre = 0.8; % 设定阈值%***************hough变换*********************************[m, n] = size(BW);Count_r = round((r_max-r_min)/step_r)+1; % °半径最大搜索次数hough_adder = zeros(m, n, Count_r);Count_angle = round(2*pi/step_angle); % 角度最大搜索次数[rows, cols] = find(BW); % 找出矩阵中的非零值count = size(rows); % 计算非零值的个数for Count_Num = 1 : countfor Count_R = 1 : Count_rfor Count_Angle = 1 : Count_anglea =round(rows(Count_Num)-(r_min+(Count_R-1)*step_r)*cos(Count_Angle*step_angle ));b =round(cols(Count_Num)-(r_min+(Count_R-1)*step_r)*sin(Count_Angle*step_angle) );isTrue = (a>0 && a<=m && b>0 && b<=n);if(isTrue)hough_adder(a,b,Count_R) = hough_adder(a,b,Count_R) + 1;% 参数空间累加器加1endendendendmax_hough_adder = max(max(max(hough_adder))); % 计算最大值index = find(hough_adder >= max_hough_adder * thre); % 设定阈值length = size(index);hough_circle=zeros(m,n);for Count_Num = 1 : countfor Count_Length = 1 : lengthpar3 = floor(index(Count_Length)/(m*n));par2 = floor((index(Count_Length)-par3*(m*n))/m);par1 = index(Count_Length)-par3*(m*n)-par2*m;isTrue =(rows(Count_Num)-par1)^2+(cols(Count_Num)-par2-1)^2<(r_min+par3*step_r)^2+5 &&(rows(Count_Num)-par1)^2+(cols(Count_Num)-par2-1)^2>(r_min+par3*step_r)^2-5 ;if(isTrue)hough_circle(rows(Count_Num),cols(Count_Num)) = 1;endendendfigureimshow(hough_circle),title('圆形检测结果');for Count_Length = 1 : lengthpar3 = floor(index(Count_Length)/(m*n));par2 = floor((index(Count_Length)-par3*(m*n))/m);par1 = index(Count_Length)-par3*(m*n)-par2*m;par3 = r_min+par3*step_r;para(:,Count_Length) = [par1,par2,par3]; % 存储符合条件的圆坐标以及半径end%***************计算总钱数*********************************total_wu = 0;for idx = 1 : length-1total_wu = total_wu + para(3,idx);if (para(3,idx+1) - para(3,idx) > 5)break;endendtotal_yi = sum(para(3,:)) - total_wu;Ave_wu = total_wu / idx;Ave_yi = total_yi / (length(1,1)-idx);% 计算五角硬币的个数count_wu = 1;j = 1;for i = 2 : idxif j<= i-1if abs(para(1,i) - para(1,j)) < 10 && abs(para(2,i) - para(2,j)) < 10count_wu = count_wu;elsecount_wu = count_wu + 1;break ;endendend% 计算一元硬币的个数count_yi = 1;j = idx+1;for i = (idx+2) : lengthif j <= i-1if abs(para(1,i) - para(1,j)) < 10 && abs(para(2,i) - para(2,j)) < 10 count_yi = count_yi;elsecount_yi = count_yi + 1;break ;endendendtotal_money = count_wu * 0.5 + count_yi * 1 % 计算总钱数下面给出处理的图像:原始图像图1 原始图像图像边缘最后给出检测出的图像如下:从图3可以看出此时检测结果还是很准确的,当然这个和我们所选取的阈值thre 有关,如果thre 选择偏大,则无法将三个圆都检测出来,相反,如果thre 偏小,那么可能检测出来图形中其他的圆(比如该图像中的U 盘上的圆圈)。

所以说这里的关键就是阈值的选择,我是通过不断调试得出这个比较理想的结果的。

最后,在屏幕上打印总的钱数为:>> total_money =2.5000一、 实验小结由于老师上课只讲述了直线的hough 变换,所以在一开始做这题的时候感觉有点无从下手。

后来查阅了冈萨雷斯的图像处理书对hough 变换有了一个更深刻图2 提取的图像边缘检测结果图3 检测出圆轮廓的了解。

其实质是将图像空间转为参数空间,然后进行累加计数,累加的最大值便是所求的半径。

相关文档
最新文档