用hough变换算法

用hough变换算法,第1张

霍夫变换在图像处理里常用来在黑白图像里检测直线,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,holdoncolormap(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=0fork=1:length(lines)%绘制各条线xy=[lines(k).point1lines(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(len>max_len)max_len=lenxy_long=xyendend%以红色线高亮显示最长的线plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','red')其中,同一条线段由于某些原因(比如光照、噪音等)变成了不连续的两条较短的线段,所以要进项合并,至于多少长度的才合并成同一条直线,是依据不同的图像而言的,由fillgap参数决定。而有些线段可能是噪声,所以小于7的舍去,这个也么有标准,需要根据不同的图像而定。

clc

clear

close

%BW=imread('D:\picture\9dafa605d53eea243812bb29.jpg')

rgb=imread('lena.jpg')

BW=rgb2gray(rgb)

thresh=[0.01,0.17]

sigma=2%定义高斯参数

f = edge(double(BW),'canny',thresh,sigma)

figure(1),

imshow(f,[])

title('canny 边缘检测')

[H, theta, rho]= hough(f,'RhoResolution', 0.5)

axis on,

axis normal

xlabel('\theta'),ylabel('rho')

p=houghpeaks(H,5)

hold on

lines=houghlines(f,theta,rho,p)

figure,

imshow(f,[]),

title('Hough Transform Detect Result'),

hold on

for k=1:length(lines)

xy=[lines(k).point1lines(k).point2]

plot(xy(:,1),xy(:,2),'LineWidth',4,'Color',[.6 .6 .6])

end

/*************************************************************************

*

* 函数名称:

* HoughDIB()

*

* 参数:

* LPSTR lpDIBBits- 指向源DIB图像指针

* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)

* LONG lHeight - 源图像高度(象素数)

* 返回值:

* BOOL - 运算成功返回TRUE,否则返回FALSE。

*

* 说明:

* 该函数用于对检测图像中的平行直线。如果图像中有两条平行的直线,则将这两条平行直线

* 提取出来。

*

* 要求目标图像为只有0和255两个灰度值的灰度图像。

************************************************************************/

BOOL WINAPI HoughDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)

{

// 指向源图像的指针

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)

if (hNewDIBBits == NULL)

{

// 分配内存失败

return FALSE

}

// 锁定内存

lpNewDIBBits = (char * )LocalLock(hNewDIBBits)

// 初始化新分配的内存,设定初始值为255

lpDst = (char *)lpNewDIBBits

memset(lpDst, (BYTE)255, lWidth * lHeight)

//计算变换域的尺寸

//最大距离

iMaxDist = (int) sqrt(lWidth*lWidth + lHeight*lHeight)

//角度从0-180,每格2度

iMaxAngleNumber = 90

//为变换域分配内存

hTransArea = LocalAlloc(LHND, lWidth * lHeight * sizeof(int))

if (hNewDIBBits == NULL)

{

// 分配内存失败

return FALSE

}

// 锁定内存

lpTransArea = (char * )LocalLock(hTransArea)

// 初始化新分配的内存,设定初始值为0

lpTrans = (char *)lpTransArea

memset(lpTrans, 0, lWidth * lHeight * sizeof(int))

// 计算图像每行的字节数

lLineBytes = WIDTHBYTES(lWidth * 8)

for(j = 0j <lHeightj++)

{

for(i = 0i <lWidthi++)

{

// 指向源图像倒数第j行,第i个象素的指针

lpSrc = (char *)lpDIBBits + lLineBytes * j + i

//取得当前指针处的像素值,注意要转换为unsigned char型

pixel = (unsigned char)*lpSrc

//目标图像中含有0和255外的其它灰度值

if(pixel != 255 &&*lpSrc != 0)

return FALSE

//如果是黑点,则在变换域的对应各点上加1

if(pixel == 0)

{

//注意步长是2度

for(iAngleNumber=0iAngleNumber<iMaxAngleNumberiAngleNumber++)

{

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=0iDist<iMaxDistiDist++)

{

for(iAngleNumber=0iAngleNumber<iMaxAngleNumberiAngleNumber++)

{

if((int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber)>MaxValue1.Value)

{

MaxValue1.Value = (int)*(lpTransArea+iDist*iMaxAngleNumber+iAngleNumber)

MaxValue1.Dist = iDist

MaxValue1.AngleNumber = iAngleNumber

}

}

}

//将第一个最大值点附近清零

for (iDist = -9iDist <10iDist++)

{

for(iAngleNumber=-1iAngleNumber<2iAngleNumber++)

{

if(iDist+MaxValue1.Dist>=0 &&iDist+MaxValue1.Dist<iMaxDist \

&&iAngleNumber+MaxValue1.AngleNumber>=0 &&iAngleNumber+MaxValue1.AngleNumber<=iMaxAngleNumber)

{

*(lpTransArea+(iDist+MaxValue1.Dist)*iMaxAngleNumber+\

(iAngleNumber+MaxValue1.AngleNumber))=0

}

}

}

//找到第二个最大值点

for (iDist=0iDist<iMaxDistiDist++)

{

for(iAngleNumber=0iAngleNumber<iMaxAngleNumberiAngleNumber++)

{

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 = 0j <lHeightj++)

{

for(i = 0i <lWidthi++)

{

// 指向缓存图像倒数第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

}

}

}

// 复制腐蚀后的图像

memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight)

// 释放内存

LocalUnlock(hNewDIBBits)

LocalFree(hNewDIBBits)

// 释放内存

LocalUnlock(hTransArea)

LocalFree(hTransArea)

// 返回

return TRUE

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7796184.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-10
下一篇 2023-04-10

发表评论

登录后才能评论

评论列表(0条)

保存