实现基于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!\n"); 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\n"); 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,"\n"); 258 } 259 260 fprintf(stdout,"\n\n"); 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,"\n"); 272 } 273 274 275 276 }
【注】 原文代码在123-125行没有加条件,因此没有跑出正确的结果