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