- Visual C++數字圖像模式識別典型案例詳解
- 馮偉興 梁洪 王臣業編著
- 388字
- 2018-12-31 19:39:05
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); } } }