dummy empty discard outliers routine, and it all works!
[sparrow.git] / edges.c
blob54113a48b6957cb70c00c292ea860202ff1066f5
1 /* Copyright (C) <2010> Douglas Bagnall <douglas@halo.gen.nz>
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Library General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Library General Public License for more details.
13 * You should have received a copy of the GNU Library General Public
14 * License along with this library; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 02111-1307, USA.
20 #include "sparrow.h"
21 #include "gstsparrow.h"
22 #include "edges.h"
24 #include <string.h>
25 #include <math.h>
27 #include "cv.h"
32 #define SIG_WEIGHT 2
34 /*3 pixels manhatten distance makes you an outlier */
35 #define OUTLIER_THRESHOLD 3 << (SPARROW_FIXED_POINT)
36 #define OUTLIER_PENALTY 8
41 #define SPARROW_MAP_LUT_SHIFT 1
42 #define SPARROW_FP_2_LUT (SPARROW_FIXED_POINT - SPARROW_MAP_LUT_SHIFT)
44 #define OFFSET(x, y, w)((((y) * (w)) >> SPARROW_FIXED_POINT) + ((x) >> SPARROW_FIXED_POINT))
47 int sort_median(int *a, guint n)
49 guint i, j;
50 /*stupid sort, but n is very small*/
51 for (i = 0; i < n; i++){
52 for (j = i + 1; j < n; j++){
53 if (a[i] > a[j]){
54 int tmp = a[j];
55 a[j] = a[i];
56 a[i] = tmp;
60 guint middle = n / 2;
61 int answer = a[middle];
63 if ((n & 1) == 0){
64 answer += a[middle - 1];
65 answer /= 2;
67 return answer;
74 static void corners_to_lut(GstSparrow *sparrow, sparrow_find_lines_t *fl){
75 //DEBUG_FIND_LINES(fl);
76 sparrow_map_t *map = &sparrow->map; /*rows in sparrow->out */
77 guint8 *mask = sparrow->screenmask; /*mask in sparrow->in */
78 sparrow_corner_t *mesh = fl->mesh; /*maps regular points in ->out to points in ->in */
80 int mesh_w = fl->n_vlines;
81 int mesh_h = fl->n_hlines;
82 int in_w = sparrow->in.width;
83 int mcy, mmy, mcx; /*Mesh Corner|Modulus X|Y*/
85 int x;
86 sparrow_map_row_t *row = map->rows;
87 sparrow_map_point_t *p = map->point_mem;
88 sparrow_corner_t *mesh_row = mesh;
89 for(mcy = 0; mcy < mesh_h; mcy++){
90 for (mmy = 0; mmy < LINE_PERIOD; mmy++){
91 sparrow_corner_t *mesh_square = mesh_row;
92 row->points = p;
93 row->start = 0;
94 row->end = 0;
95 for(mcx = 0; mcx < mesh_w; mcx++){
96 if (mesh_square->used){
97 int iy = mesh_square->in_y + mmy * mesh_square->dyd;
98 int ix = mesh_square->in_x + mmy * mesh_square->dxd;
99 int ii = OFFSET(ix, iy, in_w);
100 int ii_end = OFFSET(ix + (LINE_PERIOD - 1) * mesh_square->dxr,
101 iy + (LINE_PERIOD - 1) * mesh_square->dyr, in_w);
102 int start_on = mask[ii];
103 int end_on = mask[ii_end];
104 if(start_on && end_on){
105 /*add the point, maybe switch on */
106 if (row->start == row->end){/* if both are 0 */
107 row->start = mcx * LINE_PERIOD;
109 p->x = ix;
110 p->y = iy;
111 p->dx = mesh_square->dxr;
112 p->dy = mesh_square->dyr;
113 p++;
115 else if (start_on){
116 /*add the point, switch off somewhere in the middle*/
117 for (x = 1; x < LINE_PERIOD; x++){
118 iy += mesh_square->dyr;
119 ix += mesh_square->dxr;
120 ii = OFFSET(ix, iy, in_w);
121 if (mask[ii]){
122 /*point is not in the same column with the others,
123 but sparrow knows this because the row->start says so */
124 row->start = mcx + x;
125 p->x = ix;
126 p->y = iy;
127 p->dx = mesh_square->dxr;
128 p->dy = mesh_square->dyr;
129 p++;
130 break;
134 else if (end_on){
135 /* add some, switch off */
136 for (x = 1; x < LINE_PERIOD; x++){
137 iy += mesh_square->dyr;
138 ix += mesh_square->dxr;
139 ii = OFFSET(ix, iy, in_w);
140 if (! mask[ii]){
141 row->end = mcx + x;
142 break;
146 else {
147 /*3 cases:
148 start > end: this is first off pixel.
149 start == end: row hasn't started (both 0)
150 start < end: both are set -- row is done
152 if (row->start > row->end){
153 row->end = mcx * LINE_PERIOD;
155 else if (row->start < row->end){
156 break;
160 mesh_square++;
162 row++;
164 mesh_row += mesh_w;
168 UNUSED static void
169 corners_to_full_lut(GstSparrow *sparrow, sparrow_find_lines_t *fl){
170 //DEBUG_FIND_LINES(fl);
171 sparrow_corner_t *mesh = fl->mesh; /*maps regular points in ->out to points in ->in */
172 sparrow_map_lut_t *map_lut = sparrow->map_lut;
173 int mesh_w = fl->n_vlines;
174 int mesh_h = fl->n_hlines;
175 int mcy, mmy, mcx, mmx; /*Mesh Corner|Modulus X|Y*/
176 int i = 0;
177 sparrow_corner_t *mesh_row = mesh;
178 for(mcy = 0; mcy < mesh_h; mcy++){
179 for (mmy = 0; mmy < LINE_PERIOD; mmy++){
180 sparrow_corner_t *mesh_square = mesh_row;
181 for(mcx = 0; mcx < mesh_w; mcx++){
182 int iy = mesh_square->in_y + mmy * mesh_square->dyd;
183 int ix = mesh_square->in_x + mmy * mesh_square->dxd;
184 for (mmx = 0; mmx < LINE_PERIOD; mmx++, i++){
185 map_lut[i].x = ix >> SPARROW_FP_2_LUT;
186 map_lut[i].y = iy >> SPARROW_FP_2_LUT;
187 ix += mesh_square->dxr;
188 iy += mesh_square->dyr;
190 mesh_square++;
193 mesh_row += mesh_w;
195 sparrow->map_lut = map_lut;
198 #define DIV ((double)(1 << SPARROW_FIXED_POINT))
199 #define INTXY(x)((x) / (1 << SPARROW_FIXED_POINT))
200 #define FLOATXY(x)(((double)(x)) / (1 << SPARROW_FIXED_POINT))
201 static void
202 debug_corners_image(GstSparrow *sparrow, sparrow_find_lines_t *fl){
203 sparrow_corner_t *mesh = fl->mesh;
204 guint32 *data = (guint32*)fl->debug->imageData;
205 guint w = fl->debug->width;
206 memset(data, 0, sparrow->in.size);
207 guint32 colours[4] = {0xff0000ff, 0x0000ff00, 0x00ff0000, 0xcccccccc};
208 for (int i = 0; i < fl->n_vlines * fl->n_hlines; i++){
209 sparrow_corner_t *c = &mesh[i];
210 int x = c->in_x;
211 int y = c->in_y;
212 GST_DEBUG("i %d used %d x: %f, y: %f dxr %f dyr %f dxd %f dyd %f\n"
213 "int x, y %d,%d (raw %d,%d) data %p\n",
214 i, c->used, FLOATXY(x), FLOATXY(y),
215 FLOATXY(c->dxr), FLOATXY(c->dyr), FLOATXY(c->dxd), FLOATXY(c->dyd),
216 INTXY(x), INTXY(y), x, y, data);
217 int txr = x;
218 int txd = x;
219 int tyr = y;
220 int tyd = y;
221 for (int j = 1; j < LINE_PERIOD; j++){
222 txr += c->dxr;
223 txd += c->dxd;
224 tyr += c->dyr;
225 tyd += c->dyd;
226 data[INTXY(tyr) * w + INTXY(txr)] = 0x000088;
227 data[INTXY(tyd) * w + INTXY(txd)] = 0x663300;
229 #if 0
230 #define LP8 (LINE_PERIOD / 8)
231 #define LP4 (LINE_PERIOD / 4)
232 #define LP2 (LINE_PERIOD / 2)
233 data[INTXY(y + c->dyr * LP8) * w + INTXY(x + c->dxr * LP8)] = 0xbbbbbbbb;
234 data[INTXY(y + c->dyr * LP4) * w + INTXY(x + c->dxr * LP4)] = 0xaaaaaaaa;
235 data[INTXY(y + c->dyr * LP2) * w + INTXY(x + c->dxr * LP2)] = 0x99999999;
236 data[INTXY(y + c->dyd * LP8) * w + INTXY(x + c->dxd * LP8)] = 0xbb6666bb;
237 data[INTXY(y + c->dyd * LP4) * w + INTXY(x + c->dxd * LP4)] = 0xaa5555aa;
238 data[INTXY(y + c->dyd * LP2) * w + INTXY(x + c->dxd * LP2)] = 0x99444499;
239 #endif
240 data[INTXY(y) * w + INTXY(x)] = colours[MIN(c->used, 2)];
242 MAYBE_DEBUG_IPL(fl->debug);
246 static void
247 debug_clusters(GstSparrow *sparrow, sparrow_find_lines_t *fl){
248 //sparrow_cluster_t *clusters = fl->clusters;
251 /*signal product is close to 18 bits. reduce to 4 */
252 #define SIGNAL_QUANT (1 << 14)
254 /*maximum number of pixels in a cluster */
255 #define CLUSTER_SIZE 8
258 /*create the mesh */
259 static void
260 find_corners_make_clusters(GstSparrow *sparrow, guint8 *in, sparrow_find_lines_t *fl){
261 sparrow_cluster_t *clusters = fl->clusters;
262 int x, y;
263 /*each point in fl->map is in a vertical line, a horizontal line, both, or
264 neither. Only the "both" case matters. */
265 for (y = 0; y < sparrow->in.height; y++){
266 for (x = 0; x < sparrow->in.width; x++){
267 sparrow_intersect_t *p = &fl->map[y * sparrow->in.width + x];
268 guint vsig = p->signal[SPARROW_VERTICAL];
269 guint hsig = p->signal[SPARROW_HORIZONTAL];
270 /*remembering that 0 is valid as a line number, but not as a signal */
271 if (! (vsig && hsig)){
272 continue;
274 /*This one is lobbying for the position of a corner.*/
275 int vline = p->lines[SPARROW_VERTICAL];
276 int hline = p->lines[SPARROW_HORIZONTAL];
278 sparrow_cluster_t *cluster = &clusters[hline * fl->n_vlines + vline];
279 sparrow_voter_t *voters = cluster->voters;
280 int n = cluster->n;
281 guint signal = (vsig * hsig) / SIGNAL_QUANT;
282 int xfp = x << SPARROW_FIXED_POINT;
283 int yfp = y << SPARROW_FIXED_POINT;
285 GST_DEBUG("signal at %p (%d, %d): %dv %dh, product %u, lines: %dv %dh\n"
286 "cluster is %p, n is %d\n", p, x, y,
287 vsig, hsig, signal, vline, hline, cluster, n);
289 if (n < CLUSTER_SIZE){
290 voters[n].x = xfp;
291 voters[n].y = yfp;
292 voters[n].signal = signal;
293 cluster->n++;
295 else {
296 for (int j = 0; j < CLUSTER_SIZE; j++){
297 if (voters[j].signal < signal){
298 guint tmp_s = voters[j].signal;
299 int tmp_x = voters[j].x;
300 int tmp_y = voters[j].y;
301 voters[j].signal = signal;
302 voters[j].x = xfp;
303 voters[j].y = yfp;
304 signal = tmp_s;
305 xfp = tmp_x;
306 yfp = tmp_y;
307 GST_DEBUG("more than %d pixels at cluster for corner %d, %d.\n",
308 CLUSTER_SIZE, vline, hline);
316 /* look for connected group. if there is more than one connected group,
317 despair.*/
319 static inline void
320 discard_cluster_outliers(sparrow_cluster_t *cluster)
324 static inline void
325 x_discard_cluster_outliers(sparrow_cluster_t *cluster)
327 sparrow_voter_t *v = cluster->voters;
328 int i, j;
330 guint32 touch[CLUSTER_SIZE];
332 while (cluster->n){
333 guint32 all = (1 << cluster->n) - 1;
334 for (i = 0; i < cluster->n; i++){
335 touch[i] = 1 << i;
338 for (i = 0; i < cluster->n - 1; i++){
339 for (j = i + 1; j < cluster->n; j++){
340 if (((abs(v[i].x - v[j].x) <= 2) && (abs(v[i].y - v[j].y) <= 2)) ||
341 (touch[i] & touch[j])){
342 touch[i] |= touch[j];
343 touch[j] = touch[i];
347 if (touch[cluster->n - 1] == all){
348 break;
350 /* something is wrong! somebody is disconnected! expel them!?
351 backpropagate connectedness, find the maximum popcount, discard the
352 others. */
353 int bcount = 0;
354 guint bmask = 0;
356 for (i = cluster->n - 1; i >= 0; i++){
357 if (bmask != touch[i] &&
358 bcount < (int)popcount32(touch[i])){
359 bmask = touch[i];
360 bcount = popcount32(touch[i]);
362 for (j = 0; j < i; j++){
363 touch[j] = (touch[j] & touch[i]) ? touch[i] : touch[j];
366 if (bcount > cluster->n / 2){
367 j = 0;
368 for (i = 0; i < cluster->n; i++){
369 if (touch[i] == bmask){
370 v[j] = v[i];
371 j++;
374 cluster->n = j;
381 /*create the mesh */
382 static inline void
383 find_corners_make_corners(GstSparrow *sparrow, guint8 *in, sparrow_find_lines_t *fl){
384 //DEBUG_FIND_LINES(fl);
385 int width = fl->n_vlines;
386 int height = fl->n_hlines;
387 sparrow_cluster_t *clusters = fl->clusters;
388 sparrow_corner_t *mesh = fl->mesh;
389 int x, y, i;
391 i = 0;
392 for (y = 0; y < height; y++){
393 for (x = 0; x < width; x++, i++){
394 /* how to do this?
395 1. centre of gravity (x,y, weighted average)
396 2. discard outliers? look for connectedness? but if 2 are outliers?
398 sparrow_cluster_t *cluster = clusters + i;
399 if (cluster->n == 0){
400 continue;
403 discard_cluster_outliers(cluster);
405 int xsum, ysum;
406 int xmean, ymean;
407 int votes;
408 int j;
409 xsum = 0;
410 ysum = 0;
411 votes = 0;
412 for (j = 0; j < cluster->n; j++){
413 votes += cluster->voters[j].signal;
414 ysum += cluster->voters[j].y * cluster->voters[j].signal;
415 xsum += cluster->voters[j].x * cluster->voters[j].signal;
417 xmean = xsum / votes;
418 ymean = ysum / votes;
419 GST_DEBUG("corner %d: %d voters, %d votes, sum %d,%d, mean %d,%d\n",
420 i, cluster->n, votes, xsum, ysum, xmean, ymean);
422 mesh[i].in_x = xmean;
423 mesh[i].in_y = ymean;
424 mesh[i].used = TRUE;
425 GST_DEBUG("found corner %d at (%3f, %3f)\n",
426 i, FLOATXY(xmean), FLOATXY(ymean));
431 static inline void
432 find_corners_make_map(GstSparrow *sparrow, guint8 *in, sparrow_find_lines_t *fl){
433 int i;
434 int width = fl->n_vlines;
435 int height = fl->n_hlines;
436 sparrow_corner_t *mesh = fl->mesh;
437 gint x, y;
439 //DEBUG_FIND_LINES(fl);
440 /* calculate deltas toward adjacent corners */
441 /* try to extrapolate left and up, if possible, so need to go backwards. */
442 i = width * height - 1;
443 for (y = height - 1; y >= 0; y--){
444 for (x = width - 1; x >= 0; x--, i--){
445 sparrow_corner_t *corner = &mesh[i];
446 /* edge deltas will always come out as zero */
447 sparrow_corner_t *right = (x >= width - 1) ? corner : corner + 1;
448 sparrow_corner_t *down = (y >= height - 1) ? corner : corner + width;
449 GST_DEBUG("i %d xy %d,%d width %d. in_xy %d,%d; down in_xy %d,%d; right in_xy %d,%d\n",
450 i, x, y, width, corner->in_x, corner->in_y, down->in_x,
451 down->in_y, right->in_x, right->in_y);
452 if (corner->used){
453 corner->dxr = (right->in_x - corner->in_x) / LINE_PERIOD;
454 corner->dyr = (right->in_y - corner->in_y) / LINE_PERIOD;
455 corner->dxd = (down->in_x - corner->in_x) / LINE_PERIOD;
456 corner->dyd = (down->in_y - corner->in_y) / LINE_PERIOD;
458 else {
459 /*prefer copy from left unless it is itself reconstructed (for no
460 great reason), or it has no dx/dy because it is an edge piece.
461 A mixed copy would be possible and better */
462 sparrow_corner_t *rsrc = (right->used &&
463 (right->used <= down->used) &&
464 (right != corner)) ? right : down;
465 sparrow_corner_t *dsrc = (down->used &&
466 (right->used >= down->used) &&
467 (down != corner)) ? down : right;
468 corner->dxr = rsrc->dxr;
469 corner->dyr = rsrc->dyr;
470 corner->dxd = dsrc->dxd;
471 corner->dyd = dsrc->dyd;
472 /*now extrapolate position, preferably from both left and right */
473 int cx = 0, cy = 0, cc = 0;
474 if (right != corner){
475 cc = 1;
476 cx = right->in_x - corner->dxr * LINE_PERIOD;
477 cy = right->in_y - corner->dyr * LINE_PERIOD;
479 if (down != corner){
480 cx += down->in_x - corner->dxd * LINE_PERIOD;
481 cy += down->in_y - corner->dyd * LINE_PERIOD;
482 cx >>= cc;
483 cy >>= cc;
485 /* if neither right nor down are there, this
486 corner can't be placed */
487 corner->in_x = cx;
488 corner->in_y = cy;
489 corner->used = MAX(right->used, down->used) + 1;
495 static void
496 find_corners(GstSparrow *sparrow, guint8 *in, sparrow_find_lines_t *fl){
497 find_corners_make_clusters(sparrow, in, fl);
498 if (sparrow->debug){
499 debug_clusters(sparrow, fl);
501 find_corners_make_corners(sparrow, in, fl);
502 find_corners_make_map(sparrow, in, fl);
503 if (sparrow->debug){
504 DEBUG_FIND_LINES(fl);
505 debug_corners_image(sparrow, fl);
510 /* With no line drawn (in our colour) look at the background noise. Any real
511 signal has to be stringer than this.
513 XXX looking for simple maximum -- maybe heap or histogram might be better,
514 so as to be less susceptible to wierd outliers (e.g., bad pixels). */
515 static void
516 look_for_threshold(GstSparrow *sparrow, guint8 *in, sparrow_find_lines_t *fl){
517 //DEBUG_FIND_LINES(fl);
518 int i;
519 guint32 colour;
520 guint32 signal;
521 guint32 *in32 = (guint32 *)in;
522 guint32 highest = 0;
523 for (i = 0; i < (int)sparrow->in.pixcount; i++){
524 colour = in32[i] & sparrow->colour;
525 signal = ((colour >> fl->shift1) +
526 (colour >> fl->shift2)) & 0x1ff;
527 if (signal > highest){
528 highest = signal;
531 fl->threshold = highest + 1;
532 GST_DEBUG("found maximum noise of %d, using threshold %d\n", highest, fl->threshold);
536 static void
537 look_for_line(GstSparrow *sparrow, guint8 *in, sparrow_find_lines_t *fl,
538 sparrow_line_t *line){
539 guint i;
540 guint32 colour;
541 int signal;
542 guint32 *in32 = (guint32 *)in;
543 for (i = 0; i < sparrow->in.pixcount; i++){
544 colour = in32[i] & sparrow->colour;
545 signal = ((colour >> fl->shift1) +
546 (colour >> fl->shift2)) & 0x1ff;
547 if (signal > fl->threshold){
548 if (fl->map[i].lines[line->dir]){
549 GST_DEBUG("HEY, expected point %d to be in line %d (dir %d)"
550 "and thus empty, but it is also in line %d\n",
551 i, line->index, line->dir, fl->map[i].lines[line->dir]);
553 fl->map[i].lines[line->dir] = line->index;
554 fl->map[i].signal[line->dir] = signal;
559 static void
560 debug_map_image(GstSparrow *sparrow, sparrow_find_lines_t *fl){
561 guint32 *data = (guint32*)fl->debug->imageData;
562 memset(data, 0, sparrow->in.size);
563 for (guint i = 0; i < sparrow->in.pixcount; i++){
564 data[i] |= fl->map[i].signal[SPARROW_HORIZONTAL] << sparrow->in.gshift;
565 data[i] |= fl->map[i].signal[SPARROW_VERTICAL] << sparrow->in.rshift;
567 MAYBE_DEBUG_IPL(fl->debug);
570 /* draw the line (in sparrow->colour) */
571 static inline void
572 draw_line(GstSparrow * sparrow, sparrow_line_t *line, guint8 *out){
573 guint32 *p = (guint32 *)out;
574 int i;
575 if (line->dir == SPARROW_HORIZONTAL){
576 p += line->offset * sparrow->out.width;
577 for (i = 0; i < sparrow->out.width; i++){
578 p[i] = sparrow->colour;
581 else {
582 guint32 *p = (guint32 *)out;
583 p += line->offset;
584 for(i = 0; i < sparrow->out.height; i++){
585 *p = sparrow->colour;
586 p += sparrow->out.width;
592 /* show each line for 2 frames, then wait sparrow->lag frames, leaving line on
593 until last one.
596 INVISIBLE sparrow_state
597 mode_find_edges(GstSparrow *sparrow, guint8 *in, guint8 *out){
598 sparrow_find_lines_t *fl = (sparrow_find_lines_t *)sparrow->helper_struct;
599 //DEBUG_FIND_LINES(fl);
600 if (fl->current == fl->n_lines){
601 goto done;
603 sparrow_line_t *line = fl->shuffled_lines[fl->current];
605 sparrow->countdown--;
606 memset(out, 0, sparrow->out.size);
607 if (sparrow->countdown){
608 /* show the line except on the first round, when we find a threshold*/
609 if (fl->threshold){
610 GST_DEBUG("current %d line %p\n", fl->current, line);
611 draw_line(sparrow, line, out);
614 else{
615 /*show nothing, look for result */
616 if (fl->threshold){
617 look_for_line(sparrow, in, fl, line);
618 fl->current++;
620 else {
621 look_for_threshold(sparrow, in, fl);
623 sparrow->countdown = sparrow->lag + 2;
625 if (sparrow->debug){
626 debug_map_image(sparrow, fl);
628 return SPARROW_STATUS_QUO;
629 done:
630 /*match up lines and find corners */
631 find_corners(sparrow, in, fl);
632 corners_to_lut(sparrow, fl);
634 return SPARROW_NEXT_STATE;
637 INVISIBLE void
638 finalise_find_edges(GstSparrow *sparrow){
639 sparrow_find_lines_t *fl = (sparrow_find_lines_t *)sparrow->helper_struct;
640 //DEBUG_FIND_LINES(fl);
641 if (sparrow->debug){
642 cvReleaseImage(&fl->debug);
644 free(fl->h_lines);
645 free(fl->shuffled_lines);
646 free(fl->map);
647 free(fl->mesh);
648 free(fl->clusters);
649 free(fl);
650 sparrow->helper_struct = NULL;
654 static void
655 setup_colour_shifts(GstSparrow *sparrow, sparrow_find_lines_t *fl){
656 switch (sparrow->colour){
657 case SPARROW_WHITE:
658 case SPARROW_GREEN:
659 fl->shift1 = sparrow->in.gshift;
660 fl->shift2 = sparrow->in.gshift;
661 break;
662 case SPARROW_MAGENTA:
663 fl->shift1 = sparrow->in.rshift;
664 fl->shift2 = sparrow->in.bshift;
665 break;
669 INVISIBLE void
670 init_find_edges(GstSparrow *sparrow){
671 gint32 w = sparrow->out.width;
672 gint32 h = sparrow->out.height;
673 gint i;
674 sparrow_find_lines_t *fl = zalloc_aligned_or_die(sizeof(sparrow_find_lines_t));
675 sparrow->helper_struct = (void *)fl;
677 gint h_lines = (h + LINE_PERIOD - 1) / LINE_PERIOD;
678 gint v_lines = (w + LINE_PERIOD - 1) / LINE_PERIOD;
679 gint n_lines = (h_lines + v_lines);
680 gint n_corners = (h_lines * v_lines);
681 fl->n_hlines = h_lines;
682 fl->n_vlines = v_lines;
683 fl->n_lines = n_lines;
685 fl->h_lines = malloc_aligned_or_die(sizeof(sparrow_line_t) * n_lines);
686 fl->shuffled_lines = malloc_aligned_or_die(sizeof(sparrow_line_t*) * n_lines);
687 GST_DEBUG("shuffled lines, malloced %p\n", fl->shuffled_lines);
688 fl->map = zalloc_aligned_or_die(sizeof(sparrow_intersect_t) * sparrow->in.pixcount);
689 fl->clusters = zalloc_or_die(n_corners * sizeof(sparrow_cluster_t));
690 fl->mesh = zalloc_aligned_or_die(n_corners * sizeof(sparrow_corner_t));
692 sparrow_line_t *line = fl->h_lines;
693 sparrow_line_t **sline = fl->shuffled_lines;
694 int offset = LINE_PERIOD / 2;
696 for (i = 0, offset = LINE_PERIOD / 2; offset < h;
697 i++, offset += LINE_PERIOD){
698 line->offset = offset;
699 line->dir = SPARROW_HORIZONTAL;
700 line->index = i;
701 *sline = line;
702 line++;
703 sline++;
706 /*now add the vertical lines */
707 fl->v_lines = line;
708 for (i = 0, offset = LINE_PERIOD / 2; offset < w;
709 i++, offset += LINE_PERIOD){
710 line->offset = offset;
711 line->dir = SPARROW_VERTICAL;
712 line->index = i;
713 *sline = line;
714 line++;
715 sline++;
717 //DEBUG_FIND_LINES(fl);
719 GST_DEBUG("allocated %d lines, used %d\n", n_lines, line - fl->h_lines);
721 /*now shuffle */
722 for (i = 0; i < n_lines - 1; i++){
723 int j = RANDINT(sparrow, 0, n_lines);
724 sparrow_line_t *tmp = fl->shuffled_lines[j];
725 fl->shuffled_lines[j] = fl->shuffled_lines[i];
726 fl->shuffled_lines[i] = tmp;
729 setup_colour_shifts(sparrow, fl);
730 sparrow->countdown = sparrow->lag + 2;
731 //DEBUG_FIND_LINES(fl);
732 if (sparrow->debug){
733 CvSize size = {sparrow->in.width, sparrow->in.height};
734 fl->debug = cvCreateImage(size, IPL_DEPTH_8U, PIXSIZE);