logo资料库

数字图像形状特征提取canny算法源程序.doc

第1页 / 共13页
第2页 / 共13页
第3页 / 共13页
第4页 / 共13页
第5页 / 共13页
第6页 / 共13页
第7页 / 共13页
第8页 / 共13页
资料共13页,剩余部分请下载后查看
canny 算子代码 void CreatGauss(double sigma, double **pdKernel, int *pnWidowSize); void GaussianSmooth(SIZE sz, LPBYTE pGray, LPBYTE pResult, double sigma); void Grad(SIZE sz, LPBYTE pGray, int *pGradX, int *pGradY, int *pMag); void NonmaxSuppress(int *pMag, int *pGradX, int *pGradY, SIZE sz, LPBYTE pNSRst); void EstimateThreshold(int *pMag, SIZE sz, int *pThrHigh, int *pThrLow, LPBYTE pGray, double dRatHigh, double dRatLow); void Hysteresis(int *pMag, SIZE sz, double dRatLow, double dRatHigh, LPBYTE pResult); void TraceEdge(int y, int x, int nThrLow, LPBYTE pResult, int *pMag, SIZE sz); void Canny(LPBYTE pGray, SIZE sz, double sigma, double dRatLow, double dRatHigh, LPBYTE pResult); #include "afx.h" #include "math.h" #include "canny.h" // 一维高斯分布函数,用于平滑函数中生成的高斯滤波系数 void CreatGauss(double sigma, double **pdKernel, int *pnWidowSize) { LONG i; //数组中心点 int nCenter; //数组中一点到中心点距离 double dDis; //中间变量 double dValue; double dSum; dSum = 0; // [-3*sigma,3*sigma] 以内数据,会覆盖绝大部分滤波系数 *pnWidowSize = 1+ 2*ceil(3*sigma);
nCenter = (*pnWidowSize)/2; *pdKernel = new double[*pnWidowSize]; //生成高斯数据 for(i=0;i<(*pnWidowSize);i++) { dDis = double(i - nCenter); dValue = exp(-(1/2)*dDis*dDis/(sigma*sigma))/(sqrt(2*3.1415926)*sigma); (*pdKernel)[i] = dValue; dSum+=dValue; } //归一化 for(i=0;i<(*pnWidowSize);i++) { (*pdKernel)[i]/=dSum; } } //用高斯滤波器平滑原图像 void GaussianSmooth(SIZE sz, LPBYTE pGray, LPBYTE pResult, double sigma) { LONG x, y; LONG i; //高斯滤波器长度 int nWindowSize; //窗口长度 int nLen; //一维高斯滤波器 double *pdKernel; //高斯系数与图像数据的点乘 double dDotMul; //滤波系数总和 double dWeightSum; double *pdTemp; pdTemp = new double[sz.cx*sz.cy];
//产生一维高斯数据 CreatGauss(sigma, &pdKernel, &nWindowSize); nLen = nWindowSize/2; //x 方向滤波 for(y=0;y=0 && (i+x)=0 && (i+y)< sz.cy) { dDotMul += (double)pdTemp[(y+i)*sz.cx+x]*pdKernel[nLen+i]; dWeightSum += pdKernel[nLen+i]; } } pResult[y*sz.cx+x] = (unsigned char)dDotMul/dWeightSum; } }
delete []pdKernel; pdKernel = NULL; delete []pdTemp; pdTemp = NULL; } // 方向导数,求梯度 void Grad(SIZE sz, LPBYTE pGray,int *pGradX, int *pGradY, int *pMag) { LONG y,x; //x 方向的方向导数 for(y=1;y
dSqt2 = pGradY[y*sz.cx + x]*pGradY[y*sz.cx + x]; pMag[y*sz.cx+x] = (int)(sqrt(dSqt1+dSqt2)+0.5); } } } //非最大抑制 void NonmaxSuppress(int *pMag, int *pGradX, int *pGradY, SIZE sz, LPBYTE pNSRst) { LONG y,x; int nPos; //梯度分量 int gx; int gy; //中间变量 int g1,g2,g3,g4; double weight; double dTmp,dTmp1,dTmp2; //设置图像边缘为不可能的分界点 for(x=0;x
pNSRst[nPos] = 0; } else { //当前点的梯度幅度 dTmp = pMag[nPos]; //x,y 方向导数 gx = pGradX[nPos]; gy = pGradY[nPos]; //如果方向导数 y 分量比 x 分量大,说明导数方向趋向于 y 分量 if(abs(gy) > abs(gx)) { //计算插值比例 weight = fabs(gx)/fabs(gy); g2 = pMag[nPos-sz.cx]; g4 = pMag[nPos+sz.cx]; //如果 x,y 两个方向导数的符号相同 //C 为当前像素,与 g1-g4 的位置关系为: //g1 g2 // // if(gx*gy>0) { C g4 g3 g1 = pMag[nPos-sz.cx-1]; g3 = pMag[nPos+sz.cx+1]; } //如果 x,y 两个方向的方向导数方向相反 //C 是当前像素,与 g1-g4 的关系为: // // // else { g2 g1 C g3 g4 g1 = pMag[nPos-sz.cx+1]; g3 = pMag[nPos+sz.cx-1]; } } //如果方向导数 x 分量比 y 分量大,说明导数的方向趋向于 x 分量
else { //插值比例 weight = fabs(gy)/fabs(gx); g2 = pMag[nPos+1]; g4 = pMag[nPos-1]; //如果 x,y 两个方向的方向导数符号相同 //当前像素 C 与 g1-g4 的关系为 // // // if(gx * gy > 0) { g3 g4 C g2 g1 g1 = pMag[nPos+sz.cx+1]; g3 = pMag[nPos-sz.cx-1]; } //如果 x,y 两个方向导数的方向相反 // C 与 g1-g4 的关系为 // // // else { g1 g4 C g2 g3 g1 = pMag[nPos-sz.cx+1]; g3 = pMag[nPos+sz.cx-1]; } } //利用 g1-g4 对梯度进行插值 { dTmp1 = weight*g1 + (1-weight)*g2; dTmp2 = weight*g3 + (1-weight)*g4; //当前像素的梯度是局部的最大值 //该点可能是边界点 if(dTmp>=dTmp1 && dTmp>=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;k<256;k++) { nHist[k] = 0; } //统计直方图,利用直方图计算阈值 for(y=0;y
分享到:
收藏