|
Posted on 2007-04-30 00:01 cacar 阅读(466) 评论(0) 编辑 收藏 引用 所属分类: 图像
看别人的代码真的很辛苦,e文的资料,作者功底一般都比较nb,好在关键的地方总有些注释的。国人更nb,看过得很多源码根本就没有注释,只好自己边理解边写注释,费解死。
Mean Shift做图像分割的资料能找到的少之又少,看Rutgers上的论文,对我这个小本科来说还是有难度的。昨天上pudn淘了篇均值漂移分割图像的代码,只能做灰度图的,完全没有注释,想改一下却有最后分割的几句看不太懂,还没注释。。。
说明:下文注释不一定对哦,我的极其有限的理解,而已。
1 //MeanShift 分割滤波算法 2 //pImg 图像数据指针 3 //width height 宽度 高度 4 //bUseFilter true - filter false - image segmentation 5 //w - window size 6 // h1 space variance 7 // h2 range variance 8 void MeanShiftFilterOrSegmentation(bool bUseFilter,BYTE *pImg,int width,int height,int w,int h1,double h2,BYTE *pResImg) 9  { 10 BYTE *pCur,*CovG; 11 bool find,bOutOfImg; 12 int count,fwin = 2*w+1,top=-1,size=width*height; 13 int *G,*CovX,*CovY,x,y,i,j,new_x,new_y,new_g,old_x,old_y,old_g; 14 double sum,grayDif,*PosWeight,*pWCur,numerator_x,numerator_y,numerator_g,denominator,g; 15 //memory alloc 16 G = new int[width*height]; 17 CovX = new int[width*height]; 18 CovY = new int[width*height]; 19 CovG = new BYTE[width*height]; 20 PosWeight = new double[fwin*fwin]; 21 //distance weight 22 23 // 根据到当前点的距离设置窗口邻域内各点的权重 24 // weight = exp(-0.5*(distence^2)/(h1^2)); 25 for(pWCur=PosWeight,sum=0.0,i=0;i<fwin;i++) 26  { 27 for(j=0;j<fwin;j++,pWCur++) 28  { 29 *pWCur = exp(-0.5 * ( (i-w)*(i-w)+(j-w)*(j-w) )/(h1*h1) ); 30 } 31 } 32 //Iteration Until Convergence 33 // 逐行扫描,y为行号,pCur指向图像数据 34 for(pCur=pImg,y=0;y<height;y++) 35  { 36 // 逐列扫描,x为列号 37 for(x=0;x<width;x++,pCur++) 38  { 39 // old_x纪录当前像元列号 40 old_x = x; 41 // old_y记录当前像元行号 42 old_y = y; 43 // old_g指向当前像元灰度值 44 old_g = *pCur; 45 // 初始化计数器 46 count=0; 47 // 扫描图像越界标志,超出图像范围时为true 48 bOutOfImg = false; 49 while(count<1000) 50  { 51 count++; 52 // 53 numerator_x = numerator_y = numerator_g = denominator = 0.0; 54 // 用i=old_y-w,i<old_y+w+1限定窗口行值范围,pWCur指向窗口权重数组 55 for(pWCur=PosWeight,i=old_y-w;i<old_y+w+1;i++) 56  { 57 // 用j=old_x-w,j<old_x+w+1限定窗口列值范围,当j++时扫描当前行的 58 // 下一个像元,同时pWCur指向权重数组中下一个值. 59 // 当扫描完窗口内当前行后,由于列值j不再满足j<old_x+w+1条件,结束 60 // 本层循环,由i++将扫描像元推向窗口的下一行 61 for(j=old_x-w;j<old_x+w+1;j++,pWCur++) 62  { 63 // 64 if(i<0 || i>height-1 || j<0 || j>width-1 ) continue; 65 // *(pImg+i*width+j)是窗口内当前像元的灰度值, 66 // grayDif为窗口内当前像元灰度值与pCur指向的作为窗口中心的 67 // 当前点灰度值 68 grayDif = (*(pImg+i*width+j) - old_g); 69 // grayDif = grayDif^2; 70 grayDif = grayDif*grayDif; 71 // 用g表示当前窗口点与窗口中心样本点的差异(带权重) 72 // g为平移向量 ?????? 73 // g为差异???? 74 // exp(-0.5*grayDif/(h2*h2)) 高斯核??? 75 // g = *pWCur*exp(-0.5*grayDif/(h2*h2)); 76 // *pWCur为当前窗口位置的灰度值 77 g = *pWCur*exp(-0.5*grayDif/(h2*h2)); 78 // numerator_x是列值平移向量的和 79 numerator_x += j*g; 80 // numerator_y是行值平移向量的和 81 numerator_y += i*g; 82 // 83 numerator_g += *(pImg+i*width+j)*g; 84 // denominator为平移向量(距离,权重~)的和 85 denominator += g; 86 } 87 } 88 new_x = (int)(numerator_x/denominator+0.5); 89 new_y = (int)(numerator_y/denominator+0.5); 90 new_g = (int)(numerator_g/denominator+0.5); 91 if(new_y<0 || new_y>height-1 || new_x<0 || new_x>width-1 ) 92  {//超出图像范围 93 new_x = old_x; 94 new_y = old_y; 95 new_g = old_g; 96 bOutOfImg = true; 97 break; 98 } 99 // 如果窗体移动距离<1.1 ??? 100 // 则结束迭代 101 if( abs(new_x-old_x) + abs(new_y-old_y) < 1.1) break; 102 // 变换窗口中心,继续迭代 103 old_x = new_x; 104 old_y = new_y; 105 old_g = new_g; 106 } 107 if(count>999 ) printf("No Converge!\n"); 108 if(bOutOfImg) printf("Out Of Image!\n"); 109 // 将收敛点的列号(new_x),行号(new_y),灰度(new_g)赋给ConX,ConY,ConV中 110 // 的相应点 111 *(CovX + y*width + x) = new_x; 112 *(CovY + y*width + x) = new_y; 113 *(CovG + y*width + x) = new_g; 114 } 115 } 116 //仅用于图像分割 117 if(!bUseFilter) 118  { 119 for(i=0;i<size;i++) 120 { 121 for(find=false,j=0;j<=top;j++) 122 { 123 if( abs(*(CovG+i) - *(G+j))<h2 ) 124 { 125 find = true; 126 *(CovG+i) = *(G+j); 127 break; 128 } 129 } 130 if(!find) 131 { 132 top++; 133 *(G+top) = *(CovG+i); 134 } 135 } 136 } 137 memcpy(pResImg,CovG,width*height); 138 delete G; 139 delete CovX; 140 delete CovY; 141 delete CovG; 142 delete PosWeight; 143 } 144 145
EDISON的分割流程有个大概的印象了,Filter里面的一大块比较费力,希望可以尽快搞得定。
|