
上QQ阅读APP看书,第一时间看更新
4.4.1 图像的标识及特征提取
编程实现
[1] 在Demo1中创建类CCluster以实现模糊聚类的相应功能,在其中添加函数GetFeature(),进行有关图像的标识和特征提取。具体实现代码如代码4-1所示。
代码4-1 GetFeature()函数
void CCluster::GetFeature() { ////////////////////以下对数据区域标号whx///////////////////// BYTE * p_temp; int stop; int i,j; int counter;//记录相互独立的连通区域的个数 int present;//记录当前点的值1,2,...,counter stop=0; counter=0; p_temp=new BYTE[wide*height];//开辟一个临时内存区××××× memset(p_temp,255,wide*height);//置白 //从左到右、从上到下标号 const int T=5;//T为阈值,RGB值小于该阈值被认为是黑 for(i=0; i<wide; i++)//将第零行置白 *(m_pData+(height-1)*wide+i)=255; for(j=0;j<height;j++)//将第零列置白 *(m_pData+(height-j-1)*wide)=255; for( j=1;j<height-1;j++) // 从第一行开始搜索 { if(stop==1)//判断连通区是否太多 break; for( i=1;i<wide-1;i++) // 从第一列开始搜索 { if(counter>255) { AfxMessageBox("连通区数目太多,请减少样品个数"); stop=1; return; } if(*(m_pData+(height-j-1)*wide+i)<T)//若当前点为黑点 { if(*(m_pData+(height-j-1+1)*wide+i+1)<T)//若当前点的右上点为黑点 { *(p_temp+(height-j-1)*wide+i)=*(p_temp+(height-j-1+1) *wide+i+1); //当前点标号应该与右上点相同 present=*(p_temp+(height-j-1+1)*wide+i+1);//记录当前点的标号 if(*(m_pData+(height-j-1)*wide+i-1)<T && *(p_temp+ (height-j-1)*wide+i-1)!=present)//左前与右上点都为黑且标号不同 { int temp=*(p_temp+(height-j-1)*wide+i-1);//记录左前点的标号 if (present>temp)//当前点标号记录两者中的较小值 { present=temp; temp=*(p_temp+(height-j-1+1)*wide+i+1); } counter--;//合并左前和右上标号,标号总数减一 for(int m=1;m<=height-1;m++) for(int n=1;n<=wide-1;n++) { if(*(p_temp+(height-m-1)*wide+n)==temp) //将较大标号改成较小标号 { *(p_temp+(height-m-1)*wide+n)=present; } else if (*(p_temp+(height-m-1)*wide+n)>temp) //将较大标号以后的所有标号减一,以保持标号的连续性 { *(p_temp+(height-m-1)*wide+n)-=1; } } } if( *(m_pData+(height-j-1+1)*wide+i-1)<T && *(p_temp+ (height-j-1+1)*wide+i-1)!=present)//左上与右上点都为黑且标号不同 { counter--;//合并左上和右上标号,标号总数减一 int temp=*(p_temp+(height-j-1+1)*wide+i-1);//记录左上点的值 if (present<temp)//当前点标号记录两者中的较小值 { temp=present; present=*(p_temp+(height-j-1+1)*wide+i-1); } for(int m=1;m<=height-1;m++) for(int n=1;n<=wide-1;n++) { if(*(p_temp+(height-m-1)*wide+n)==present) //将较大标号改成较小标号 { *(p_temp+(height-m-1)*wide+n)=temp; } else if (*(p_temp+(height-m-1)*wide+n)>present) //将较大标号以后的所有标号减一,以保持标号的连续性 { *(p_temp+(height-m-1)*wide+n)-=1; } } present=temp; } } else if(*(m_pData+(height-j-1+1)*wide+i)<T) //当前点黑,右上不为黑,正上为黑 { *(p_temp+(height-j-1)*wide+i)=*(p_temp+(height-j-1+1) *wide+i); //当前标号=正上标号 present=*(p_temp+(height-j-1+1)*wide+i); } else if(*(m_pData+(height-j-1+1)*wide+i-1)<T)//左上 { *(p_temp+(height-j-1)*wide+i)=*(p_temp+(height-j-1+1) *wide+i-1); present=*(p_temp+(height-j-1+1)*wide+i-1);} else if(*(m_pData+(height-j-1)*wide+i-1)<T)//左前 { *(p_temp+(height-j-1)*wide+i)=*(p_temp+(height-j-1) *wide+i-1); present=*(p_temp+(height-j-1)*wide+i-1); } else//产生新标号 { ++counter; present=counter; *(p_temp+(height-j-1)*wide+i)=present; } }//end if }// 列 }//end行 // //////////////////////以上对数据区域标号////////////////////////// //////////////////////以下获得各个样品所在位置及编号/////////////////// patternnum=counter;//样品总数 if (m_pattern!=NULL) delete []m_pattern; m_pattern=new Pattern[patternnum]; for( i=0;i<patternnum;i++) { m_pattern[i].index=i+1; m_pattern[i].category=0; m_pattern[i].lefttop.x=wide; m_pattern[i].lefttop.y=height; m_pattern[i].rightbottom.x=0; m_pattern[i].rightbottom.y=0; } for(int t=1;t<=patternnum;t++)//记录每个样品(独立连通区域)的左上、右下点坐标 { for(int j=1;j<height-1;j++)//搜索整幅图像 for(int i=1;i<wide-1;i++) { if(*(p_temp+(height-j-1)*wide+i)==t) { if (m_pattern[t-1].lefttop.x>i)//get the lefttop point m_pattern[t-1].lefttop.x=i; if (m_pattern[t-1].lefttop.y>j) m_pattern[t-1].lefttop.y=j; if (m_pattern[t-1].rightbottom.x<i)//get the rightbottom point m_pattern[t-1].rightbottom.x=i; if (m_pattern[t-1].rightbottom.y<j) m_pattern[t-1].rightbottom.y=j; } } } delete []p_temp; //////////////////////以下获得所有样品特征放入m_pattern中//////////////////// for ( i=0;i<patternnum;i++)//=patternnum { CalFeature(&m_pattern[i]);//调用函数计算第i号模板的值 } //////////////////////以上获得所有样品特征放入m_pattern中//////////////////// }
[2] 上述代码中,CalFeature ()函数用于计算样品的特征值,该函数的实现代码如代码4-2所示。
代码4-2 CalFeature ()函数
void CCluster::CalFeature(CCluster::Pattern *m_pattern) { int w,h,count; int i,j; w=(int)(m_pattern->rightbottom.x-m_pattern->lefttop.x)/N;//特征值中每个特征的宽 h=(int)(m_pattern->rightbottom.y-m_pattern->lefttop.y)/N;//特征值中每个特征的高 for ( j=0;j<N;j++) { for ( i=0;i<N;i++) { count=0;//每个特征内黑点的个数 for(int m= height-m_pattern->rightbottom.y+h*j;m<height-m_pattern-> rightbottom.y+h*j+h;m++) for (int n=m_pattern->lefttop.x+i*w; n<m_pattern->lefttop.x+i*w +w; n++) if (*(m_pData+m*wide+n)==0) count++; m_pattern->feature[j*N+i]=(double)count/(double)(w*h); } } }