改進的二值圖像像素標記算法及程序實現(含代碼)

  筆者實現了一個論文裏面的算法程序,論文(能夠網上搜索到,實在搜不到能夠聯繫筆者或留下郵箱發給你)講解比較到位,按照做者的思路寫完了代碼,測試效果很好,在此分享一下算法思路及實現代碼。算法

  此算法優於通常的像素標記算法,只需掃描一遍就能夠得出圖像邊界、面積等等,大大減小了計算量。數組

算法描述:學習

  1、全圖掃描測試

    對二值圖像全圖掃描,左到右,上到下,一遇到像素邊界就進行判斷。像素邊界指當前像素灰度爲1,其餘8領域至少有一個灰度值爲0。ui

    1.先依次判斷當前像素(i,j)的左側、左上側、上側像素和右上側像素是否被已標記,一旦遇到已標記則說明當前像素(i,j)和這個已標記像素屬於同一個目標,賦予Edge[i][j]相同的標記值,結束本像素標記,如四個像素都未標記則進入第二步。spa

    2.當前像素右移一部,即變爲(i,j+1),進入一子循環,每次循環判斷當前像素右上側像素是否已標記。如已標記則賦予Edge[i][j]相同的標記值並跳出循環結束,如當前像素右上側像素未標記則右移一位像素繼續判斷,直到到達這一行像素的右側邊界,跳出循環說明像素(i,j)屬於新目標。則原來最大目標標記值temp加1並賦予Edge[i][j],結束本像素標記。debug

    這一大步須要注意可能會有同一類別被分到不一樣目標,須要全圖掃描時進行判斷,主要是凹形。code

  2、掃描後處理blog

    1.歸類。前面記錄的等價標記數組只是記錄了兩兩等價狀況,而實際可能超過兩個,如三個等價。這裏須要補充的是,Same2數組是一個tempX1的數組,第幾行就對應第幾個目標處理狀況。依次掃描Same1數組每一行,在Same2中修改類別值,保證統一類的值歸爲一類。class

    2.標以正確的目標值。通過上一步,屬於同一目標的像素標記值都已歸爲一類,有幾類就有幾個帶下凹的目標,再加上0的個數(不帶下凹的目標個數)就是實際目標總數。順序掃描Same2,遇到0說明該行號表示的目標位沒有下凹的,result+1賦予Same3的同一行,遇到非零數字,則看它是否第一次出現,若是第一次出現,result+1並賦予Same3同一行,如Same2這一行的值不是第一次出現,則把前面具備相同數字那一行在Same3中同行的值賦予Same3的這一行,直到檢測完Same2。最後在Same3的最後數字表示的就是目標數。

    3.根據獲得目標數進行目標劃分,整個圖像就被分到了幾個目標值。獲得的目標值能夠統計目標數目、實現面積、周長和質心等特徵值。

