1 /**********
2 *
3 * Copyright (c) 2003, Division of Imaging Science and Biomedical Engineering,
4 * University of Manchester, UK. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 *
9 * . Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * . Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * . Neither the name of the University of Manchester nor the names of its
17 * contributors may be used to endorse or promote products derived from this
18 * software without specific prior written permission.
19 *
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 **********
34 *
35 * Program : TINA
36 * File : $Source: /home/tina/cvs/tina-libs/tina/image/imgPrc_bskel.c,v $
37 * Date : $Date: 2003/09/22 16:09:02 $
38 * Version : $Revision: 1.6 $
39 * CVS Id : $Id: imgPrc_bskel.c,v 1.6 2003/09/22 16:09:02 tony Exp $
40 *
41 * Author : Legacy TINA
42 */
43
44 /**
45 * @file
46 * @brief Morphological thinning (skeleton) of binary images.
47 *
48 *
49 * imcthin1n() thins the objects in an image
50 * using algorithm in Gonzalez&Wintz
51 * iterates until zero pixels are changed
52 * *pixelcount is the number of changed pixels
53 *
54 * functions called: NONE
55 *
56 *
57 * imcbthin1n() thins the background in an image
58 * using algorithm in G&W
59 * iterates until zero pixels are changed
60 * *pixelcount is the number of changed pixels
61 *
62 * functions called: NONE
63 *
64 */
65
66 #include "imgPrc_bskel.h"
67
68 #if HAVE_CONFIG_H
69 #include <config.h>
70 #endif
71
72 #include <stdio.h>
73 #include <stdlib.h>
74 #include <limits.h>
75 #include <math.h>
76 #include <tina/sys/sysDef.h>
77 #include <tina/sys/sysPro.h>
78 #include <tina/math/mathDef.h>
79 #include <tina/math/mathPro.h>
80 #include <tina/image/img_GenDef.h>
81
82 /* defines from old morph header */
83
84 #define IMAGE_POINTER_NULL 1000
85 #define IMAGE_DATA_NULL 900
86 #define PIXEL_TYPE 800
87 #define XROI_MINIMUM 700
88 #define YROI_MINIMUM 600
89 #define OK 1
90
91 /* PAB : Defines of FALSE and TRUE added during Tina 5 rewrite */
92
93 #define FALSE 0
94 #define TRUE 1
95
96
97 int imcthin1n(Imrect * im1, Imrect * im2, unsigned long *pixelcount)
98 {
99 unsigned int i, j;
100 int count;
101 unsigned long pcount;
102 int a, b, c, d, f, g, h, k;
103 unsigned char m;
104 int sp1;
105 unsigned int jminus1, jplus1;
106 unsigned char **image1, **image2;
107 unsigned char *ipointm1, *ipoint1, *ipointp1;
108 unsigned char *ipoint2;
109 unsigned int xmin, ymin, xmax, ymax;
110
111
112 /*** access image1 structure with error checking ***/
113
114 if ((im1 == NULL) || (im2 == NULL))
115 return (IMAGE_POINTER_NULL); /* undefined image struct */
116 if ((im1->data == NULL) || (im2->data == NULL))
117 return (IMAGE_DATA_NULL); /* image data corrupt */
118
119 if ((im1->vtype != uchar_v) ||
120 ((*im2).vtype != uchar_v))
121 return (PIXEL_TYPE);
122
123 image1 = (unsigned char **) im1->data;
124 image2 = (unsigned char **) im2->data;
125
126
127 /* get window values with limits checking */
128 xmin = im1->region->lx + 1;
129 xmax = im1->region->ux - 1;
130 ymin = im1->region->ly + 1;
131 ymax = im1->region->uy - 1;
132
133
134 /*** conditional mark logic ***/
135 /*
136 * local array is labeled :
137 *
138 * abc 8 4 2 def 16 1 ghk 32 64 128
139 */
140
141 *pixelcount = 0;
142 do
143 {
144 pcount = 0;
145 /*** first image pass ***/
146
147 for (i = ymin; i < ymax; i++)
148 {
149 ipointm1 = IM_ROW(im1, i - 1);
150 ipoint1 = IM_ROW(im1, i);
151 ipointp1 = IM_ROW(im1, i + 1);
152 ipoint2 = IM_ROW(im2, i);
153 for (j = xmin; j < xmax; j++)
154 {
155 m = (unsigned char) FALSE;
156
157 if (ipoint1[j])
158 {
159 jminus1 = j - 1;
160 jplus1 = j + 1;
161
162 a = (ipointm1[jplus1] ? 1 : 0);
163 b = (ipoint1[jplus1] ? 1 : 0);
164 c = (ipointp1[jplus1] ? 1 : 0);
165 d = (ipointm1[j] ? 1 : 0);
166 f = (ipointp1[j] ? 1 : 0);
167 g = (ipointm1[jminus1] ? 1 : 0);
168 h = (ipoint1[jminus1] ? 1 : 0);
169 k = (ipointp1[jminus1] ? 1 : 0);
170
171 count = a + b + c + d;
172 count += f + g + h + k;
173 if ((count == 1) || (count > 6)) /* condition A */
174 goto nextpixel;
175
176 /* condition B */
177 sp1 = 0;
178 if (!b && c)
179 sp1++;
180 if (!c && f)
181 sp1++;
182 if (!f && k)
183 sp1++;
184 if (!k && h)
185 sp1++;
186 if (!h && g)
187 sp1++;
188 if (!g && d)
189 sp1++;
190 if (!d && a)
191 sp1++;
192 if (!a && b)
193 sp1++;
194 if (sp1 != 1)
195 goto nextpixel;
196
197 /* conditions C and D */
198 if ((b && f && h) || (f && h && d))
199 goto nextpixel;
200
201 m = (unsigned char) TRUE;
202 pcount++;
203 }
204 nextpixel:
205 ;
206
207 ipoint2[j] = m;
208 }
209 }
210
211 for (i = ymin; i < ymax; i++)
212 {
213 ipoint1 = IM_ROW(im1, i);
214 ipoint2 = IM_ROW(im2, i);
215 for (j = xmin; j < xmax; j++)
216 if (ipoint2[j])
217 {
218 ipoint1[j] = (unsigned char) FALSE;
219 ipoint2[j] = (unsigned char) FALSE;
220 }
221 }
222 /*** second image pass ***/
223 for (i = ymin; i < ymax; i++)
224 {
225 ipointm1 = IM_ROW(im1, i - 1);
226 ipoint1 = IM_ROW(im1, i);
227 ipointp1 = IM_ROW(im1, i + 1);
228 ipoint2 = IM_ROW(im2, i);
229 for (j = xmin; j < xmax; j++)
230 {
231 m = (unsigned char) FALSE;
232
233 if (ipoint1[j])
234 {
235 jminus1 = j - 1;
236 jplus1 = j + 1;
237
238 a = (ipointm1[jplus1] ? 1 : 0);
239 b = (ipoint1[jplus1] ? 1 : 0);
240 c = (ipointp1[jplus1] ? 1 : 0);
241 d = (ipointm1[j] ? 1 : 0);
242 f = (ipointp1[j] ? 1 : 0);
243 g = (ipointm1[jminus1] ? 1 : 0);
244 h = (ipoint1[jminus1] ? 1 : 0);
245 k = (ipointp1[jminus1] ? 1 : 0);
246
247 count = a + b + c + d;
248 count += f + g + h + k;
249 if ((count == 1) || (count > 6)) /* condition A */
250 goto nextpixel2;
251
252 /* condition B */
253 sp1 = 0;
254 if (!b && c)
255 sp1++;
256 if (!c && f)
257 sp1++;
258 if (!f && k)
259 sp1++;
260 if (!k && h)
261 sp1++;
262 if (!h && g)
263 sp1++;
264 if (!g && d)
265 sp1++;
266 if (!d && a)
267 sp1++;
268 if (!a && b)
269 sp1++;
270 if (sp1 != 1)
271 goto nextpixel2;
272
273
274 /* conditions C and D */
275 if ((b && f && d) || (b && d && h))
276 goto nextpixel2;
277
278 m = (unsigned char) TRUE;
279 pcount++;
280 }
281 nextpixel2:
282 ;
283
284 ipoint2[j] = m;
285 }
286 }
287
288 for (i = ymin; i < ymax; i++)
289 {
290 ipoint1 = IM_ROW(im1, i);
291 ipoint2 = IM_ROW(im2, i);
292 for (j = xmin; j < xmax; j++)
293 if (ipoint2[j])
294 ipoint1[j] = (unsigned char) FALSE;
295 }
296 (*pixelcount) += pcount;
297 }
298 while (pcount != 0);
299
300
301 return (OK);
302 }
303
304
305 int imcbthin1n(Imrect * im1, Imrect * im2, unsigned long *pixelcount)
306 {
307 int status;
308 unsigned int i, j;
309 unsigned char *ipoint1;
310
311 /*** access image1 structure with error checking ***/
312
313 if ((im1 == NULL) || (im2 == NULL))
314 return (IMAGE_POINTER_NULL); /* undefined image struct */
315 if ((im1->data == NULL) || (im2->data == NULL))
316 return (IMAGE_DATA_NULL); /* image data corrupt */
317
318 if ((im1->vtype != uchar_v) ||
319 ((*im2).vtype != uchar_v))
320 return (PIXEL_TYPE);
321
322
323
324 /* reverse image region */
325 for (i = im1->region->ly; i < im1->region->uy; i++)
326 {
327 ipoint1 = (unsigned char *) IM_ROW(im1, i);
328 for (j = im1->region->lx; j < im1->region->ux; j++)
329 ipoint1[j] = (unsigned char) !ipoint1[j];
330 }
331
332 if ((status = imcthin1n(im1, im2, pixelcount)) != OK)
333 return (status);
334
335 for (i = im1->region->ly; i < im1->region->uy; i++)
336 {
337 ipoint1 = (unsigned char *) IM_ROW(im1, i);
338 for (j = im1->region->lx; j < im1->region->ux; j++)
339 ipoint1[j] = (unsigned char) !ipoint1[j];
340 }
341
342 return OK;
343 }
344
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.