「hough变换java」hough变换原理
本篇文章给大家谈谈hough变换java,以及hough变换原理对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
用hough变换算法
霍夫变换在图像处理里常用来在黑白图像里检测直线,matlab里有相应的几个函数,使用方便,这里把matlab帮助里介绍的例子演示一下。matlab里霍夫变换主要包含一下三个函数:hough:实现霍夫变换,得到霍夫变换矩阵,用法如下[H,theta,rho]=hough(BW)[H,theta,rho]=hough(BW,ParameterName,ParameterValue)houghpeaks:在霍夫变换矩阵里找极值点peaks=houghpeaks(H,numpeaks)peaks=houghpeaks(,param1,val1,param2,val2)houghlines:从霍夫变换矩阵中提取线段lines=houghlines(BW,theta,rho,peaks)lines=houghlines(,param1,val1,param2,val2)下面以一个例子来看看霍夫变换的效果,代码如下:%测试霍夫变换clcclearcloseall%读取图像I=imread('circuit.tif');rotI=imrotate(I,80,'crop');%旋转33度,保持原图片大小fig1=imshow(rotI);%提取边BW=edge(rotI,'canny');figure,imshow(BW);%霍夫变换[H,theta,rho]=hough(BW);%计算二值图像的标准霍夫变换,H为霍夫变换矩阵,theta,rho为计算霍夫变换的角度和半径值figure,imshow(imadjust(mat2gray(H)),[],'XData',theta,'YData',rho,'InitialMagnification','fit');xlabel('\theta(degrees)'),ylabel('\rho');axison,axisnormal,holdon;colormap(hot)%显示霍夫变换矩阵中的极值点P=houghpeaks(H,50,'threshold',ceil(0.3*max(H(:))));%从霍夫变换矩阵H中提取5个极值点x=theta(P(:,2));y=rho(P(:,1));plot(x,y,'s','color','black');%找原图中的线lines=houghlines(BW,theta,rho,P,'FillGap',18,'MinLength',180);figure,imshow(rotI),holdonmax_len=0;fork=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');%计算线的长度,找最长线段len=norm(lines(k).point1-lines(k).point2);if(lenmax_len)max_len=len;xy_long=xy;endend%以红色线高亮显示最长的线plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','red');其中,同一条线段由于某些原因(比如光照、噪音等)变成了不连续的两条较短的线段,所以要进项合并,至于多少长度的才合并成同一条直线,是依据不同的图像而言的,由fillgap参数决定。而有些线段可能是噪声,所以小于7的舍去,这个也么有标准,需要根据不同的图像而定。
Hough变换
最近在看图像处理的东西,为了检测直线,可以用的一个神奇的东西---Hough变换。
一条直线可以用如下的方程来表示:y=kx+b,k是直线的斜率,b是截距。
图像是一个个离散的像素点构成的,如果在图像中有一条直线,那也是一系列的离散点构成的。那么怎样检测这些离散的点构成了直线呢?
我们再看上面的直线方程:y=kx+b,(x,y)就是点。我们转换下变成:b=-kx+y。我们是不是也可以把(k,b)看作另外一个空间中的点?这就是k-b参数空间。
我们看到,图1中,在x-y图像空间中的一个点,变成了k-b参数空间中的一条直线,而x-y图像空间中的2点连成的直线,变成了k-b参数空间中的一个交点。
如果x-y图像空间中有很多点在k-b空间中相交于一点,那么这个交点就是我们要检测的直线。这就是霍夫变换检测直线的基本原理。
当然,有一个问题需要注意,图像空间中如果一条直线是垂直的,那么斜率k是没有定义的(或者说无穷大)。为了避免这个问题,霍夫变换采用了另一个参数空间:距离-角度参数空间。
平面上的一个点也可以用距离-角度来定义,也就是极坐标:
那么在图像中,每一个点都可以用距离和角度来表达: 但是,使用距离-角度后,点(x,y)与距离,角度的关系变成了:
ρ=xcosθ+ysinθ (1)
x=ρcosθ,xcosθ=ρcosθ^2 (2) y=ρsinθ, ysinθ=ρsinθ^2 (3)
由(2)加(3)便可得到(1)
于是,在新的距离-角度参数空间中,图像中的一个点变成了一个正弦曲线(比如,当x=1,y=1时,ρ=xcosθ+ysinθ=cosθ+2sinθ=根号2*sin(θ+pi/4) ),而不是k-b参数空间中的直线了。这些正弦曲线的交点就是图像空间中我们要检测的直线了。
我们普通图片是的线条可以表示为 y=m0x+b0 ,在霍夫(参数)空间就是一个点
相反,图片上的点在霍夫空间就可以表示为线,我们要检测线条的话,就可以把图像上的每个点转换到霍夫空间去,找到霍夫空间上线条相交的点,就可以确定参数m, b
但是我们知道如果是垂直线的话,它的斜率不存在,那又怎么办呢?
这样就有了另一种直线表达方法 ρ=xcosθ+ysinθ
无论采用xy坐标还是极坐标,原空间的点都对应参数空间的曲线,原空间的直线都对应着参数空间中曲线的交点。如下图所示,可以根据在参数空间中每个grid相交点的出现次数寻找原空间中的直线。
意思就是,属于同一条直线上点在极坐标空间(ρ,θ)必然在一个点上有最强的信号出现,根据此反算到平面坐标中就可以得到直线上各点的像素坐标,从而得到直线。
说了这么多原理,那么对于一张具体的图片,我们如何检测其中的直线呢?
首先对图像边缘检测,二值化(即灰度值为0(黑),灰度值为255(白)),这样我们的图像中就只看到了白色的物体边缘,其他的都是黑的,然后提取出这些灰度值为255(白色)的像素,对每个像素进行Hough变换。
一个像素点在参数空间对应一条正弦曲线(上面的理论说过),也有原图像中的一条直线在参数空间中对应一点(ρ,θ)。这也就是说,找到像素点对应正弦曲线的交点(ρ0,θ0),反变换回来便得到由像素点构成的直线(把ρ0,θ0带入 ρ=xcosθ+ysinθ中,就是ax+by-c=0,这是一条直线啊)。
就说这么多吧,以后有新的体会再补充。
什么是hough变换
Hough变换利用图像空间和Hough参数空间的点-线对偶性,把图像空间中的检测问题转换到参数空间。通过在参数空间里进行简单的累加统计,然后在Hough参数空间寻找累加器峰值的方法检测直线。例如,图1(a)中的九条线段对应于如图1(b)所示的其Hough参数空间的九个累加器峰值。图1(b)中,Hough参数空间的横纵坐标分别为直线极坐标方程:ρ=x×cos(θ) + y×sin(θ) 的两个参数ρ和θ。九个峰值的ρ和θ值唯一的确定其对应线段所在直线的两个参数。并且线段的长度决定坐标(ρ,θ)处的累加值的大小。
求助编程实现hough变换检测直线
/*************************************************************************
*
* 函数名称:
* HoughDIB()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
* LONG lLineBytes - 源图像每行所占的字节数
* WORD wBitsPerPixel - 源图像位深
* LPSTR lpNewDIBBits - 目标图像数据区的指针
*
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用于对检测图像中的平行直线。如果图像中有两条平行的直线,则将这两条平行直线
* 提取出来。
*
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
BOOL WINAPI HoughDIB(LPSTR lpDIBBits,LONG lWidth,LONG lHeight,LONG lLineBytes,
WORD wBitsPerPixel,LPSTR lpNewDIBBits)
{
// 指向源图像的指针
LPSTR lpSrc;
// 指向缓存图像的指针
LPSTR lpDst;
// 指向变换域的指针
LPSTR lpTrans;
// 图像每行的字节数
// LONG lLineBytes;
// 指向缓存DIB图像的指针
//LPSTR lpNewDIBBits;
//HLOCAL hNewDIBBits;
//指向变换域的指针
LPSTR lpTransArea;
HLOCAL hTransArea;
//变换域的尺寸
int iMaxDist;
int iMaxAngleNumber;
//变换域的坐标
int iDist;
int iAngleNumber;
//循环变量
long i;
long j;
//像素值
unsigned char pixel;
//存储变换域中的两个最大值
MaxValue MaxValue1;
MaxValue MaxValue2;
// 暂时分配内存,以保存新图像
//hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
// 初始化新分配的内存,设定初始值为255
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lLineBytes * lHeight);
//计算变换域的尺寸
//最大距离
iMaxDist = (int) sqrt(lWidth*lWidth + lHeight*lHeight);
//角度从0-180,每格2度
iMaxAngleNumber = 90;
//为变换域分配内存
hTransArea = LocalAlloc(LHND, lWidth * lHeight * sizeof(int));
// 锁定内存
lpTransArea = (char * )LocalLock(hTransArea);
// 初始化新分配的内存,设定初始值为0
lpTrans = (char *)lpTransArea;
memset(lpTrans, 0, lWidth * lHeight * sizeof(int));
for(j = 0; j lHeight; j++)
{
for(i = 0;i lWidth; i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if(pixel != 255 *lpSrc != 0)
{
MessageBox(NULL,"目标图像中含有0和255外的其它灰度值","错误",MB_OK);
return FALSE;
}
//如果是黑点,则在变换域的对应各点上加1
if(pixel == 0)
{
//注意步长是2度
for(iAngleNumber=0; iAngleNumberiMaxAngleNumber; iAngleNumber++)
{
iDist = (int) fabs(i*cos(iAngleNumber*2*PI/180.0) + \
j*sin(iAngleNumber*2*PI/180.0));
//变换域的对应点上加1
*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber) = \
*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber) +1;
}
}
}
}
//找到变换域中的两个最大值点
MaxValue1.Value=0;
MaxValue2.Value=0;
//找到第一个最大值点
for (iDist=0; iDistiMaxDist;iDist++)
{
for(iAngleNumber=0; iAngleNumberiMaxAngleNumber; iAngleNumber++)
{
if((int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber)MaxValue1.Value)
{
MaxValue1.Value = (int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber);
MaxValue1.Dist = iDist;
MaxValue1.AngleNumber = iAngleNumber;
}
}
}
//将第一个最大值点附近清零
for (iDist = -9;iDist 10;iDist++)
{
for(iAngleNumber=-1; iAngleNumber2; iAngleNumber++)
{
if(iDist+MaxValue1.Dist=0 iDist+MaxValue1.DistiMaxDist \
iAngleNumber+MaxValue1.AngleNumber=0 iAngleNumber+MaxValue1.AngleNumber=iMaxAngleNumber)
{
*(lpTransArea+(iDist+MaxValue1.Dist)*iMaxAngleNumber+\
(iAngleNumber+MaxValue1.AngleNumber))=0;
}
}
}
//找到第二个最大值点
for (iDist=0; iDistiMaxDist;iDist++)
{
for(iAngleNumber=0; iAngleNumberiMaxAngleNumber; iAngleNumber++)
{
if((int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber)MaxValue2.Value)
{
MaxValue2.Value = (int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber);
MaxValue2.Dist = iDist;
MaxValue2.AngleNumber = iAngleNumber;
}
}
}
//判断两直线是否平行
if(abs(MaxValue1.AngleNumber-MaxValue2.AngleNumber)=2)
{
//两直线平行,在缓存图像中重绘这两条直线
for(j = 0; j lHeight; j++)
{
for(i = 0;i lWidth; i++)
{
// 指向缓存图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
//如果该点在某一条平行直线上,则在缓存图像上将该点赋为黑
//在第一条直线上
iDist = (int) fabs(i*cos(MaxValue1.AngleNumber*2*PI/180.0) + \
j*sin(MaxValue1.AngleNumber*2*PI/180.0));
if (iDist == MaxValue1.Dist)
*lpDst = (unsigned char)0;
//在第二条直线上
iDist = (int) fabs(i*cos(MaxValue2.AngleNumber*2*PI/180.0) + \
j*sin(MaxValue2.AngleNumber*2*PI/180.0));
if (iDist == MaxValue2.Dist)
*lpDst = (unsigned char)0;
}
}
}
// 释放内存
LocalUnlock(hTransArea);
LocalFree(hTransArea);
// 返回
return TRUE;
}
如何用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;subplot
Sobel:算子边缘检测图像
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:ecount
for r=1:size_r
for k=1:size_angle
a = 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(a0a=mb0b=n)
hough_space(a,b,r) = hough_space(a,b,r)+1;
end
end
end
end
max_para = max(max(max(hough_space)));
index = find(hough_space=max_para*p);
length = size(index);
hough_circle = false(m,n);
for i=1:ecount
for k=1:length
par3 = 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;
end
end
end
for k=1:length
par3 = 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];
end
subplot(221),imshow(f);
subplot(222),imshow(BW);
subplot(223),imshow(hough_circle)
关于hough变换java和hough变换原理的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。