实现基于C语言的二值图像连通域标记算法

实现基于C语言的二值图像连通域标记算法

  1 #include <stdio.h>
  2 #include <stdarg.h>
  3 #include <stddef.h>
  4 #include <stdlib.h>
  5 #include <stdint.h>
  6 #include <math.h>
  7 
  8 #define CONNECTIVITY4 4
  9 #define CONNECTIVITY8 8
 10 #define STACK_INIT_SIZE 256
 11 #define STACK_INCRE 256
 12 #define TRUE 1
 13 #define FALSE 0
 14 
 15 typedef struct tagStack
 16 {
 17     int **base;
 18     int **top;
 19     int stacksize;
 20 }Stack;
 21 
 22 
 23 Stack* CreatStack(void)
 24 {
 25     Stack *pStack = (Stack*)calloc(1, sizeof(Stack));
 26     pStack->base = (int **)calloc(STACK_INIT_SIZE + 1, sizeof(int *));
 27     pStack->top = pStack->base;
 28     pStack->stacksize = STACK_INIT_SIZE;
 29  
 30     return pStack;
 31 }
 32 
 33 int IsStackEmpty(Stack *pStack)
 34 {
 35     if (pStack->top == pStack->base)
 36         return TRUE;
 37     else
 38         return FALSE;
 39 }
 40 
 41 void Push(Stack *pStack, int *pnElement)
 42 {
 43     if (pStack->top - pStack->base >= pStack->stacksize)
 44         {
 45             pStack->base = (int **)realloc(pStack->base, (pStack->stacksize + STACK_INCRE) * sizeof(int *));
 46             pStack->top = pStack->base + pStack->stacksize;
 47             pStack->stacksize += STACK_INCRE;
 48         }
 49     ++pStack->top;
 50     *(pStack->top) = pnElement;
 51 }
 52 
 53 void Pop(Stack *pStack, int *pnElement)
 54 {
 55     if (pStack->top == pStack->base && *(pStack->top) == NULL)
 56         printf("empty!
");
 57     else
 58         {
 59             memcpy(pnElement, *(pStack->top), 4 * sizeof(int));
 60             (pStack->top)--;
 61         }
 62 }
 63 
 64 void DestroyStack(Stack *pStack)
 65 {
 66     free(pStack->base);
 67     pStack->top = pStack->base = NULL;
 68     pStack->stacksize = 0;
 69  
 70     free(pStack), pStack = NULL;
 71 }
 72 
 73 /*
 74   connected component labeling
 75   pNumLine: the number of connected line in each row
 76   LineInfos: the row number;
 77   the start column number
 78   the end column number
 79   labeling number
 80 */
 81 int ConnectedComponentLabeling(uint8_t *pData, int *pResult, int width, int height, int mode, int* pAddress)
 82 {
 83     int i = 0, j = 0, k = 0, m = 0, n = 0, L = 0, R = 0, LL = 0, RR = 0, N = 0, X = 0, nFlag = 0;
 84     int widthPadded = width + 1, heightPadded = height + 1;
 85     int *pNumLine = NULL, **pLineInfos = NULL, *pTemp = NULL;
 86     int *p1, *p3;
 87     uint8_t *p2;
 88     uint8_t *pnBWPadded;
 89     Stack *pStack = NULL;
 90  
 91     if (mode != CONNECTIVITY4 && mode != CONNECTIVITY8){
 92         printf("[error]: wrong mode
");
 93         exit(-1);
 94     }
 95     //
 96     pnBWPadded = pData;
 97     pNumLine = (int *)malloc(heightPadded * sizeof(int));
 98     pLineInfos = (int **)calloc(heightPadded, sizeof(int *));
 99     for (i = 0; i < heightPadded; i++){
100         pLineInfos[i] = (int *)(pAddress + i*width * 2);
101     }
102     p1 = pNumLine;        
103     p2 = pnBWPadded;
104         
105     //calculate each row's connected line, including their row number, starting column number, ending column number
106     for (i = 0; i < height; i++) {
107         n = 0;
108         p3 = pLineInfos[i];
109         for (j = 0; j < widthPadded - 1; j++) {
110             if (*p2 == 1) {
111                 k = j;
112                 while (*p2 != 0 && k < width) {
113                     p2++;
114                     k++;
115                 }
116                 *p3++ = i;
117                 *p3++ = j;
118                 *p3++ = k - 1;
119                 *p3++ = 0;
120                 n++;
121                 j = k;
122             }
123             if(j < widthPadded - 1){
124                 p2++;
125             }
126         }
127         *p1++ = n;
128     }
129  
130     pStack = CreatStack();
131     N = 1;
132     for (i = 0; i < heightPadded - 1; i++){
133         for (j = 0; j < pNumLine[i]; j++){
134             //
135             if (pLineInfos[i][j * 4 + 3] == 0){
136                 pTemp = &pLineInfos[i][j * 4];
137                 //*(pStack->top) = pTemp;
138                 pTemp[3] = -1;
139                 Push(pStack, pTemp);
140             Loop:
141                 pTemp = *(pStack->top);
142                 X = pTemp[0];
143                 L = pTemp[1];
144                 R = pTemp[2];
145 
146                 //connectivity8 or connectivity4
147                 LL = (mode == CONNECTIVITY8) ? (L - 1) : L;
148                 RR = (mode == CONNECTIVITY8) ? (R + 1) : R;
149  
150                 nFlag = 0;
151 
152                 //previous row
153                 if (X > 0){
154                     for (m = 0; m < pNumLine[X - 1]; m++){
155                         if (pLineInfos[X - 1][m * 4 + 1] <= RR && pLineInfos[X - 1][m * 4 + 2] >= LL && pLineInfos[X - 1][m * 4 + 3] == 0){
156                             pLineInfos[X - 1][m * 4 + 3] = -1;
157                             Push(pStack, &pLineInfos[X - 1][m * 4]);
158                             nFlag = 1;
159                         }
160                     }
161                 }
162                 //next row
163                 if (X < heightPadded - 1) {
164                     for (n = 0; n < pNumLine[X + 1]; n++){
165                         if (pLineInfos[X + 1][n * 4 + 1] <= RR && pLineInfos[X + 1][n * 4 + 2] >= LL && pLineInfos[X + 1][n * 4 + 3] == 0){
166                             pLineInfos[X + 1][n * 4 + 3] = -1;
167                             Push(pStack, &pLineInfos[X + 1][n * 4]);
168                             nFlag = 1;
169                         }
170                     }
171                 }
172  
173                 //no line connected to current line or current line has been labeled
174                 if (nFlag == 0){
175                     if (IsStackEmpty(pStack)){
176                         N++;
177                         continue;
178                     }
179                     else{
180                         (*(pStack->top))[3] = N;
181                         Pop(pStack, pTemp);
182                         if (IsStackEmpty(pStack)){
183                             N++;
184                             continue;
185                         }
186                         else{
187                             goto Loop;
188                         }
189                     }
190                 }else{
191                     goto Loop;
192                 }
193 
194             }
195         }
196     }
197  
198     //label result
199     int *label_cnt = malloc(N*sizeof(int));
200     memset(label_cnt,0,N*sizeof(int));
201     for (i = 0; i<height; i++){
202         for (j = 0; j<pNumLine[i]; j++){
203             for (k = pLineInfos[i][j * 4 + 1]; k <= pLineInfos[i][j * 4 + 2]; k++){
204                 pResult[i*width + k] = pLineInfos[i][j * 4 + 3];
205                 label_cnt[pLineInfos[i][j * 4 + 3]]++;
206             }
207         }
208     }
209     int max_label_cnt = 0;
210     for(i=0;i<N;i++){
211         if(label_cnt[i] > max_label_cnt){
212             max_label_cnt = label_cnt[i];
213         }
214     }
215     free(pNumLine), pNumLine = NULL;
216     free(pLineInfos), pLineInfos = NULL;
217     free(label_cnt);
218     DestroyStack(pStack);
219 
220     return max_label_cnt;
221 }
222 
223 
224 int main()
225 {
226     //binary img
227     uint8_t imgmap[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1,
228                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,
229                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
230                             1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0,
231                             1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
232                             0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
233                             0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
234                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
235                             0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
236                             0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
237                             0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
238                             1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
239                             0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
240                             0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
241                             0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
242                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
243 
244     int *labelmap = (int*)malloc(16*16*sizeof(int));
245     memset(labelmap,0,16*16*sizeof(int));
246     int *pAddress = (int*)malloc(1024*sizeof(int));
247     memset(pAddress,0,1024*sizeof(int));
248     int ind = 0;
249                   
250     int n=0,m=0;
251 
252     for(n=0; n<16; n++){
253         for(m=0; m<16; m++){
254             fprintf(stdout,"%2d,",imgmap[ind]);
255             ind++;
256         }
257         fprintf(stdout,"
");
258     }
259 
260     fprintf(stdout,"

");
261 
262     //
263     ind = 0;
264     ConnectedComponentLabeling(imgmap,labelmap,16,16,8,pAddress);
265 
266     for(n=0; n<16; n++){
267         for(m=0; m<16; m++){
268             fprintf(stdout,"%3d",labelmap[ind]);
269             ind++;
270         }
271         fprintf(stdout,"
");
272     }
273 
274 
275 
276 }

【注】 原文代码在123-125行没有加条件,因此没有跑出正确的结果

原文地址:https://www.cnblogs.com/liuxin0430/p/9822366.html