C语言canny算子函数 c语言里的算法( 三 )


//该点可能是边界点
if(dTmp=dTmp1dTmp=dTmp2)
{
pNSRst[nPos] = 128;
}
else
{
//不可能是边界点
pNSRst[nPos] = 0;
}
}
}
}
}
}
// 统计pMag的直方图,判定阈值
void EstimateThreshold(int *pMag, SIZE sz, int *pThrHigh, int *pThrLow, LPBYTE pGray,
double dRatHigh, double dRatLow)
{
LONG y,x,k;
//该数组的大小和梯度值的范围有关,如果采用本程序的算法
//那么梯度的范围不会超过pow(2,10)
int nHist[256];
//可能边界数
int nEdgeNum;
//最大梯度数
int nMaxMag;
int nHighCount;
nMaxMag = 0;
//初始化
for(k=0;k256;k++)
{
nHist[k] = 0;
}
//统计直方图,利用直方图计算阈值
for(y=0;ysz.cy;y++)
{
for(x=0;xsz.cx;x++)
{
if(pGray[y*sz.cx+x]==128)
{
nHist[pMag[y*sz.cx+x]]++;
}
}
}
nEdgeNum = nHist[0];
nMaxMag = 0;
//统计经过“非最大值抑制”后有多少像素
for(k=1;k256;k++)
{
if(nHist[k] != 0)
{
nMaxMag = k;
}
//梯度为0的点是不可能为边界点的
//经过non-maximum suppression后有多少像素
nEdgeNum += nHist[k];
}
//梯度比高阈值*pThrHigh 小的像素点总书目
nHighCount = (int)(dRatHigh * nEdgeNum + 0.5);
k=1;
nEdgeNum = nHist[1];
//计算高阈值
while((k(nMaxMag-1))(nEdgeNumnHighCount))
{
k++;
nEdgeNum += nHist[k];
}
*pThrHigh = k;
//低阈值
*pThrLow = (int)((*pThrHigh) * dRatLow + 0.5);
}
//利用函数寻找边界起点
void Hysteresis(int *pMag, SIZE sz, double dRatLow, double dRatHigh, LPBYTE pResult)
{
LONG y,x;
int nThrHigh,nThrLow;
int nPos;
//估计TraceEdge 函数需要的低阈值,以及Hysteresis函数使用的高阈值
EstimateThreshold(pMag, sz,nThrHigh,nThrLow,pResult,dRatHigh,dRatLow);
//寻找大于dThrHigh的点,这些点用来当作边界点,
//然后用TraceEdge函数跟踪该点对应的边界
for(y=0;ysz.cy;y++)
{
for(x=0;xsz.cx;x++)
{
nPos = y*sz.cx + x;
//如果该像素是可能的边界点,并且梯度大于高阈值 , 
//该像素作为一个边界的起点
if((pResult[nPos]==128)(pMag[nPos] = nThrHigh))
{
//设置该点为边界点
pResult[nPos] = 255;
TraceEdge(y,x,nThrLow,pResult,pMag,sz);
}
}
}
//其他点已经不可能为边界点
for(y=0;ysz.cy;y++)
{
for(x=0;xsz.cx;x++)
{
nPos = y*sz.cx + x;
if(pResult[nPos] != 255)
{
pResult[nPos] = 0;
}
}
}
}
//根据Hysteresis 执行的结果,从一个像素点开始搜索,搜索以该像素点为边界起点的一条边界的
//一条边界的所有边界点 , 函数采用C语言canny算子函数了递归算法
//从(x,y)坐标出发 , 进行边界点的跟踪 , 跟踪只考虑pResult中没有处理并且可能是边界
//点的像素(=128),像素值为0表明该点不可能是边界点,像素值为255表明该点已经是边界点
void TraceEdge(int y, int x, int nThrLow, LPBYTE pResult, int *pMag, SIZE sz)
{
//对8邻域像素进行查询
int xNum[8] = {1,1,0,-1,-1,-1,0,1};
int yNum[8] = {0,1,1,1,0,-1,-1,-1};
LONG yy,xx,k;
for(k=0;k8;k++)
{
yy = y+yNum[k];
xx = x+xNum[k];
if(pResult[yy*sz.cx+xx]==128pMag[yy*sz.cx+xx]=nThrLow )
{
//该点设为边界点
pResult[yy*sz.cx+xx] = 255;
//以该点为中心再进行跟踪
TraceEdge(yy,xx,nThrLow,pResult,pMag,sz);

推荐阅读