实现基于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行没有加条件
