/************************************************************************* * * \函数名称: * TraceEdge() * * \输入参数: * int x - 跟踪起点的x坐标 * int y - 跟踪起点的y坐标 * int nLowThd - 判断一个点是否为边界点的低阈值 * unsigned char *pUnchEdge - 记录边界点的缓冲区 * int *pnMag - 梯度幅度图 * int nWidth - 图象数据宽度 * * \返回值: * 无 * * \说明: * 递归调用 * 从(x,y)坐标出发,进行边界点的跟踪,跟踪只考虑pUnchEdge中没有处理并且 * 可能是边界点的那些象素(=128),象素值为0表明该点不可能是边界点,象素值 * 为255表明该点已经被设置为边界点,不必再考虑 * * ************************************************************************* */ void TraceEdge (int y, int x, int nLowThd, unsigned char *pUnchEdge, int *pnMag, int nWidth) { // 对8邻域象素进行查询 int xNb[8] = {1, 1, 0,-1,-1,-1, 0, 1} ; int yNb[8] = {0, 1, 1, 1,0 ,-1,-1,-1} ; int yy ; int xx ; int k ; for(k=0; k<8; k++) { yy = y + yNb[k] ; xx = x + xNb[k] ; // 如果该象素为可能的边界点,又没有处理过 // 并且梯度大于阈值 if(pUnchEdge[yy*nWidth+xx] == 128 && pnMag[yy*nWidth+xx]>=nLowThd) { // 把该点设置成为边界点 pUnchEdge[yy*nWidth+xx] = 255 ; // 以该点为中心进行跟踪 TraceEdge(yy, xx, nLowThd, pUnchEdge, pnMag, nWidth); } } }
//边缘递归生长函数 void TraceEdge(int x, int y, float grd) { //对8邻域像素进行查询 int yy, xx, k; for (k = 0; k < 8; k++) { xx = x + a8i[k]; yy = y + a8j[k]; //以该点为中心再进行跟踪 if (xx < g_listk.rows - 1 && yy < g_listk.cols - 1 && xx>0 && yy>0) { if (g_srcGrad.at<float>(xx, yy) > 9 && g_imgFlg.at<int>(xx, yy) == 0) { //该点设为边界点 g_edge[2].at<float>(xx, yy) = 255; g_imgFlg.at<int>(xx, yy) = 1; TraceEdge(xx, yy, 10); //g_srcGrad.at<float>(xx, yy) } } else { cout << "out of range!\n"; } } }
/************************************************************************* * * \函数名称: * Hysteresis() * * \输入参数: * int *pnMag - 梯度幅度图 * int nWidth - 图象数据宽度 * int nHeight - 图象数据高度 * double dRatioLow - 低阈值和高阈值之间的比例 * double dRatioHigh - 高阈值占图象象素总数的比例 * unsigned char *pUnchEdge - 记录边界点的缓冲区 * * \返回值: * 无 * * \说明: * 本函数实现类似“磁滞现象”的一个功能,也就是,先调用EstimateThreshold * 函数对经过non-maximum处理后的数据pUnchSpr估计一个高阈值,然后判断 * pUnchSpr中可能的边界象素(=128)的梯度是不是大于高阈值nThdHigh,如果比 * 该阈值大,该点将作为一个边界的起点,调用TraceEdge函数,把对应该边界 * 的所有象素找出来。最后,当整个搜索完毕时,如果还有象素没有被标志成 * 边界点,那么就一定不是边界点。 * ************************************************************************* */ void Hysteresis(int *pnMag, int nWidth, int nHeight, double dRatioLow, double dRatioHigh, unsigned char *pUnchEdge) { // 循环控制变量 int y; int x; int nThdHigh ; int nThdLow ; int nPos; // 估计TraceEdge需要的低阈值,以及Hysteresis函数使用的高阈值 EstimateThreshold(pnMag, nWidth, nHeight, &nThdHigh, &nThdLow, pUnchEdge,dRatioHigh, dRatioLow); // 这个循环用来寻找大于nThdHigh的点,这些点被用来当作边界点,然后用 // TraceEdge函数来跟踪该点对应的边界 for(y=0; y<nHeight; y++) { for(x=0; x<nWidth; x++) { nPos = y*nWidth + x ; // 如果该象素是可能的边界点,并且梯度大于高阈值,该象素作为 // 一个边界的起点 if((pUnchEdge[nPos] == 128) && (pnMag[nPos] >= nThdHigh)) { // 设置该点为边界点 pUnchEdge[nPos] = 255; TraceEdge(y, x, nThdLow, pUnchEdge, pnMag, nWidth); } } } // 那些还没有被设置为边界点的象素已经不可能成为边界点 for(y=0; y<nHeight; y++) { for(x=0; x<nWidth; x++) { nPos = y*nWidth + x ; if(pUnchEdge[nPos] != 255) { // 设置为非边界点 pUnchEdge[nPos] = 0 ; } } } }
//利用函数寻找边界起点 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;y<sz.cy;y++) { for(x=0;x<sz.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;y<sz.cy;y++) { for(x=0;x<sz.cx;x++) { nPos = y*sz.cx + x; if(pResult[nPos] != 255) { pResult[nPos] = 0; } } } }
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;k<8;k++) { yy = y+yNum[k]; xx = x+xNum[k]; if(pResult[yy*sz.cx+xx]==128 && pMag[yy*sz.cx+xx]>=nThrLow ) { //该点设为边界点 pResult[yy*sz.cx+xx] = 255; //以该点为中心再进行跟踪 TraceEdge(yy,xx,nThrLow,pResult,pMag,sz); } } }