程序代碼:

  

  1 //改進的像素標記算法實現代碼及註釋
  2 //做者用這個算法來繪製目標外接矩形用的
  3 //返回找到圖像目標處理凹形數目,參數frame是原始二值圖像,num爲處理前凹形找到目標數目,s和e分別表示繪製矩形的開始點和結束點
  4 int pixelFlag(cv::Mat &frame,int &num,vector<Point2f> &s,vector<Point2f> &e)//返回個數
  5 {
  6     //frame.
  7     int kind=0,kindEnd=0,kindResult=0;//歸類類別
  8     vector<int> same1[2];//可疑邊界目標
  9 
 10     int edge[frame.rows][frame.cols];//代表邊界屬於哪一個類
 11     memset(edge,0,sizeof(edge));
 12     //qDebug()<<frame.channels();
 13     //掃描每一個像素判斷
 14     for(int i=1;i<frame.rows-1;i++)
 15          for(int j=1;j<frame.cols-1;j++)
 16         {
 17             if((frame.at<uchar>(i,j)!=0)&&(!frame.at<uchar>(i-1,j)||!frame.at<uchar>(i-1,j-1)||!frame.at<uchar>(i-1,j+1)
 18                                       ||!frame.at<uchar>(i,j-1)||!frame.at<uchar>(i,j+1)||!frame.at<uchar>(i+1,j-1)
 19                                       ||!frame.at<uchar>(i+1,j)||!frame.at<uchar>(i+1,j+1)))//判斷邊界點
 20             {
 21                 if(edge[i][j-1])//判斷是否緊鄰已被標物體  左
 22                 {
 23                     edge[i][j]=edge[i][j-1];
 24                 }
 25                 else
 26                     if(edge[i-1][j-1])//左上
 27                     {
 28                         edge[i][j]=edge[i-1][j-1];
 29                     }
 30                     else
 31                         if(edge[i-1][j])//
 32                         {
 33                             edge[i][j]=edge[i-1][j];
 34                         }else
 35                             if(edge[i-1][j+1])//右上
 36                             {
 37                                 edge[i][j]=edge[i-1][j+1];
 38                             }else
 39                             {
 40                                 int f=0;
 41                                 while(frame.at<uchar>(i,j+f)&&((j+f)<frame.cols-1))//右移判斷
 42                                 {
 43                                     if(edge[i-1][j+f+1])
 44                                     {
 45                                         edge[i][j]=edge[i-1][j+f+1];
 46                                         break;
 47                                     }
 48                                     else
 49                                     {
 50                                         f++;
 51                                     }
 52                                 }
 53                                 if(!frame.at<uchar>(i,j+f))//未找處處理
 54                                 {
 55                                     kind++;
 56                                     edge[i][j]=kind;
 57 
 58                                 }
 59                             }
 60                 if(edge[i][j]&&edge[i-1][j+1])//若是當前點和右上不在一個類別就記錄
 61                 {
 62                     if(edge[i][j]!=edge[i-1][j+1])
 63                     {
 64                         same1[0].push_back(edge[i][j]);
 65                         same1[1].push_back(edge[i-1][j+1]);
 66                     }
 67                 }
 68 
 69 
 70 
 71             }
 72         }
 73 
 74     //處理掃描後的結果
 75     int same2[kind];memset(same2,0,sizeof(same2));
 76     int sameEnd[kind];memset(sameEnd,0,sizeof(sameEnd));
 77     //QDebug debug;
 78     if(!same1[0].empty())
 79     {
 80         for(uint i=0;i<same1[0].size();i++)
 81         {
 82             if((!same2[same1[0][i]-1])&&(!same2[same1[1][i]-1]))//若是都沒有處理,種類加1
 83             {
 84                 kindEnd++;
 85                 same2[same1[0][i]-1]=kindEnd;
 86                 same2[same1[1][i]-1]=kindEnd;
 87             }else
 88                 if(same2[same1[0][i]-1]&&same2[same1[1][i]-1])
 89                 {
 90                     same2[same1[0][i]-1]=same2[same1[1][i]-1];
 91 
 92                 }else
 93                     if(!same2[same1[0][i]-1]&&same2[same1[1][i]-1])
 94                     {
 95                         same2[same1[0][i]-1]=same2[same1[1][i]-1];
 96                     }else if(same2[same1[0][i]-1]&&!same2[same1[1][i]-1])
 97                     {
 98                         same2[same1[1][i]-1]=same2[same1[0][i]-1];
 99                     }
100 
101         }
102     }
103 
104     for(int i=0;i<kind;i++)//複製到sameend
105     {
106 
107         if(!same2[i])
108         {
109             kindResult++;
110             sameEnd[i]=kindResult;
111         }
112         else
113             //if(same2)
114             {
115                 int j=0;
116                 while(j<i)
117                 {
118                     if(same2[j]==same2[i])
119                     {
120                         break;
121                     }
122                     j++;
123                 }
124                 if(j<i)
125                 {
126                     sameEnd[i]=sameEnd[j];
127                 }else
128                 {
129                     kindResult++;
130                     sameEnd[i]=kindResult;
131                 }
132 
133             }
134     }
135     num=kind;
136     //對邊界進行處理
137     for(int i=1;i<frame.rows-1;i++)
138         for(int j=1;j<frame.cols-1;j++)
139         {
140             if(edge[i][j])
141             {
142                 edge[i][j]=sameEnd[edge[i][j]-1];
143             }
144         }
145     for(int i=0;i<kindResult;i++)
146     {
147         s.push_back(Point2f(1000,1000));
148         e.push_back(Point2f(0,0));
149     }
150     for(int i=1;i<frame.rows-1;i++)//求邊界對角點
151         for(int j=1;j<frame.cols-1;j++)
152         {
153             if(edge[i][j])
154             {
155                 if(s[edge[i][j]-1].y>i)
156                 {
157                     s[edge[i][j]-1].y=i;
158                 }
159                 if(s[edge[i][j]-1].x>j)
160                 {
161                     s[edge[i][j]-1].x=j;
162                 }
163                 if(e[edge[i][j]-1].y<i)

164 {
165 e[edge[i][j]-1].y=i; 166  } 167 168 if(e[edge[i][j]-1].x<j) 169  { 170 e[edge[i][j]-1].x=j; 171  } 172  } 173  } 174 return kindResult; 175 176 177 178 }

效果以下:

  

共享園友,學習共勉!

相關文章
相關標籤/搜索