以下是代码:
bool CDIB::Hough(SLineInfo *pInfoRet, int nLineRet)
{
int i, j;
// 极坐标域中的最大Rho和Theta
int nMaxDist = sqrt(bih.biHeight*bih.biHeight + bih.biWidth*bih.biWidth);
int nMaxAngle = 90;
// 为极坐标域分配空间
int nAreaNum = nMaxAngle * nMaxDist * 2;
int *pTransArea = new int[nAreaNum];
memset(pTransArea, 0, nAreaNum * sizeof(int));
// 转化到极坐标域
int nAngle, nDist; //极坐标下的角度和极径
double fRadian; //弧度
for(i = 0; i < bih.biHeight; i ++)
{
for(j=0; j<bih.biWidth; j++)
{
if(m_pdata[bih.biWidth*i+j] == 255)
{
for(nAngle = 0; nAngle < nMaxAngle; nAngle ++)
{
fRadian = nAngle*2*PI/180.0; //转化为弧度
nDist = (j*cos(fRadian) + i*sin(fRadian)); //计算极径
if(nDist >= 0)//正半周
{
pTransArea[nDist*nMaxAngle + nAngle] ++;
}
else//负半周
{
nDist = fabs(nDist);
pTransArea[nMaxAngle * nMaxDist + nDist*nMaxAngle + nAngle] ++;
}
}//for nAngle
}//if
}//for j
}//for i
SMaxValue MaxValue1;
//清零时角度和极径的范围
int nMaxDisAllow = 20;
int nMaxAngleAllow = 5;
for(int nLine=0; nLine<nLineRet; nLine++) //寻找前nLineRet个峰值点
{
// 寻找最大点
MaxValue1.nValue = 0;
for(i=0; i<nAreaNum; i++)
{
if(pTransArea[i] > MaxValue1.nValue)
{
MaxValue1.nValue = pTransArea[i];
MaxValue1.nAngle = i;
}
}
if(MaxValue1.nValue == 0) //找不到可能的共线点
{
return FALSE;
}
if(MaxValue1.nAngle < nMaxAngle * nMaxDist)
{
MaxValue1.nDist = MaxValue1.nAngle/nMaxAngle;
MaxValue1.nAngle = MaxValue1.nAngle%nMaxAngle;
}
else
{
MaxValue1.nAngle -= nMaxAngle * nMaxDist;
MaxValue1.nDist = MaxValue1.nAngle/nMaxAngle;
MaxValue1.nDist *= -1;
MaxValue1.nAngle = MaxValue1.nAngle%nMaxAngle;
}
// 将结果保存至pInfoRet结构指针
pInfoRet[nLine].nAngle = MaxValue1.nAngle*2;
pInfoRet[nLine].nDist = MaxValue1.nDist;
pInfoRet[nLine].nPixels = MaxValue1.nValue;
if(pInfoRet[nLine].nDist < 0)
{
pInfoRet[nLine].nAngle = pInfoRet[nLine].nAngle - 180;
pInfoRet[nLine].nDist = pInfoRet[nLine].nDist*(-1);
}
// 将附近点清零,为寻找下一个峰值做准备
for(nDist = (-1)*nMaxDisAllow; nDist <= nMaxDisAllow; nDist ++)
{
for(nAngle = (-1)*nMaxAngleAllow; nAngle <= nMaxAngleAllow; nAngle ++)
{
int nThisDist = MaxValue1.nDist + nDist;
int nThisAngle = MaxValue1.nAngle + nAngle;
nThisAngle *= 2;
if(nThisAngle < 0 && nThisAngle >= -180)
{
nThisAngle += 180;
nThisDist *= -1;
}
if(nThisAngle >= 180 && nThisAngle < 360)
{
nThisAngle -= 180;
nThisDist *= -1;
}
if(fabs(nThisDist) <= nMaxDist
&& nThisAngle >= 0 && nThisAngle <= nMaxAngle*2)
{
nThisAngle /= 2;
if(nThisDist >= 0)
{
pTransArea[nThisDist*nMaxAngle + nThisAngle] = 0;
}
else
{
nThisDist = fabs(nThisDist);
pTransArea[nMaxDist*nMaxAngle + nThisDist*nMaxAngle + nThisAngle] = 0;
}
}
}//for nAngle
}//for nDist
}//for nLine
delete []pTransArea; //释放极坐标域空间
return TRUE;
}
void CIMAGEPROCESSINGView::OnHough()
{
// TODO: Add your command handler code here
int wide,height;
wide=m_dib.GetDIBWidth();
height=m_dib.GetDIBHeight();
int nLineCount=5;
SLineInfo * pLines = new SLineInfo[nLineCount];
// Hough变换
m_dib.Hough(pLines, nLineCount);
// 输出结果
for (int k = 0; k<nLineCount; k++)//处理第k条直线
{
//扫描图像绘制直线
for(int i = 0; i <height; i++)
{
for(int j = 0;j <wide; j++)
{
int nDist;
//根据theta计算rho
nDist = (int) (j*cos(pLines[k].nAngle*PI/180.0) + i*sin(pLines[k].nAngle*PI/180.0));
if((fabs(nDist - pLines[k].nDist)<=3) && (m_dib.m_pdata[wide*i+j]==255)) //如果点(j, i)在直线上
m_dib.m_pdata[wide*i+j]=100;
}//for j
}//for i
}//for k
for(int i = 0; i <height; i++)
{
for(int j = 0;j <wide; j++)
{
if(m_dib.m_pdata[wide*i+j]!=100)
m_dib.m_pdata[wide*i+j]=0;
else
m_dib.m_pdata[wide*i+j]=255;
}//for j
}//for i
// 将结果返回给文档类
m_dib.UpdateData();
Invalidate();
}
7 个解决方案
#1
太长了,不高兴看,你看一下hough变换的原理。你检测出来的直线应该能够统计出一共经过了多少个点,如果你想找一条直线的话,那么就是经过点的数量最多的那条直线了,可以一次统计出来。或者你可以设置一个阈值T,当经过直线的点的数量大于T的时候就画出来。
#2
恩,我知道是这个原理,就是不知道代码如何写,这个hough变换的代码变量有点多,我都不知道那个直线的数据存储在哪个变量里的
#3
"C:\Program Files\OpenCV\samples\cpp\houghlines.cpp"
#4
楼上这位大哥是啥意思?
#5
让你看opencv自带的例程,是吧 赵老师
#6
可以用matlab试试看
#7
是
#1
太长了,不高兴看,你看一下hough变换的原理。你检测出来的直线应该能够统计出一共经过了多少个点,如果你想找一条直线的话,那么就是经过点的数量最多的那条直线了,可以一次统计出来。或者你可以设置一个阈值T,当经过直线的点的数量大于T的时候就画出来。
#2
恩,我知道是这个原理,就是不知道代码如何写,这个hough变换的代码变量有点多,我都不知道那个直线的数据存储在哪个变量里的
#3
"C:\Program Files\OpenCV\samples\cpp\houghlines.cpp"
#4
楼上这位大哥是啥意思?
#5
楼上这位大哥是啥意思?
让你看opencv自带的例程,是吧 赵老师
#6
可以用matlab试试看
#7
楼上这位大哥是啥意思?
让你看opencv自带的例程,是吧 赵老师
是