很多站长朋友们都不太清楚hough直线检测php,今天小编就来给大家整理hough直线检测php,希望对各位有所帮助,具体内容如下:
本文目录一览: 1、 如何用Hough变换检测一幅二值图像中的最长直线 2、 求助编程实现hough变换检测直线 3、 Hough变换算法检测特定长度的直线 4、 HoughLinesP(霍夫变换直线检测) 5、 Python OpenCV 霍夫(Hough Transform)直线变换检测原理,图像处理第 33 篇博客 6、 Hough变换检测直线求助 如何用Hough变换检测一幅二值图像中的最长直线楼主可以试一下这段代码,希望能对你有帮助
I = imread('E:\pic\2\编号\4.bmp');%读取图像
rotI = imrotate(I,-4,'crop');%图像旋转33°
subplot(221),
fig1 = imshow(I);%在第一幅子图中绘制旋转后的图像
BW = edge(I,'canny');%使用canny方法检测目标边界
subplot(222),
imshow(BW);%显示边界的二值图像
[H,theta,rho] = hough(BW);%hough变换
subplot(223),
imshow(imadjust(mat2gray(H)),[],'XData',theta,'YData',rho,...
'InitialMagnification','fit');%显示hough变换的变换矩阵
xlabel('\theta (degrees)'), ylabel('\rho');
axis on, axis normal, hold on;
colormap(hot)%颜色映射表
P = houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));%hough变换的极值点
x = theta(P(:,2));
y = rho(P(:,1));
plot(x,y,'s','color','black');%画出极值点
lines = houghlines(BW,theta,rho,P,'FillGap',...
5,'MinLength',7);%返回直线的端点%
subplot(224),
imshow(rotI), 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(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 = len;%确定最长的直线
xy_long = xy;
end
end
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,...
'Color','cyan');%绘制最长的直线
求助编程实现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; iAngleNumber<iMaxAngleNumber; 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; iDist<iMaxDist;iDist++)
{
for(iAngleNumber=0; iAngleNumber<iMaxAngleNumber; 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; iAngleNumber<2; iAngleNumber++)
{
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=0; iDist<iMaxDist;iDist++)
{
for(iAngleNumber=0; iAngleNumber<iMaxAngleNumber; 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变换算法检测特定长度的直线I=imread('图像名称’);
figure;imshow(I);title('原图')
I=double(I);
BW=edge(I,'canny');
[A,B,C]=hough(BW);
imshow(A,[],'XData',B,'Ydata',C,'InitialMagnification','fit'); title('hough变换图像')
xlabel('\theta'), ylabel('\rho');
axis normal,hold on;
P=houghpeaks(A,5);
x=B(P(:,2));y=C(P(:,1));
plot(x,y,'s','color','white');
lines=houghlines(O,B,C,P);
figure,imshow(N),hold on
max_len=0;
for k=1:要检测的长度值
xy=[lines(k).point1;lines(k).point2];
plot(xy(:,1),xy(:,2),'color','green');
plot(xy(1,1),xy(1,2),'color','yellow');
plot(xy(2,1),xy(2,2),'color','red');
len=norm(lines(k).point1-lines(k).point2);
if (len>max_len)
max_len=len;
xy_long=xy;
end
end
plot(xy_long(:,1),xy_long(:,2),'color','cyan');
HoughLinesP(霍夫变换直线检测)霍夫变换 是一种特征检测(feature extraction),被广泛应用在 图像分析 (image analysis)、计算机视觉(computer vision)以及数位影像处理(digital image processing)。霍夫变换是用来辨别找出物件中的特征,例如:线条。他的 算法 流程大致如下,给定一个物件、要辨别的形状的种类,算法会在参数空间(parameter space)中执行投票来决定物体的形状,而这是由累加空间(accumulator space)里的局部最大值(local maximum)来决定。
现在广泛使用的霍夫变换是由RichardDuda和PeterHart在公元1972年发明,并称之为广义霍夫变换(generalizedHoughtransform),广义霍夫变换和更早前1962年的PaulHough的专利有关。经典的霍夫变换是侦测图片中的 直线 ,之后,霍夫变换不仅能识别直线,也能够识别任何形状,常见的有圆形、椭圆形。1981年,因为DanaH.Ballard的一篇期刊论文"Generalizing the Hough transform to detect arbitrary shapes",让霍夫变换开始流行于计算机视觉界。
●源图像
●处理后图像
●函数原型
○c++
○Android
●参数解释
○image:输入图像:8-bit,灰度图
○lines:存储线段极坐标的容器,每一条线由具有四个元素的矢量(x_1,y_1, x_2, y_2) 表示,其中,(x_1, y_1)和(x_2, y_2) 是每个检测到的线段的结束点。
○rho:生成极坐标的像素扫描步长。
○theta:生成极坐标的角度步长,一般是π/180。
○threshold:要”检测” 一条直线所需最少的的曲线交点 。
○minLineLength :默认值0,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来。
○maxLineGap :默认值0,允许将同一行点与点之间连接起来的最大的距离。
●c++中
●Android中
Python OpenCV 霍夫(Hough Transform)直线变换检测原理,图像处理第 33 篇博客霍夫变换(Hough Transform)是图像处理领域中,从图像中识别几何形状的基本方法之一。主要识别具有某些相同特征的几何形状,例如直线,圆形,本篇博客的目标就是从黑白图像中识别出直线。
翻阅霍夫直线变换的原理时候,橡皮擦觉得原理部分需要先略过,否则很容易在这个地方陷进去,但是问题来了,这个原理略过了,直接应用函数,里面有些参数竟然看不懂。例如极坐标,角度扫描范围,这种函数就属于绕不过去的知识点了,所以本文转移方向,死磕原理,下面的博文将语无伦次的为你展示如何学习原理知识。
因为数学知识的贫乏,所以在学习阶段会涉及到很多基础概念的学习,一起来吧。
首先找到相对官方的资料,打开该 地址
下面是一个数学小白对原理的学习经验。
教材说:众所周知,一条直线在图像二维空间可由两个变量表示。
抱歉,小白还真不知道……即使学习过,这些年也早已经还给老师了。
一开始难道要学习笛卡尔坐标系,不,你低估小白的能力了,我第一个查询的是 θ 读作 西塔 ,是一个希腊字母。
什么是笛卡尔坐标系?
这个比较简单,直角坐标系。
斜率和截距
斜率,亦称“角系数”,表示一条直线相对于横坐标轴的倾斜程度。
一条直线与某平面直角坐标系横坐标轴正半轴方向的夹角的正切值即该直线相对于该坐标系的斜率。
如果直线与 x 轴互相垂直,直角的正切直无穷大,故此直线不存在斜率。
对于一次函数 y=kx+b , k 就是该函数图像的斜率。
在学习的时候,也学到如下内容:
截距:对 x 的截距就是 y=0 时, x 的值,对 y 的截距就是 x=0 时, y 的值,
截距就是直线与坐标轴的交点的横(纵)坐标。 x 截距为 a , y 截距 b ,截距式就是: x/a+y/b=1(a≠0且b≠0) 。
斜率:对于任意函数上任意一点,其斜率等于其切线与 x 轴正方向所成的角,即 k=tanα 。 ax+by+c=0中,k=-a/b 。
什么是极坐标系?
关于极坐标系,打开 百度百科 学习一下即可。
重点学到下面这个结论就行:
找资料的时候,发现一个解释的比较清楚的 博客 ,后续可以继续学习使用。
继续阅读资料,看到如下所示的图,这个图也出现在了很多解释原理的博客里面,但是图下面写了一句话
在这里直接蒙掉了,怎么就表示成极坐标系了?上面这个公式依旧是笛卡尔坐标系表示直线的方式呀,只是把 k 和 b 的值给替换掉了。
为何是这样的,具体原因可以参照下图。
<center>chou 图</center>
继续寻找关于霍夫变换的资料,找到一个新的概念 霍夫空间 。
在笛卡尔坐标系中,一条直线可以用公式 表示,其中 k 和 b 是参数,表示的是斜率和截距。
接下来将方程改写为 ,这时就建立了一个基于 k - b 的笛卡尔坐标系。
此时这个新的方程在 k - b 坐标系也有一个新的直线。
你可以在纸上画出这两个方程对应的线和点,如下图所示即可。
<center>chou 图</center>
新的 k - b 坐标系就叫做霍夫空间,这时得到一个结论,图像空间 x - y 中的点 对应了 霍夫空间 k - b 中的一条直线 ,即图像空间的点与霍夫空间的直线发生了对应关系。
如果在图像空间 x - y 中在增加一个点 ,那相应的该点在霍夫空间也会产生相同的点与线的对应关系,并且 A 点与 B 点产生的直线会在霍夫空间相交于一个点。而这个点的坐标值 就是直线 AB 的参数。
如果到这里你掌握了,这个性质就为我们解决直线检测提供了方法,只需要把图像空间的直线对应到霍夫空间的点,然后统计交点就可以达到目的,例如图像空间中有 3 条直线,那对应到霍夫空间就会有 3 个峰值点。
遍历图像空间中的所有点,将点转换到霍夫空间,形成大量直线,然后统计出直线交会的点,每个点的坐标都是图像空间直线方程参数,这时就能得到图像空间的直线了。
上述的内容没有问题,但是存在一种情况是,当直线趋近于垂直时,斜率 k 会趋近于无穷大,这时就没有办法转换了,解决办法是使用法线来表示直线。
上文提及的斜截式如下:
通过第二个公式,可以得到下述公式:
此时,我们可以带入一些数值进行转换。
图像空间有如下的几个点:
转换后的函数,都可以在霍夫空间 θ - ρ (横坐标是 θ ,纵坐标是 ρ )进行表示。
原理这时就比较清晰了:
除了一些数学知识以外,经典的博客我们也有必要记录一下,方便后面学习的时候,进行复盘。
本部分用于记录本文中提及的相关数学原理,后续还要逐步埋坑。
今天涉及了一点点数学知识,能力限制,大家一起学习,有错误的地方,可以在评论区指出,不胜感激。
希望今天的 1 个小时(今天内容有点多,不一定可以看完),你有所收获,我们下篇博客见~
相关阅读
技术专栏
逗趣程序员
Hough变换检测直线求助1 直线是如何表示的?
对于平面中的一条直线,在笛卡尔坐标系中,常见的有点斜式,两点式两种表示方法。然而在hough变换中,考虑的是另外一种表示方式:使用(r,theta)来表示一条直线。其中r为该直线到原点的距离,theta为该直线的垂线与x轴的夹角。如下图所示。
2 如果坐标系中有多个点,又怎样识别出哪些点在一条直线上呢?
使用hough变换来检测直线的思想就是:为每一个点假设n个方向的直线,通常n=180,此时检测的直线的角度精度为1°,分别计算这n条直线的(r,theta)坐标,得到n个坐标点。如果要判断的点共有N个,最终得到的(r,theta)坐标有N*n个。有关这N*n个(r,theta)坐标,其中theta是离散的角度,共有180个取值。
最重要的地方来了,如果多个点在一条直线上,那么必有这多个点在theta=某个值theta_i时,这多个点的r近似相等于r_i。也就是说这多个点都在直线(r_i,theta_i)上。
3 下面拿个例子说明:
如果空间中有3个点,如何判断这三个点在不在一个直线上,如果在,这条直线是的位置为?
这个例子中,对于每个点均求过该点的6条直线的(r,theta)坐标,共求了3*6个(r,theta)坐标。可以发现在theta=60时,三个点的r都近似为80.7,由此可判定这三个点都在直线(80.7,60)上。
通过 r0theta 坐标系可以更直观表示这种关系,如下图:图中三个点的(r,theta)曲线汇集在一起,该交点就是同时经过这三个点的直线。
在实际的直线检测情况中,如果超过一定数目的点拥有相同的(r,theta)坐标,那么就可以判定此处有一条直线。在r0theta 坐标系图中,明显的交汇点就标示一条检测出的直线。
如下图,可以判定出平面上的点共构成了两条直线,即检测出两条直线。
4 代码:
在matlab中提供了hough变换的代码,有hough,houghlines,houghpeaks,具体的使用可以在help中查到。
(II)圆篇
继使用hough变换检测出直线之后,顺着坐标变换的思路,提出了一种检测圆的方法。
1 如何表示一个圆?
与使用(r,theta)来表示一条直线相似,使用(a,b,r)来确定一个圆心为(a,b)半径为 r 的圆。
2 如何表示过某个点的所有圆?
某个圆过点(x1,y1),则有:(x1-a1)^2 + (y1-b1)^2 = r1^2 。
那么过点(x1,y1)的所有圆可以表示为(a1(i),b1(i),r1(i)),其中r1∈(0,无穷),每一个 i 值都对应一个不同的圆,(a1(i),b1(i),r1(i))表示了无穷多个过点(x1,y1)的圆。
3 如何确定多个点在同一个圆上?
如(2)中说明,过点(x1,y1)的所有圆可以表示为(a1(i),b1(i),r1(i)),过点(x2,y2)的所有圆可以表示为(a2(i),b2(i),r2(i)),过点(x3,y3)的所有圆可以表示为(a3(i),b3(i),r3(i)),如果这三个点在同一个圆上,那么存在一个值(a0,b0,r0),使得 a0 = a1(k)=a2(k)=a3(k) 且b0 = b1(k)=b2(k)=b3(k) 且r0 = r1(k)=r2(k)=r3(k),即这三个点同时在圆(a0,b0,r0)上。
关于hough直线检测php的介绍到此就结束了,不知道本篇文章是否对您有帮助呢?如果你还想了解更多此类信息,记得收藏关注本站,我们会不定期更新哦。
查看更多关于hough直线检测php hough直线检测输出的详细内容...