1 /**********
2 *
3 * This file is part of the TINA Open Source Image Analysis Environment
4 * henceforth known as TINA
5 *
6 * TINA is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation.
9 *
10 * TINA is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with TINA; if not, write to the Free Software Foundation, Inc.,
17 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 **********
20 *
21 * Program : TINA
22 * File : $Source: /home/tina/cvs/tina-libs/tina/vision/visMatch_corner.c,v $
23 * Date : $Date: 2004/08/04 15:07:47 $
24 * Version : $Revision: 1.4 $
25 * CVS Id : $Id: visMatch_corner.c,v 1.4 2004/08/04 15:07:47 paul Exp $
26 *
27 * Author : Legacy TINA
28 *
29 * Notes :
30 *
31 *********
32 */
33
34 #include "visMatch_corner.h"
35
36 #if HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <math.h>
41 #include <tina/sys/sysDef.h>
42 #include <tina/sys/sysPro.h>
43 #include <tina/math/mathDef.h>
44 #include <tina/math/mathPro.h>
45 #include <tina/image/img_GenDef.h>
46 #include <tina/image/img_GenPro.h>
47 #include <tina/geometry/geomDef.h>
48 #include <tina/geometry/geomPro.h>
49
50 void get_corner_matches(Rindex * fx1, Rindex * fx2, int pos_type, Imregion(*search_func) ( /* ??? */ ), void* (*make_match) ( /* ??? */ ))
51 /* given the corners detercted in two specified regions and indexed by
52 the Rindex fast access structure, generate a list of candidate matches
53 for each corner from those available within the specified search region */
54 {
55 int ly, uy;
56 int i;
57 Imregion *index_region;
58
59 if (fx1 == NULL || fx2 == NULL)
60 return;
61
62 if ((index_region = fx1->region) == NULL)
63 return;
64
65 ly = index_region->ly;
66 uy = index_region->uy;
67
68 for (i = ly; i < uy; ++i)
69 {
70 List *ledge = fx1->index[i];
71
72 while (ledge != NULL)
73 {
74 Edgel *edge = (Edgel *) ledge->to;
75
76 if (edge != NULL)
77 get_corner_match(edge, fx2, pos_type, search_func(edge), make_match);
78 ledge = ledge->next;
79 }
80 }
81 }
82
83 void apply_func_to_windex(Rindex * fx, void *(*func) ( /* ??? */ ), void *data)
84 /* generic function to apply ana arbitrary function (func) to every Edgel
85 data structure indexed by the Rindex fast access structure, the generic
86 extra data field is user specifiable */
87 {
88 int ly, uy;
89 int i;
90 Imregion *index_region;
91
92 if (fx == NULL)
93 return;
94
95 if ((index_region = fx->region) == NULL)
96 return;
97
98 ly = index_region->ly;
99 uy = index_region->uy;
100
101 for (i = ly; i < uy; ++i)
102 {
103 List *ledge = fx->index[i];
104
105 while (ledge != NULL)
106 {
107 Edgel *edge = (Edgel *) ledge->to;
108
109 if (edge != NULL)
110 func(edge, data);
111 ledge = ledge->next;
112 }
113 }
114 }
115
116 void get_corner_match(Edgel * edge1, Rindex * fx2, int pos_type,
117 Imregion search_region, void *(*make_match) ( /* ??? */ ))
118 /* matches a single corner specified by edge1 to all possible matches
119 specified by the Rindex fast access structure */
120 {
121 int lx, ly, ux, uy;
122 int i;
123 Imregion *index_region;
124
125 if (edge1 == NULL || fx2 == NULL)
126 return;
127
128 if ((index_region = fx2->region) == NULL)
129 return;
130
131 lx = search_region.lx;
132 ly = search_region.ly;
133 ux = search_region.ux;
134 uy = search_region.uy;
135
136 if (lx < index_region->lx)
137 lx = index_region->lx;
138 if (ux > index_region->ux)
139 ux = index_region->ux;
140 if (lx > ux)
141 return;
142 if (ly < index_region->ly)
143 ly = index_region->ly;
144 if (uy > index_region->uy)
145 uy = index_region->uy;
146 if (ly > uy)
147 return;
148
149 for (i = ly; i < uy; ++i)
150 {
151 List *ledge = fx2->index[i];
152
153 while (ledge != NULL)
154 {
155 Edgel *edge2 = (Edgel *) ledge->to;
156 Vec2 *rect;
157
158 if (edge2 != NULL)
159 {
160 rect = (Vec2 *) prop_get(edge2->props, pos_type);
161 if (rect == NULL)
162 rect = &edge2->pos;
163 if ((int) rect->el[0] >= lx && (int) rect->el[0] <= ux)
164 make_match(edge1, edge2);
165 }
166 ledge = ledge->next;
167 }
168 }
169 }
170
171 static double match_weight(Match * match)
172 {
173 return (-match->weight); /*BUG fix lack of negative sign resulted in
174 wrongly ordered match list NAT/SAM 23/11/95 */
175 }
176
177 static void rm_match_list(List * list)
178 {
179 list_rm(list, match_free);
180 }
181
182 void add_match_to_props(Edgel * edge, void *match, int type)
183 {
184 List *list;
185
186 if (edge == NULL || match == NULL)
187 return;
188
189 list = prop_get(edge->props, type);
190 list = list_add_sorted(list, link_alloc((void *) match, POT_MATCH), match_weight);
191 edge->props = proplist_addifnp(edge->props, (void *) list, type, rm_match_list, false);
192 }
193
194 void rm_match_from_props(Edgel * edge, int *type)
195 {
196 edge->props = proplist_free(edge->props, *type);
197 }
198
199 void rm_corner_matches(Rindex * fx, int *type)
200 /* free up all corner matches curent stored in the edge data structures indexed
201 by the Rindex fast access data structure */
202 {
203 apply_func_to_windex(fx, (void *(*) ()) rm_match_from_props, (void *) type);
204 }
205
206 void *get_matches_list(Edgel * edgel, int *type)
207 {
208 List *matches;
209
210 matches = prop_get(edgel->props, *type);
211 return ((void *) matches);
212 }
213
214 Matrix *add_patch_to_props(Edgel * edge, Imrect * image, float sigma)
215 /* store a small piece of the image on the specified edge data structure
216 for use later during correlation based feature matching */
217 {
218 static Matrix *weight = NULL;
219 Matrix *patch;
220 float x0, y0;
221 float x, y, x1, y1;
222 float dx, dy;
223 float orient;
224 float norm = (float)0.0;
225 int i, j;
226
227 if (edge == NULL || image == NULL)
228 return (NULL);
229 if (weight == NULL)
230 {
231 weight = matrix_alloc(5, 5, matrix_full, float_v);
232 for (x = (float)-2.0 * sigma, i = 0; x <= 2.0 * sigma; x += sigma, i++)
233 for (y = (float)-2.0 * sigma, j = 0; y <= 2.0 * sigma; y += sigma, j++)
234 weight->el.float_v[i][j] = (float)(exp(-(x * x + y * y) / (4.0 * sigma * sigma)));
235 }
236 /*
237 orient = edge->orient;
238 */
239 orient = 0.0;
240 if ((patch = matrix_alloc(5, 5, matrix_full, float_v)) == NULL)
241 return (NULL);
242 x0 = edge->pos.el[0];
243 y0 = edge->pos.el[1];
244 for (x = (float)-2.0 * sigma, i = 0; x <= 2.0 * sigma; x += sigma, i++)
245 for (y = (float)-2.0 * sigma, j = 0; y <= 2.0 * sigma; y += sigma, j++)
246 {
247 x1 = -x*sin(orient) + y*cos(orient);
248 y1 = x*cos(orient) + y*sin(orient);
249 patch->el.float_v[i][j] = (float)(weight->el.float_v[i][j] *
250 im_get_quadinterpf(image, x0 + x1, y0 + y1, &dx, &dy));
251 norm += patch->el.float_v[i][j] * patch->el.float_v[i][j];
252 }
253 /* feature normalisation found to be unnecessary (ie: worse)
254 */
255 if (norm != 0.0)
256 norm = (float)(1.0 / sqrt(norm));
257 else
258 norm = (float)0.0;
259 for (i = 0; i < 5; i++)
260 for (j = 0; j < 5; j++)
261 patch->el.float_v[i][j] *= norm;
262
263 edge->props = proplist_add(edge->props, (void *) patch, PATCH, matrix_free);
264 return (patch);
265 }
266
267 float corner_correlation(Imrect * image1, Imrect * image2, Edgel * edge1, Edgel * edge2, float sigma)
268 {
269 float total = (float)0.0;
270 int i, j;
271 float norm1 = 0.0, norm2 = 0.0;
272 Matrix *patch1;
273 Matrix *patch2;
274
275 if (edge1 == NULL || edge2 == NULL)
276 return ((float)0.0);
277
278 if ((patch1 = prop_get(edge1->props, PATCH)) == NULL)
279 if ((patch1 = add_patch_to_props(edge1, image1, sigma)) == NULL)
280 return ((float)0.0);
281
282 if ((patch2 = prop_get(edge2->props, PATCH)) == NULL)
283 if ((patch2 = add_patch_to_props(edge2, image2, sigma)) == NULL)
284 return ((float)0.0);
285
286 for (i = 0; i < 5; i++)
287 for (j = 0; j < 5; j++)
288 {
289 total += patch1->el.float_v[i][j]*patch2->el.float_v[i][j];
290 norm1 += patch1->el.float_v[i][j]*patch1->el.float_v[i][j];
291 norm2 += patch2->el.float_v[i][j]*patch2->el.float_v[i][j];
292 }
293
294 return (total/sqrt(norm1*norm2));
295 }
296
297 float good_corner(Edgel * edge1, Edgel * edge2, float region, float asymetry, Imrect * image1, Imrect * image2)
298 {
299 float corr, asym;
300
301 if (edge1 == NULL || edge2 == NULL)
302 return ((float)0.0);
303
304 /* weak constraint on relative value of corner strength */
305 asym = (edge1->contrast - edge2->contrast)
306 / (edge1->contrast + edge2->contrast);
307 if (fabs(asym) > asymetry)
308 return ((float)0.0);
309 corr = corner_correlation(image1, image2, edge1, edge2, region);
310
311 return (corr);
312 }
313
314 float correlation(Imrect * image1, Imrect * image2, float x1, float y1, float x2, float y2, float sigma)
315 {
316 float total = (float)0.0;
317 float norm1 = (float)0.0;
318 float norm2 = (float)0.0;
319 float grey1, grey2, dx, dy;
320 float x, y;
321 static Matrix *weight = NULL;
322 int i, j;
323
324 if (weight == NULL)
325 {
326 weight = matrix_alloc(5, 5, matrix_full, float_v);
327 for (x = (float)-2.0 * sigma, i = 0; x <= 2.0 * sigma; x += sigma, i++)
328 for (y = (float)-2.0 * sigma, j = 0; y <= 2.0 * sigma; y += sigma, j++)
329 weight->el.float_v[i][j] = (float)(exp(-(x * x + y * y) / (2.0 * sigma * sigma)));
330 }
331 for (x = (float)-2.0 * sigma, i = 0; x <= 2.0 * sigma; x += sigma, i++)
332 {
333 for (y = (float)-2.0 * sigma, j = 0; y <= 2.0 * sigma; y += sigma, j++)
334 {
335 grey1 = (float)im_get_quadinterpf(image1, x1 + x, y1 + y, &dx, &dy);
336 grey2 = (float)im_get_quadinterpf(image2, x2 + x, y2 + y, &dx, &dy);
337 total += weight->el.float_v[i][j] * grey1 * grey2;
338 norm1 += weight->el.float_v[i][j] * grey1 * grey1;
339 norm2 += weight->el.float_v[i][j] * grey2 * grey2;
340 }
341 }
342 total /= (float)sqrt(norm1 * norm2);
343 return (total);
344 }
345
346 void *get_fixed_match(Edgel * edgel, int *type)
347 /* simple function to return the fixed matches for the specified corner
348 intended for use with apply_func_to_windex() */
349 {
350 List *matches;
351
352 matches = prop_get(edgel->props, *type);
353 if (matches != NULL && matches->type == FIXED_MATCH)
354 return (matches->to);
355 else
356 return (NULL);
357 }
358
359 void *get_good_match(Edgel * edgel, int *type)
360 /* simple function to return the good matches for the specified corner
361 intended for use with apply_func_to_windex() */
362 {
363 List *matches;
364
365 matches = prop_get(edgel->props, *type);
366 if (matches != NULL && matches->type == GOOD_MATCH)
367 return (matches->to);
368 else
369 return (NULL);
370 }
371
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.