apriltag.c
Go to the documentation of this file.
1 /* Copyright (C) 2013-2016, The Regents of The University of Michigan.
2 All rights reserved.
3 
4 This software was developed in the APRIL Robotics Lab under the
5 direction of Edwin Olson, ebolson@umich.edu. This software may be
6 available under alternative licensing terms; contact the address above.
7 
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10 
11 1. Redistributions of source code must retain the above copyright notice, this
12  list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 The views and conclusions contained in the software and documentation are those
29 of the authors and should not be interpreted as representing official policies,
30 either expressed or implied, of the Regents of The University of Michigan.
31 */
32 
33 #include "apriltag.h"
34 
35 #include <math.h>
36 #include <assert.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <stdio.h>
40 #include <inttypes.h>
41 #include <sys/time.h>
42 
43 #include "common/image_u8.h"
44 #include "common/image_u8x3.h"
45 #include "common/zhash.h"
46 #include "common/zarray.h"
47 #include "common/matd.h"
48 #include "common/homography.h"
49 #include "common/timeprofile.h"
50 #include "common/math_util.h"
51 #include "common/g2d.h"
52 #include "common/floats.h"
53 
54 #include "apriltag_math.h"
55 
57 
58 #ifndef M_PI
59 # define M_PI 3.141592653589793238462643383279502884196
60 #endif
61 
64 
65 // Regresses a model of the form:
66 // intensity(x,y) = C0*x + C1*y + CC2
67 // The J matrix is the:
68 // J = [ x1 y1 1 ]
69 // [ x2 y2 1 ]
70 // [ ... ]
71 // The A matrix is J'J
72 
73 struct graymodel
74 {
75  double A[3][3];
76  double B[3];
77  double C[3];
78 };
79 
80 void graymodel_init(struct graymodel *gm)
81 {
82  memset(gm, 0, sizeof(struct graymodel));
83 }
84 
85 void graymodel_add(struct graymodel *gm, double x, double y, double gray)
86 {
87  // update upper right entries of A = J'J
88  gm->A[0][0] += x*x;
89  gm->A[0][1] += x*y;
90  gm->A[0][2] += x;
91  gm->A[1][1] += y*y;
92  gm->A[1][2] += y;
93  gm->A[2][2] += 1;
94 
95  // update B = J'gray
96  gm->B[0] += x * gray;
97  gm->B[1] += y * gray;
98  gm->B[2] += gray;
99 }
100 
101 void graymodel_solve(struct graymodel *gm)
102 {
103  mat33_sym_solve((double*) gm->A, gm->B, gm->C);
104 }
105 
106 double graymodel_interpolate(struct graymodel *gm, double x, double y)
107 {
108  return gm->C[0]*x + gm->C[1]*y + gm->C[2];
109 }
110 
112 {
113  uint64_t rcode; // the queried code
114  uint16_t id; // the tag ID (a small integer)
115  uint8_t hamming; // how many errors corrected?
116  uint8_t rotation; // number of rotations [0, 3]
117 };
118 
120 {
121  int nentries;
123 };
124 
133 static uint64_t rotate90(uint64_t w, uint32_t d)
134 {
135  uint64_t wr = 0;
136 
137  for (int32_t r = d-1; r >=0; r--) {
138  for (int32_t c = 0; c < d; c++) {
139  int32_t b = r + d*c;
140 
141  wr = wr << 1;
142 
143  if ((w & (((uint64_t) 1) << b))!=0)
144  wr |= 1;
145  }
146  }
147 
148  return wr;
149 }
150 
151 void quad_destroy(struct quad *quad)
152 {
153  if (!quad)
154  return;
155 
156  matd_destroy(quad->H);
157  matd_destroy(quad->Hinv);
158  free(quad);
159 }
160 
161 struct quad *quad_copy(struct quad *quad)
162 {
163  struct quad *q = calloc(1, sizeof(struct quad));
164  memcpy(q, quad, sizeof(struct quad));
165  if (quad->H)
166  q->H = matd_copy(quad->H);
167  if (quad->Hinv)
168  q->Hinv = matd_copy(quad->Hinv);
169  return q;
170 }
171 
172 void quick_decode_add(struct quick_decode *qd, uint64_t code, int id, int hamming)
173 {
174  uint32_t bucket = code % qd->nentries;
175 
176  while (qd->entries[bucket].rcode != UINT64_MAX) {
177  bucket = (bucket + 1) % qd->nentries;
178  }
179 
180  qd->entries[bucket].rcode = code;
181  qd->entries[bucket].id = id;
182  qd->entries[bucket].hamming = hamming;
183 }
184 
186 {
187  if (!fam->impl)
188  return;
189 
190  struct quick_decode *qd = (struct quick_decode*) fam->impl;
191  free(qd->entries);
192  free(qd);
193  fam->impl = NULL;
194 }
195 
196 void quick_decode_init(apriltag_family_t *family, int maxhamming)
197 {
198  assert(family->impl == NULL);
199  assert(family->ncodes < 65535);
200 
201  struct quick_decode *qd = calloc(1, sizeof(struct quick_decode));
202  int capacity = family->ncodes;
203 
204  int nbits = family->d * family->d;
205 
206  if (maxhamming >= 1)
207  capacity += family->ncodes * nbits;
208 
209  if (maxhamming >= 2)
210  capacity += family->ncodes * nbits * (nbits-1);
211 
212  if (maxhamming >= 3)
213  capacity += family->ncodes * nbits * (nbits-1) * (nbits-2);
214 
215  qd->nentries = capacity * 3;
216 
217 // printf("capacity %d, size: %.0f kB\n",
218 // capacity, qd->nentries * sizeof(struct quick_decode_entry) / 1024.0);
219 
220  qd->entries = calloc(qd->nentries, sizeof(struct quick_decode_entry));
221  if (qd->entries == NULL) {
222  printf("apriltag.c: failed to allocate hamming decode table. Reduce max hamming size.\n");
223  exit(-1);
224  }
225 
226  for (int i = 0; i < qd->nentries; i++)
227  qd->entries[i].rcode = UINT64_MAX;
228 
229  for (int i = 0; i < family->ncodes; i++) {
230  uint64_t code = family->codes[i];
231 
232  // add exact code (hamming = 0)
233  quick_decode_add(qd, code, i, 0);
234 
235  if (maxhamming >= 1) {
236  // add hamming 1
237  for (int j = 0; j < nbits; j++)
238  quick_decode_add(qd, code ^ (1L << j), i, 1);
239  }
240 
241  if (maxhamming >= 2) {
242  // add hamming 2
243  for (int j = 0; j < nbits; j++)
244  for (int k = 0; k < j; k++)
245  quick_decode_add(qd, code ^ (1L << j) ^ (1L << k), i, 2);
246  }
247 
248  if (maxhamming >= 3) {
249  // add hamming 3
250  for (int j = 0; j < nbits; j++)
251  for (int k = 0; k < j; k++)
252  for (int m = 0; m < k; m++)
253  quick_decode_add(qd, code ^ (1L << j) ^ (1L << k) ^ (1L << m), i, 3);
254  }
255 
256  if (maxhamming > 3) {
257  printf("apriltag.c: maxhamming beyond 3 not supported\n");
258  }
259  }
260 
261  family->impl = qd;
262 
263  if (0) {
264  int longest_run = 0;
265  int run = 0;
266  int run_sum = 0;
267  int run_count = 0;
268 
269  // This accounting code doesn't check the last possible run that
270  // occurs at the wrap-around. That's pretty insignificant.
271  for (int i = 0; i < qd->nentries; i++) {
272  if (qd->entries[i].rcode == UINT64_MAX) {
273  if (run > 0) {
274  run_sum += run;
275  run_count ++;
276  }
277  run = 0;
278  } else {
279  run ++;
280  longest_run = imax(longest_run, run);
281  }
282  }
283 
284  printf("quick decode: longest run: %d, average run %.3f\n", longest_run, 1.0 * run_sum / run_count);
285  }
286 }
287 
288 // returns an entry with hamming set to 255 if no decode was found.
289 static void quick_decode_codeword(apriltag_family_t *tf, uint64_t rcode,
290  struct quick_decode_entry *entry)
291 {
292  struct quick_decode *qd = (struct quick_decode*) tf->impl;
293 
294  for (int ridx = 0; ridx < 4; ridx++) {
295 
296  for (int bucket = rcode % qd->nentries;
297  qd->entries[bucket].rcode != UINT64_MAX;
298  bucket = (bucket + 1) % qd->nentries) {
299 
300  if (qd->entries[bucket].rcode == rcode) {
301  *entry = qd->entries[bucket];
302  entry->rotation = ridx;
303  return;
304  }
305  }
306 
307  rcode = rotate90(rcode, tf->d);
308  }
309 
310  entry->rcode = 0;
311  entry->id = 65535;
312  entry->hamming = 255;
313  entry->rotation = 0;
314 }
315 
316 static inline int detection_compare_function(const void *_a, const void *_b)
317 {
320 
321  return a->id - b->id;
322 }
323 
325 {
326  quick_decode_uninit(fam);
327  zarray_remove_value(td->tag_families, &fam, 0);
328 }
329 
331 {
332  zarray_add(td->tag_families, &fam);
333 
334  if (!fam->impl)
335  quick_decode_init(fam, bits_corrected);
336 }
337 
339 {
340  for (int i = 0; i < zarray_size(td->tag_families); i++) {
341  apriltag_family_t *fam;
342  zarray_get(td->tag_families, i, &fam);
343  quick_decode_uninit(fam);
344  }
346 }
347 
349 {
350  apriltag_detector_t *td = (apriltag_detector_t*) calloc(1, sizeof(apriltag_detector_t));
351 
352  td->nthreads = 1;
353  td->quad_decimate = 1.0;
354  td->quad_sigma = 0.0;
355 
356  td->qtp.max_nmaxima = 10;
357  td->qtp.min_cluster_pixels = 5;
358 
359  td->qtp.max_line_fit_mse = 10.0;
360  td->qtp.critical_rad = 10 * M_PI / 180;
361  td->qtp.deglitch = 0;
362  td->qtp.min_white_black_diff = 5;
363 
365 
366  pthread_mutex_init(&td->mutex, NULL);
367 
368  td->tp = timeprofile_create();
369 
370  td->refine_edges = 1;
371  td->refine_pose = 0;
372  td->refine_decode = 0;
373 
374  td->debug = 0;
375 
376  // NB: defer initialization of td->wp so that the user can
377  // override td->nthreads.
378 
379  return td;
380 }
381 
383 {
384  timeprofile_destroy(td->tp);
385  workerpool_destroy(td->wp);
386 
388 
390  free(td);
391 }
392 
394 {
395  int i0, i1;
398 
401 
403 };
404 
406 {
407  int64_t rcode;
408  double score;
409  matd_t *H, *Hinv;
410 
413 };
414 
415 // returns non-zero if an error occurs (i.e., H has no inverse)
417 {
418  zarray_t *correspondences = zarray_create(sizeof(float[4]));
419 
420  for (int i = 0; i < 4; i++) {
421  float corr[4];
422 
423  // At this stage of the pipeline, we have not attempted to decode the
424  // quad into an oriented tag. Thus, just act as if the quad is facing
425  // "up" with respect to our desired corners. We'll fix the rotation
426  // later.
427  // [-1, -1], [1, -1], [1, 1], [-1, 1]
428  corr[0] = (i==0 || i==3) ? -1 : 1;
429  corr[1] = (i==0 || i==1) ? -1 : 1;
430 
431  corr[2] = quad->p[i][0];
432  corr[3] = quad->p[i][1];
433 
434  zarray_add(correspondences, &corr);
435  }
436 
437  if (quad->H)
438  matd_destroy(quad->H);
439  if (quad->Hinv)
440  matd_destroy(quad->Hinv);
441 
442  // XXX Tunable
443  quad->H = homography_compute(correspondences, HOMOGRAPHY_COMPUTE_FLAG_SVD);
444  quad->Hinv = matd_inverse(quad->H);
445  zarray_destroy(correspondences);
446 
447  if (quad->H && quad->Hinv)
448  return 0;
449 
450  return -1;
451 }
452 
453 // compute a "score" for a quad that is independent of tag family
454 // encoding (but dependent upon the tag geometry) by considering the
455 // contrast around the exterior of the tag.
456 double quad_goodness(apriltag_family_t *family, image_u8_t *im, struct quad *quad)
457 {
458  // when sampling from the white border, how much white border do
459  // we actually consider valid, measured in bit-cell units? (the
460  // outside portions are often intruded upon, so it could be advantageous to use
461  // less than the "nominal" 1.0. (Less than 1.0 not well tested.)
462 
463  // XXX Tunable
464  float white_border = 1;
465 
466  // in tag coordinates, how big is each bit cell?
467  double bit_size = 2.0 / (2*family->black_border + family->d);
468 // double inv_bit_size = 1.0 / bit_size;
469 
470  int32_t xmin = INT32_MAX, xmax = 0, ymin = INT32_MAX, ymax = 0;
471 
472  for (int i = 0; i < 4; i++) {
473  double tx = (i == 0 || i == 3) ? -1 - bit_size : 1 + bit_size;
474  double ty = (i == 0 || i == 1) ? -1 - bit_size : 1 + bit_size;
475  double x, y;
476 
477  homography_project(quad->H, tx, ty, &x, &y);
478  xmin = imin(xmin, x);
479  xmax = imax(xmax, x);
480  ymin = imin(ymin, y);
481  ymax = imax(ymax, y);
482  }
483 
484  // clamp bounding box to image dimensions
485  xmin = imax(0, xmin);
486  xmax = imin(im->width-1, xmax);
487  ymin = imax(0, ymin);
488  ymax = imin(im->height-1, ymax);
489 
490 // int nbits = family->d * family->d;
491 
492  int64_t W1 = 0, B1 = 0, Wn = 0, Bn = 0;
493 
494  float wsz = bit_size*white_border;
495  float bsz = bit_size*family->black_border;
496 
497  matd_t *Hinv = quad->Hinv;
498 // matd_t *H = quad->H;
499 
500  // iterate over all the pixels in the tag. (Iterating in pixel space)
501  for (int y = ymin; y <= ymax; y++) {
502 
503  // we'll incrementally compute the homography
504  // projections. Begin by evaluating the homogeneous position
505  // [(xmin - .5f), y, 1]. Then, we'll update as we stride in
506  // the +x direction.
507  double Hx = MATD_EL(Hinv, 0, 0) * (.5 + (int) xmin) +
508  MATD_EL(Hinv, 0, 1) * (y + .5) + MATD_EL(Hinv, 0, 2);
509  double Hy = MATD_EL(Hinv, 1, 0) * (.5 + (int) xmin) +
510  MATD_EL(Hinv, 1, 1) * (y + .5) + MATD_EL(Hinv, 1, 2);
511  double Hh = MATD_EL(Hinv, 2, 0) * (.5 + (int) xmin) +
512  MATD_EL(Hinv, 2, 1) * (y + .5) + MATD_EL(Hinv, 2, 2);
513 
514  for (int x = xmin; x <= xmax; x++) {
515  // project the pixel center.
516  double tx, ty;
517 
518  // divide by homogeneous coordinate
519  tx = Hx / Hh;
520  ty = Hy / Hh;
521 
522  // if we move x one pixel to the right, here's what
523  // happens to our three pre-normalized coordinates.
524  Hx += MATD_EL(Hinv, 0, 0);
525  Hy += MATD_EL(Hinv, 1, 0);
526  Hh += MATD_EL(Hinv, 2, 0);
527 
528  float txa = fabsf((float) tx), tya = fabsf((float) ty);
529  float xymax = fmaxf(txa, tya);
530 
531 // if (txa >= 1 + wsz || tya >= 1 + wsz)
532  if (xymax >= 1 + wsz)
533  continue;
534 
535  uint8_t v = im->buf[y*im->stride + x];
536 
537  // it's within the white border?
538 // if (txa >= 1 || tya >= 1) {
539  if (xymax >= 1) {
540  W1 += v;
541  Wn ++;
542  continue;
543  }
544 
545  // it's within the black border?
546 // if (txa >= 1 - bsz || tya >= 1 - bsz) {
547  if (xymax >= 1 - bsz) {
548  B1 += v;
549  Bn ++;
550  continue;
551  }
552 
553  // it must be a data bit. We don't do anything with these.
554  continue;
555  }
556  }
557 
558 
559  // score = average margin between white and black pixels near border.
560  double margin = 1.0 * W1 / Wn - 1.0 * B1 / Bn;
561 // printf("margin %f: W1 %f, B1 %f\n", margin, W1, B1);
562 
563  return margin;
564 }
565 
566 // returns the decision margin. Return < 0 if the detection should be rejected.
567 float quad_decode(apriltag_family_t *family, image_u8_t *im, struct quad *quad, struct quick_decode_entry *entry, image_u8_t *im_samples)
568 {
569  // decode the tag binary contents by sampling the pixel
570  // closest to the center of each bit cell.
571 
572  int64_t rcode = 0;
573 
574  // how wide do we assume the white border is?
575  float white_border = 1.0;
576 
577  // We will compute a threshold by sampling known white/black cells around this tag.
578  // This sampling is achieved by considering a set of samples along lines.
579  //
580  // coordinates are given in bit coordinates. ([0, fam->d]).
581  //
582  // { initial x, initial y, delta x, delta y, WHITE=1 }
583  float patterns[] = {
584  // left white column
585  0 - white_border / 2.0, 0.5,
586  0, 1,
587  1,
588 
589  // left black column
590  0 + family->black_border / 2.0, 0.5,
591  0, 1,
592  0,
593 
594  // right white column
595  2*family->black_border + family->d + white_border / 2.0, .5,
596  0, 1,
597  1,
598 
599  // right black column
600  2*family->black_border + family->d - family->black_border / 2.0, .5,
601  0, 1,
602  0,
603 
604  // top white row
605  0.5, -white_border / 2.0,
606  1, 0,
607  1,
608 
609  // top black row
610  0.5, family->black_border / 2.0,
611  1, 0,
612  0,
613 
614  // bottom white row
615  0.5, 2*family->black_border + family->d + white_border / 2.0,
616  1, 0,
617  1,
618 
619  // bottom black row
620  0.5, 2*family->black_border + family->d - family->black_border / 2.0,
621  1, 0,
622  0
623 
624  // XXX double-counts the corners.
625  };
626 
627  struct graymodel whitemodel, blackmodel;
628  graymodel_init(&whitemodel);
629  graymodel_init(&blackmodel);
630 
631  for (int pattern_idx = 0; pattern_idx < sizeof(patterns)/(5*sizeof(float)); pattern_idx ++) {
632  float *pattern = &patterns[pattern_idx * 5];
633 
634  int is_white = pattern[4];
635 
636  for (int i = 0; i < 2*family->black_border + family->d; i++) {
637  double tagx01 = (pattern[0] + i*pattern[2]) / (2*family->black_border + family->d);
638  double tagy01 = (pattern[1] + i*pattern[3]) / (2*family->black_border + family->d);
639 
640  double tagx = 2*(tagx01-0.5);
641  double tagy = 2*(tagy01-0.5);
642 
643  double px, py;
644  homography_project(quad->H, tagx, tagy, &px, &py);
645 
646  // don't round
647  int ix = px;
648  int iy = py;
649  if (ix < 0 || iy < 0 || ix >= im->width || iy >= im->height)
650  continue;
651 
652  int v = im->buf[iy*im->stride + ix];
653 
654  if (im_samples) {
655  im_samples->buf[iy*im_samples->stride + ix] = (1-is_white)*255;
656  }
657 
658  if (is_white)
659  graymodel_add(&whitemodel, tagx, tagy, v);
660  else
661  graymodel_add(&blackmodel, tagx, tagy, v);
662  }
663  }
664 
665  graymodel_solve(&whitemodel);
666  graymodel_solve(&blackmodel);
667 
668  // XXX Tunable
669  if (graymodel_interpolate(&whitemodel, 0, 0) - graymodel_interpolate(&blackmodel, 0, 0) < 0)
670  return -1;
671 
672  // compute the average decision margin (how far was each bit from
673  // the decision boundary?
674  //
675  // we score this separately for white and black pixels and return
676  // the minimum average threshold for black/white pixels. This is
677  // to penalize thresholds that are too close to an extreme.
678  float black_score = 0, white_score = 0;
679  float black_score_count = 1, white_score_count = 1;
680 
681  for (int bitidx = 0; bitidx < family->d * family->d; bitidx++) {
682  int bitx = bitidx % family->d;
683  int bity = bitidx / family->d;
684 
685  double tagx01 = (family->black_border + bitx + 0.5) / (2*family->black_border + family->d);
686  double tagy01 = (family->black_border + bity + 0.5) / (2*family->black_border + family->d);
687 
688  // scale to [-1, 1]
689  double tagx = 2*(tagx01-0.5);
690  double tagy = 2*(tagy01-0.5);
691 
692  double px, py;
693  homography_project(quad->H, tagx, tagy, &px, &py);
694 
695  rcode = (rcode << 1);
696 
697  // don't round.
698  int ix = px;
699  int iy = py;
700 
701  if (ix < 0 || iy < 0 || ix >= im->width || iy >= im->height)
702  continue;
703 
704  int v = im->buf[iy*im->stride + ix];
705 
706  double thresh = (graymodel_interpolate(&blackmodel, tagx, tagy) + graymodel_interpolate(&whitemodel, tagx, tagy)) / 2.0;
707  if (v > thresh) {
708  white_score += (v - thresh);
709  white_score_count ++;
710  rcode |= 1;
711  } else {
712  black_score += (thresh - v);
713  black_score_count ++;
714  }
715 
716  if (im_samples)
717  im_samples->buf[iy*im_samples->stride + ix] = (1 - (rcode & 1)) * 255;
718  }
719 
720  quick_decode_codeword(family, rcode, entry);
721 
722  return fmin(white_score / white_score_count, black_score / black_score_count);
723 }
724 
725 double score_goodness(apriltag_family_t *family, image_u8_t *im, struct quad *quad, void *user)
726 {
727  return quad_goodness(family, im, quad);
728 }
729 
730 double score_decodability(apriltag_family_t *family, image_u8_t *im, struct quad *quad, void *user)
731 {
732  struct quick_decode_entry entry;
733 
734  float decision_margin = quad_decode(family, im, quad, &entry, NULL);
735 
736  // hamming trumps decision margin; maximum value for decision_margin is 255.
737  return decision_margin - entry.hamming*1000;
738 }
739 
740 // returns score of best quad
741 double optimize_quad_generic(apriltag_family_t *family, image_u8_t *im, struct quad *quad0,
742  float *stepsizes, int nstepsizes,
743  double (*score)(apriltag_family_t *family, image_u8_t *im, struct quad *quad, void *user),
744  void *user)
745 {
746  struct quad *best_quad = quad_copy(quad0);
747  double best_score = score(family, im, best_quad, user);
748 
749  for (int stepsize_idx = 0; stepsize_idx < nstepsizes; stepsize_idx++) {
750 
751  int improved = 1;
752 
753  // when we make progress with a particular step size, how many
754  // times will we try to perform that same step size again?
755  // (max_repeat = 0 means ("don't repeat--- just move to the
756  // next step size").
757  // XXX Tunable
758  int max_repeat = 1;
759 
760  for (int repeat = 0; repeat <= max_repeat && improved; repeat++) {
761 
762  improved = 0;
763 
764  // wiggle point i
765  for (int i = 0; i < 4; i++) {
766 
767  float stepsize = stepsizes[stepsize_idx];
768 
769  // XXX Tunable (really 1 makes the best sense since)
770  int nsteps = 1;
771 
772  struct quad *this_best_quad = NULL;
773  double this_best_score = best_score;
774 
775  for (int sx = -nsteps; sx <= nsteps; sx++) {
776  for (int sy = -nsteps; sy <= nsteps; sy++) {
777  if (sx==0 && sy==0)
778  continue;
779 
780  struct quad *this_quad = quad_copy(best_quad);
781  this_quad->p[i][0] = best_quad->p[i][0] + sx*stepsize;
782  this_quad->p[i][1] = best_quad->p[i][1] + sy*stepsize;
783  if (quad_update_homographies(this_quad))
784  continue;
785 
786  double this_score = score(family, im, this_quad, user);
787 
788  if (this_score > this_best_score) {
789  quad_destroy(this_best_quad);
790 
791  this_best_quad = this_quad;
792  this_best_score = this_score;
793  } else {
794  quad_destroy(this_quad);
795  }
796  }
797  }
798 
799  if (this_best_score > best_score) {
800  quad_destroy(best_quad);
801  best_quad = this_best_quad;
802  best_score = this_best_score;
803  improved = 1;
804  }
805  }
806  }
807  }
808 
809  matd_destroy(quad0->H);
810  matd_destroy(quad0->Hinv);
811  memcpy(quad0, best_quad, sizeof(struct quad)); // copy pointers
812  free(best_quad);
813  return best_score;
814 }
815 
816 static void refine_edges(apriltag_detector_t *td, image_u8_t *im_orig, struct quad *quad)
817 {
818  double lines[4][4]; // for each line, [Ex Ey nx ny]
819 
820  for (int edge = 0; edge < 4; edge++) {
821  int a = edge, b = (edge + 1) & 3; // indices of the end points.
822 
823  // compute the normal to the current line estimate
824  double nx = quad->p[b][1] - quad->p[a][1];
825  double ny = -quad->p[b][0] + quad->p[a][0];
826  double mag = sqrt(nx*nx + ny*ny);
827  nx /= mag;
828  ny /= mag;
829 
830  // we will now fit a NEW line by sampling points near
831  // our original line that have large gradients. On really big tags,
832  // we're willing to sample more to get an even better estimate.
833  int nsamples = imax(16, mag / 8); // XXX tunable
834 
835  // stats for fitting a line...
836  double Mx = 0, My = 0, Mxx = 0, Mxy = 0, Myy = 0, N = 0;
837 
838  for (int s = 0; s < nsamples; s++) {
839  // compute a point along the line... Note, we're avoiding
840  // sampling *right* at the corners, since those points are
841  // the least reliable.
842  double alpha = (1.0 + s) / (nsamples + 1);
843  double x0 = alpha*quad->p[a][0] + (1-alpha)*quad->p[b][0];
844  double y0 = alpha*quad->p[a][1] + (1-alpha)*quad->p[b][1];
845 
846  // search along the normal to this line, looking at the
847  // gradients along the way. We're looking for a strong
848  // response.
849  double Mn = 0;
850  double Mcount = 0;
851 
852  // XXX tunable: how far to search? We want to search far
853  // enough that we find the best edge, but not so far that
854  // we hit other edges that aren't part of the tag. We
855  // shouldn't ever have to search more than quad_decimate,
856  // since otherwise we would (ideally) have started our
857  // search on another pixel in the first place. Likewise,
858  // for very small tags, we don't want the range to be too
859  // big.
860  double range = td->quad_decimate + 1;
861 
862  // XXX tunable step size.
863  for (double n = -range; n <= range; n += 0.25) {
864  // Because of the guaranteed winding order of the
865  // points in the quad, we will start inside the white
866  // portion of the quad and work our way outward.
867  //
868  // sample to points (x1,y1) and (x2,y2) XXX tunable:
869  // how far +/- to look? Small values compute the
870  // gradient more precisely, but are more sensitive to
871  // noise.
872  double grange = 1;
873  int x1 = x0 + (n + grange)*nx;
874  int y1 = y0 + (n + grange)*ny;
875  if (x1 < 0 || x1 >= im_orig->width || y1 < 0 || y1 >= im_orig->height)
876  continue;
877 
878  int x2 = x0 + (n - grange)*nx;
879  int y2 = y0 + (n - grange)*ny;
880  if (x2 < 0 || x2 >= im_orig->width || y2 < 0 || y2 >= im_orig->height)
881  continue;
882 
883  int g1 = im_orig->buf[y1*im_orig->stride + x1];
884  int g2 = im_orig->buf[y2*im_orig->stride + x2];
885 
886  if (g1 < g2) // reject points whose gradient is "backwards". They can only hurt us.
887  continue;
888 
889  double weight = (g2 - g1)*(g2 - g1); // XXX tunable. What shape for weight=f(g2-g1)?
890 
891  // compute weighted average of the gradient at this point.
892  Mn += weight*n;
893  Mcount += weight;
894  }
895 
896  // what was the average point along the line?
897  if (Mcount == 0)
898  continue;
899 
900  double n0 = Mn / Mcount;
901 
902  // where is the point along the line?
903  double bestx = x0 + n0*nx;
904  double besty = y0 + n0*ny;
905 
906  // update our line fit statistics
907  Mx += bestx;
908  My += besty;
909  Mxx += bestx*bestx;
910  Mxy += bestx*besty;
911  Myy += besty*besty;
912  N++;
913  }
914 
915  // fit a line
916  double Ex = Mx / N, Ey = My / N;
917  double Cxx = Mxx / N - Ex*Ex;
918  double Cxy = Mxy / N - Ex*Ey;
919  double Cyy = Myy / N - Ey*Ey;
920 
921  double normal_theta = .5 * atan2f(-2*Cxy, (Cyy - Cxx));
922  nx = cosf(normal_theta);
923  ny = sinf(normal_theta);
924  lines[edge][0] = Ex;
925  lines[edge][1] = Ey;
926  lines[edge][2] = nx;
927  lines[edge][3] = ny;
928  }
929 
930  // now refit the corners of the quad
931  for (int i = 0; i < 4; i++) {
932 
933  // solve for the intersection of lines (i) and (i+1)&3.
934  double A00 = lines[i][3], A01 = -lines[(i+1)&3][3];
935  double A10 = -lines[i][2], A11 = lines[(i+1)&3][2];
936  double B0 = -lines[i][0] + lines[(i+1)&3][0];
937  double B1 = -lines[i][1] + lines[(i+1)&3][1];
938 
939  double det = A00 * A11 - A10 * A01;
940 
941  // inverse.
942  if (fabs(det) > 0.001) {
943  // solve
944  double W00 = A11 / det, W01 = -A01 / det;
945 
946  double L0 = W00*B0 + W01*B1;
947 
948  // compute intersection
949  quad->p[i][0] = lines[i][0] + L0*A00;
950  quad->p[i][1] = lines[i][1] + L0*A10;
951  } else {
952  // this is a bad sign. We'll just keep the corner we had.
953 // printf("bad det: %15f %15f %15f %15f %15f\n", A00, A11, A10, A01, det);
954  }
955  }
956 }
957 
958 static void quad_decode_task(void *_u)
959 {
960  struct quad_decode_task *task = (struct quad_decode_task*) _u;
961  apriltag_detector_t *td = task->td;
962  image_u8_t *im = task->im;
963 
964  for (int quadidx = task->i0; quadidx < task->i1; quadidx++) {
965  struct quad *quad_original;
966  zarray_get_volatile(task->quads, quadidx, &quad_original);
967 
968  // refine edges is not dependent upon the tag family, thus
969  // apply this optimization BEFORE the other work.
970  //if (td->quad_decimate > 1 && td->refine_edges) {
971  if (td->refine_edges) {
972  refine_edges(td, im, quad_original);
973  }
974 
975  // make sure the homographies are computed...
976  if (quad_update_homographies(quad_original))
977  continue;
978 
979  for (int famidx = 0; famidx < zarray_size(td->tag_families); famidx++) {
980  apriltag_family_t *family;
981  zarray_get(td->tag_families, famidx, &family);
982 
983  double goodness = 0;
984 
985  // since the geometry of tag families can vary, start any
986  // optimization process over with the original quad.
987  struct quad *quad = quad_copy(quad_original);
988 
989  // improve the quad corner positions by minimizing the
990  // variance within each intra-bit area.
991  if (td->refine_pose) {
992  // NB: We potentially step an integer
993  // number of times in each direction. To make each
994  // sample as useful as possible, the step sizes should
995  // not be integer multiples of each other. (I.e.,
996  // probably don't use 1, 0.5, 0.25, etc.)
997 
998  // XXX Tunable
999  float stepsizes[] = { 1, .4, .16, .064 };
1000  int nstepsizes = sizeof(stepsizes)/sizeof(float);
1001 
1002  goodness = optimize_quad_generic(family, im, quad, stepsizes, nstepsizes, score_goodness, NULL);
1003  }
1004 
1005  if (td->refine_decode) {
1006  // this optimizes decodability, but we don't report
1007  // that value to the user. (so discard return value.)
1008  // XXX Tunable
1009  float stepsizes[] = { .4 };
1010  int nstepsizes = sizeof(stepsizes)/sizeof(float);
1011 
1012  optimize_quad_generic(family, im, quad, stepsizes, nstepsizes, score_decodability, NULL);
1013  }
1014 
1015  struct quick_decode_entry entry;
1016 
1017  float decision_margin = quad_decode(family, im, quad, &entry, task->im_samples);
1018 
1019  if (entry.hamming < 255 && decision_margin >= 0) {
1020  apriltag_detection_t *det = calloc(1, sizeof(apriltag_detection_t));
1021 
1022  det->family = family;
1023  det->id = entry.id;
1024  det->hamming = entry.hamming;
1025  det->goodness = goodness;
1026  det->decision_margin = decision_margin;
1027 
1028  double theta = -entry.rotation * M_PI / 2.0;
1029  double c = cos(theta), s = sin(theta);
1030 
1031  // Fix the rotation of our homography to properly orient the tag
1032  matd_t *R = matd_create(3,3);
1033  MATD_EL(R, 0, 0) = c;
1034  MATD_EL(R, 0, 1) = -s;
1035  MATD_EL(R, 1, 0) = s;
1036  MATD_EL(R, 1, 1) = c;
1037  MATD_EL(R, 2, 2) = 1;
1038 
1039  det->H = matd_op("M*M", quad->H, R);
1040 
1041  matd_destroy(R);
1042 
1043  homography_project(det->H, 0, 0, &det->c[0], &det->c[1]);
1044 
1045  // [-1, -1], [1, -1], [1, 1], [-1, 1], Desired points
1046  // [-1, 1], [1, 1], [1, -1], [-1, -1], FLIP Y
1047  // adjust the points in det->p so that they correspond to
1048  // counter-clockwise around the quad, starting at -1,-1.
1049  for (int i = 0; i < 4; i++) {
1050  int tcx = (i == 1 || i == 2) ? 1 : -1;
1051  int tcy = (i < 2) ? 1 : -1;
1052 
1053  double p[2];
1054 
1055  homography_project(det->H, tcx, tcy, &p[0], &p[1]);
1056 
1057  det->p[i][0] = p[0];
1058  det->p[i][1] = p[1];
1059  }
1060 
1061  pthread_mutex_lock(&td->mutex);
1062  zarray_add(task->detections, &det);
1063  pthread_mutex_unlock(&td->mutex);
1064  }
1065 
1066  quad_destroy(quad);
1067  }
1068  }
1069 }
1070 
1072 {
1073  if (det == NULL)
1074  return;
1075 
1076  matd_destroy(det->H);
1077  free(det);
1078 }
1079 
1080 int prefer_smaller(int pref, double q0, double q1)
1081 {
1082  if (pref) // already prefer something? exit.
1083  return pref;
1084 
1085  if (q0 < q1)
1086  return -1; // we now prefer q0
1087  if (q1 < q0)
1088  return 1; // we now prefer q1
1089 
1090  // no preference
1091  return 0;
1092 }
1093 
1095 {
1096  if (zarray_size(td->tag_families) == 0) {
1098  printf("apriltag.c: No tag families enabled.");
1099  return s;
1100  }
1101 
1102  if (td->wp == NULL || td->nthreads != workerpool_get_nthreads(td->wp)) {
1103  workerpool_destroy(td->wp);
1104  td->wp = workerpool_create(td->nthreads);
1105  }
1106 
1107  timeprofile_clear(td->tp);
1108  timeprofile_stamp(td->tp, "init");
1109 
1111  // Step 1. Detect quads according to requested image decimation
1112  // and blurring parameters.
1113  image_u8_t *quad_im = im_orig;
1114  if (td->quad_decimate > 1) {
1115  quad_im = image_u8_decimate(im_orig, td->quad_decimate);
1116 
1117  timeprofile_stamp(td->tp, "decimate");
1118  }
1119 
1120  if (td->quad_sigma != 0) {
1121  // compute a reasonable kernel width by figuring that the
1122  // kernel should go out 2 std devs.
1123  //
1124  // max sigma ksz
1125  // 0.499 1 (disabled)
1126  // 0.999 3
1127  // 1.499 5
1128  // 1.999 7
1129 
1130  float sigma = fabsf((float) td->quad_sigma);
1131 
1132  int ksz = 4 * sigma; // 2 std devs in each direction
1133  if ((ksz & 1) == 0)
1134  ksz++;
1135 
1136  if (ksz > 1) {
1137 
1138  if (td->quad_sigma > 0) {
1139  // Apply a blur
1140  image_u8_gaussian_blur(quad_im, sigma, ksz);
1141  } else {
1142  // SHARPEN the image by subtracting the low frequency components.
1143  image_u8_t *orig = image_u8_copy(quad_im);
1144  image_u8_gaussian_blur(quad_im, sigma, ksz);
1145 
1146  for (int y = 0; y < orig->height; y++) {
1147  for (int x = 0; x < orig->width; x++) {
1148  int vorig = orig->buf[y*orig->stride + x];
1149  int vblur = quad_im->buf[y*quad_im->stride + x];
1150 
1151  int v = 2*vorig - vblur;
1152  if (v < 0)
1153  v = 0;
1154  if (v > 255)
1155  v = 255;
1156 
1157  quad_im->buf[y*quad_im->stride + x] = (uint8_t) v;
1158  }
1159  }
1160  image_u8_destroy(orig);
1161  }
1162  }
1163  }
1164 
1165  timeprofile_stamp(td->tp, "blur/sharp");
1166 
1167  if (td->debug)
1168  image_u8_write_pnm(quad_im, "debug_preprocess.pnm");
1169 
1170 // zarray_t *quads = apriltag_quad_gradient(td, im_orig);
1171  zarray_t *quads = apriltag_quad_thresh(td, quad_im);
1172 
1173  // adjust centers of pixels so that they correspond to the
1174  // original full-resolution image.
1175  if (td->quad_decimate > 1) {
1176  for (int i = 0; i < zarray_size(quads); i++) {
1177  struct quad *q;
1178  zarray_get_volatile(quads, i, &q);
1179 
1180  for (int i = 0; i < 4; i++) {
1181  q->p[i][0] *= td->quad_decimate;
1182  q->p[i][1] *= td->quad_decimate;
1183  }
1184  }
1185  }
1186 
1187  if (quad_im != im_orig)
1188  image_u8_destroy(quad_im);
1189 
1190  zarray_t *detections = zarray_create(sizeof(apriltag_detection_t*));
1191 
1192  td->nquads = zarray_size(quads);
1193 
1194  timeprofile_stamp(td->tp, "quads");
1195 
1196  if (td->debug) {
1197  image_u8_t *im_quads = image_u8_copy(im_orig);
1198  image_u8_darken(im_quads);
1199  image_u8_darken(im_quads);
1200 
1201  srandom(0);
1202 
1203  for (int i = 0; i < zarray_size(quads); i++) {
1204  struct quad *quad;
1205  zarray_get_volatile(quads, i, &quad);
1206 
1207  const int bias = 100;
1208  int color = bias + (random() % (255-bias));
1209 
1210  image_u8_draw_line(im_quads, quad->p[0][0], quad->p[0][1], quad->p[1][0], quad->p[1][1], color, 1);
1211  image_u8_draw_line(im_quads, quad->p[1][0], quad->p[1][1], quad->p[2][0], quad->p[2][1], color, 1);
1212  image_u8_draw_line(im_quads, quad->p[2][0], quad->p[2][1], quad->p[3][0], quad->p[3][1], color, 1);
1213  image_u8_draw_line(im_quads, quad->p[3][0], quad->p[3][1], quad->p[0][0], quad->p[0][1], color, 1);
1214  }
1215 
1216  image_u8_write_pnm(im_quads, "debug_quads_raw.pnm");
1217  image_u8_destroy(im_quads);
1218  }
1219 
1221  // Step 2. Decode tags from each quad.
1222  if (1) {
1223  image_u8_t *im_samples = td->debug ? image_u8_copy(im_orig) : NULL;
1224 
1225  int chunksize = 1 + zarray_size(quads) / (APRILTAG_TASKS_PER_THREAD_TARGET * td->nthreads);
1226 
1227  struct quad_decode_task tasks[zarray_size(quads) / chunksize + 1];
1228 
1229  int ntasks = 0;
1230  for (int i = 0; i < zarray_size(quads); i+= chunksize) {
1231  tasks[ntasks].i0 = i;
1232  tasks[ntasks].i1 = imin(zarray_size(quads), i + chunksize);
1233  tasks[ntasks].quads = quads;
1234  tasks[ntasks].td = td;
1235  tasks[ntasks].im = im_orig;
1236  tasks[ntasks].detections = detections;
1237 
1238  tasks[ntasks].im_samples = im_samples;
1239 
1240  workerpool_add_task(td->wp, quad_decode_task, &tasks[ntasks]);
1241  ntasks++;
1242  }
1243 
1244  workerpool_run(td->wp);
1245 
1246  if (im_samples != NULL) {
1247  image_u8_write_pnm(im_samples, "debug_samples.pnm");
1248  image_u8_destroy(im_samples);
1249  }
1250  }
1251 
1252  if (td->debug) {
1253  image_u8_t *im_quads = image_u8_copy(im_orig);
1254  image_u8_darken(im_quads);
1255  image_u8_darken(im_quads);
1256 
1257  srandom(0);
1258 
1259  for (int i = 0; i < zarray_size(quads); i++) {
1260  struct quad *quad;
1261  zarray_get_volatile(quads, i, &quad);
1262 
1263  const int bias = 100;
1264  int color = bias + (random() % (255-bias));
1265 
1266  image_u8_draw_line(im_quads, quad->p[0][0], quad->p[0][1], quad->p[1][0], quad->p[1][1], color, 1);
1267  image_u8_draw_line(im_quads, quad->p[1][0], quad->p[1][1], quad->p[2][0], quad->p[2][1], color, 1);
1268  image_u8_draw_line(im_quads, quad->p[2][0], quad->p[2][1], quad->p[3][0], quad->p[3][1], color, 1);
1269  image_u8_draw_line(im_quads, quad->p[3][0], quad->p[3][1], quad->p[0][0], quad->p[0][1], color, 1);
1270 
1271  }
1272 
1273  image_u8_write_pnm(im_quads, "debug_quads_fixed.pnm");
1274  image_u8_destroy(im_quads);
1275  }
1276 
1277  timeprofile_stamp(td->tp, "decode+refinement");
1278 
1280  // Step 3. Reconcile detections--- don't report the same tag more
1281  // than once. (Allow non-overlapping duplicate detections.)
1282  if (1) {
1283  zarray_t *poly0 = g2d_polygon_create_zeros(4);
1284  zarray_t *poly1 = g2d_polygon_create_zeros(4);
1285 
1286  for (int i0 = 0; i0 < zarray_size(detections); i0++) {
1287 
1288  apriltag_detection_t *det0;
1289  zarray_get(detections, i0, &det0);
1290 
1291  for (int k = 0; k < 4; k++)
1292  zarray_set(poly0, k, det0->p[k], NULL);
1293 
1294  for (int i1 = i0+1; i1 < zarray_size(detections); i1++) {
1295 
1296  apriltag_detection_t *det1;
1297  zarray_get(detections, i1, &det1);
1298 
1299  if (det0->id != det1->id || det0->family != det1->family)
1300  continue;
1301 
1302  for (int k = 0; k < 4; k++)
1303  zarray_set(poly1, k, det1->p[k], NULL);
1304 
1305  if (g2d_polygon_overlaps_polygon(poly0, poly1)) {
1306  // the tags overlap. Delete one, keep the other.
1307 
1308  int pref = 0; // 0 means undecided which one we'll keep.
1309  pref = prefer_smaller(pref, det0->hamming, det1->hamming); // want small hamming
1310  pref = prefer_smaller(pref, -det0->decision_margin, -det1->decision_margin); // want bigger margins
1311  pref = prefer_smaller(pref, -det0->goodness, -det1->goodness); // want bigger goodness
1312 
1313  // if we STILL don't prefer one detection over the other, then pick
1314  // any deterministic criterion.
1315  for (int i = 0; i < 4; i++) {
1316  pref = prefer_smaller(pref, det0->p[i][0], det1->p[i][0]);
1317  pref = prefer_smaller(pref, det0->p[i][1], det1->p[i][1]);
1318  }
1319 
1320  if (pref == 0) {
1321  // at this point, we should only be undecided if the tag detections
1322  // are *exactly* the same. How would that happen?
1323  printf("uh oh, no preference for overlappingdetection\n");
1324  }
1325 
1326  if (pref < 0) {
1327  // keep det0, destroy det1
1329  zarray_remove_index(detections, i1, 1);
1330  i1--; // retry the same index
1331  goto retry1;
1332  } else {
1333  // keep det1, destroy det0
1335  zarray_remove_index(detections, i0, 1);
1336  i0--; // retry the same index.
1337  goto retry0;
1338  }
1339  }
1340 
1341  retry1: ;
1342  }
1343 
1344  retry0: ;
1345  }
1346 
1347  zarray_destroy(poly0);
1348  zarray_destroy(poly1);
1349  }
1350 
1351  timeprofile_stamp(td->tp, "reconcile");
1352 
1354  // Produce final debug output
1355  if (td->debug) {
1356 
1357  image_u8_t *darker = image_u8_copy(im_orig);
1358  image_u8_darken(darker);
1359  image_u8_darken(darker);
1360 
1361  // assume letter, which is 612x792 points.
1362  FILE *f = fopen("debug_output.ps", "w");
1363  fprintf(f, "%%!PS\n\n");
1364  double scale = fmin(612.0/darker->width, 792.0/darker->height);
1365  fprintf(f, "%f %f scale\n", scale, scale);
1366  fprintf(f, "0 %d translate\n", darker->height);
1367  fprintf(f, "1 -1 scale\n");
1368  postscript_image(f, darker);
1369 
1370  image_u8_destroy(darker);
1371 
1372  for (int i = 0; i < zarray_size(detections); i++) {
1373  apriltag_detection_t *det;
1374  zarray_get(detections, i, &det);
1375 
1376  float rgb[3];
1377  int bias = 100;
1378 
1379  for (int i = 0; i < 3; i++)
1380  rgb[i] = bias + (random() % (255-bias));
1381 
1382  fprintf(f, "%f %f %f setrgbcolor\n", rgb[0]/255.0f, rgb[1]/255.0f, rgb[2]/255.0f);
1383  fprintf(f, "%f %f moveto %f %f lineto %f %f lineto %f %f lineto %f %f lineto stroke\n",
1384  det->p[0][0], det->p[0][1],
1385  det->p[1][0], det->p[1][1],
1386  det->p[2][0], det->p[2][1],
1387  det->p[3][0], det->p[3][1],
1388  det->p[0][0], det->p[0][1]);
1389  }
1390 
1391  fprintf(f, "showpage\n");
1392  fclose(f);
1393  }
1394 
1395  if (td->debug) {
1396  image_u8_t *darker = image_u8_copy(im_orig);
1397  image_u8_darken(darker);
1398  image_u8_darken(darker);
1399 
1400  image_u8x3_t *out = image_u8x3_create(darker->width, darker->height);
1401  for (int y = 0; y < im_orig->height; y++) {
1402  for (int x = 0; x < im_orig->width; x++) {
1403  out->buf[y*out->stride + 3*x + 0] = darker->buf[y*darker->stride + x];
1404  out->buf[y*out->stride + 3*x + 1] = darker->buf[y*darker->stride + x];
1405  out->buf[y*out->stride + 3*x + 2] = darker->buf[y*darker->stride + x];
1406  }
1407  }
1408 
1409  for (int i = 0; i < zarray_size(detections); i++) {
1410  apriltag_detection_t *det;
1411  zarray_get(detections, i, &det);
1412 
1413  float rgb[3];
1414  int bias = 100;
1415 
1416  for (int i = 0; i < 3; i++)
1417  rgb[i] = bias + (random() % (255-bias));
1418 
1419  for (int j = 0; j < 4; j++) {
1420  int k = (j + 1) & 3;
1422  det->p[j][0], det->p[j][1], det->p[k][0], det->p[k][1],
1423  (uint8_t[]) { rgb[0], rgb[1], rgb[2] },
1424  1);
1425  }
1426  }
1427 
1428  image_u8x3_write_pnm(out, "debug_output.pnm");
1429  image_u8x3_destroy(out);
1430  }
1431 
1432  // deallocate
1433  if (td->debug) {
1434  FILE *f = fopen("debug_quads.ps", "w");
1435  fprintf(f, "%%!PS\n\n");
1436 
1437  image_u8_t *darker = image_u8_copy(im_orig);
1438  image_u8_darken(darker);
1439  image_u8_darken(darker);
1440 
1441  // assume letter, which is 612x792 points.
1442  double scale = fmin(612.0/darker->width, 792.0/darker->height);
1443  fprintf(f, "%f %f scale\n", scale, scale);
1444  fprintf(f, "0 %d translate\n", darker->height);
1445  fprintf(f, "1 -1 scale\n");
1446 
1447  postscript_image(f, darker);
1448 
1449  image_u8_destroy(darker);
1450 
1451  for (int i = 0; i < zarray_size(quads); i++) {
1452  struct quad *q;
1453  zarray_get_volatile(quads, i, &q);
1454 
1455  float rgb[3];
1456  int bias = 100;
1457 
1458  for (int i = 0; i < 3; i++)
1459  rgb[i] = bias + (random() % (255-bias));
1460 
1461  fprintf(f, "%f %f %f setrgbcolor\n", rgb[0]/255.0f, rgb[1]/255.0f, rgb[2]/255.0f);
1462  fprintf(f, "%f %f moveto %f %f lineto %f %f lineto %f %f lineto %f %f lineto stroke\n",
1463  q->p[0][0], q->p[0][1],
1464  q->p[1][0], q->p[1][1],
1465  q->p[2][0], q->p[2][1],
1466  q->p[3][0], q->p[3][1],
1467  q->p[0][0], q->p[0][1]);
1468  }
1469 
1470  fprintf(f, "showpage\n");
1471  fclose(f);
1472  }
1473 
1474  timeprofile_stamp(td->tp, "debug output");
1475 
1476  for (int i = 0; i < zarray_size(quads); i++) {
1477  struct quad *quad;
1478  zarray_get_volatile(quads, i, &quad);
1479  matd_destroy(quad->H);
1480  matd_destroy(quad->Hinv);
1481  }
1482 
1483  zarray_destroy(quads);
1484 
1486  timeprofile_stamp(td->tp, "cleanup");
1487 
1488  return detections;
1489 }
1490 
1491 
1492 // Call this method on each of the tags returned by apriltag_detector_detect
1494 {
1495  for (int i = 0; i < zarray_size(detections); i++) {
1496  apriltag_detection_t *det;
1497  zarray_get(detections, i, &det);
1498 
1500  }
1501 
1502  zarray_destroy(detections);
1503 }
1504 
1506 {
1507  assert(fam != NULL);
1508  assert(idx >= 0 && idx < fam->ncodes);
1509 
1510  uint64_t code = fam->codes[idx];
1511  int border = fam->black_border + 1;
1512  int dim = fam->d + 2*border;
1513  image_u8_t *im = image_u8_create(dim, dim);
1514 
1515  // Make 1px white border
1516  for (int i = 0; i < dim; i += 1) {
1517  im->buf[i] = 255;
1518  im->buf[(dim-1)*im->stride + i] = 255;
1519  im->buf[i*im->stride] = 255;
1520  im->buf[i*im->stride + (dim-1)] = 255;
1521  }
1522 
1523  for (int y = 0; y < fam->d; y += 1) {
1524  for (int x = 0; x < fam->d; x += 1) {
1525  int pos = (fam->d-1 - y) * fam->d + (fam->d-1 - x);
1526  if ((code >> pos) & 0x1) {
1527  int i = (y+border)*im->stride + x+border;
1528  im->buf[i] = 255;
1529  }
1530  }
1531  }
1532 
1533  return im;
1534 }
matd_t * H
Definition: apriltag.h:57
void graymodel_add(struct graymodel *gm, double x, double y, double gray)
Definition: apriltag.c:85
void image_u8_gaussian_blur(image_u8_t *im, double sigma, int k)
Definition: image_u8.c:348
image_u8_t * image_u8_decimate(image_u8_t *im, float factor)
Definition: image_u8.c:523
#define APRILTAG_TASKS_PER_THREAD_TARGET
Definition: apriltag.h:49
static void zarray_get_volatile(const zarray_t *za, int idx, void *p)
Definition: zarray.h:218
zarray_t * quads
Definition: apriltag.c:396
static void zarray_sort(zarray_t *za, int(*compar)(const void *, const void *))
Definition: zarray.h:432
static int zarray_remove_value(zarray_t *za, const void *p, int shuffle)
Definition: zarray.h:299
void matd_destroy(matd_t *m)
Definition: matd.c:226
static void timeprofile_stamp(timeprofile_t *tp, const char *name)
Definition: timeprofile.h:83
int quad_update_homographies(struct quad *quad)
Definition: apriltag.c:416
uint32_t ncodes
Definition: apriltag.h:68
apriltag_detector_t * td
Definition: apriltag.c:397
void * impl
Definition: apriltag.h:88
int workerpool_get_nthreads(workerpool_t *wp)
Definition: workerpool.c:157
matd_t * matd_inverse(const matd_t *a)
Definition: matd.c:485
image_u8_t * im_samples
Definition: apriltag.c:402
matd_t * matd_op(const char *expr,...)
Definition: matd.c:798
void quick_decode_add(struct quick_decode *qd, uint64_t code, int id, int hamming)
Definition: apriltag.c:172
double score_goodness(apriltag_family_t *family, image_u8_t *im, struct quad *quad, void *user)
Definition: apriltag.c:725
int nentries
Definition: apriltag.c:121
static void quad_decode_task(void *_u)
Definition: apriltag.c:958
double p[4][2]
Definition: apriltag.h:245
static void mat33_sym_solve(const double *A, const double *B, double *R)
Definition: apriltag_math.h:89
pthread_mutex_t mutex
Definition: apriltag.h:200
zarray_t * tag_families
Definition: apriltag.h:194
static int zarray_size(const zarray_t *za)
Definition: zarray.h:136
static void homography_project(const matd_t *H, double x, double y, double *ox, double *oy)
Definition: homography.h:140
matd_t * Hinv
Definition: apriltag.h:57
int prefer_smaller(int pref, double q0, double q1)
Definition: apriltag.c:1080
static void zarray_destroy(zarray_t *za)
Definition: zarray.h:76
static void zarray_set(zarray_t *za, int idx, const void *p, void *outp)
Definition: zarray.h:345
uint32_t black_border
Definition: apriltag.h:74
uint32_t d
Definition: apriltag.h:77
apriltag_detector_t * apriltag_detector_create()
Definition: apriltag.c:348
int image_u8_write_pnm(const image_u8_t *im, const char *path)
Definition: image_u8.c:205
image_u8_t * image_u8_create(unsigned int width, unsigned int height)
Definition: image_u8.c:59
static void zarray_remove_index(zarray_t *za, int idx, int shuffle)
Definition: zarray.h:260
static int imax(int a, int b)
Definition: math_util.h:165
static int detection_compare_function(const void *_a, const void *_b)
Definition: apriltag.c:316
#define MATD_EL(m, row, col)
Definition: matd.h:71
void apriltag_detections_destroy(zarray_t *detections)
Definition: apriltag.c:1493
timeprofile_t * tp
Definition: apriltag.h:182
void quad_destroy(struct quad *quad)
Definition: apriltag.c:151
matd_t * matd_create(int rows, int cols)
Definition: matd.c:50
const int32_t height
Definition: image_types.h:14
Definition: apriltag.c:111
uint64_t * codes
Definition: apriltag.h:71
uint8_t rotation
Definition: apriltag.c:116
static zarray_t * zarray_create(size_t el_sz)
Definition: zarray.h:63
const int32_t width
Definition: image_types.h:13
float p[4][2]
Definition: apriltag.h:53
matd_t * Hinv
Definition: apriltag.c:409
uint8_t * buf
Definition: image_types.h:27
uint64_t rcode
Definition: apriltag.c:113
uint8_t hamming
Definition: apriltag.c:115
const int32_t stride
Definition: image_types.h:15
zarray_t * detections
Definition: apriltag.c:400
struct apriltag_quad_thresh_params qtp
Definition: apriltag.h:178
void graymodel_init(struct graymodel *gm)
Definition: apriltag.c:80
void workerpool_add_task(workerpool_t *wp, void(*f)(void *p), void *p)
Definition: workerpool.c:162
double B[3]
Definition: apriltag.c:76
image_u8_t * image_u8_copy(const image_u8_t *in)
Definition: image_u8.c:74
void graymodel_solve(struct graymodel *gm)
Definition: apriltag.c:101
void apriltag_detector_remove_family(apriltag_detector_t *td, apriltag_family_t *fam)
Definition: apriltag.c:324
matd_t * matd_copy(const matd_t *m)
Definition: matd.c:158
void apriltag_detection_destroy(apriltag_detection_t *det)
Definition: apriltag.c:1071
void quick_decode_uninit(apriltag_family_t *fam)
Definition: apriltag.c:185
#define M_PI
Definition: apriltag.c:59
static timeprofile_t * timeprofile_create()
Definition: timeprofile.h:61
const int32_t stride
Definition: image_types.h:25
static int imin(int a, int b)
Definition: math_util.h:160
static uint64_t rotate90(uint64_t w, uint32_t d)
Definition: apriltag.c:133
zarray_t * apriltag_quad_thresh(apriltag_detector_t *td, image_u8_t *im)
uint8_t * buf
Definition: image_types.h:17
double graymodel_interpolate(struct graymodel *gm, double x, double y)
Definition: apriltag.c:106
float quad_decode(apriltag_family_t *family, image_u8_t *im, struct quad *quad, struct quick_decode_entry *entry, image_u8_t *im_samples)
Definition: apriltag.c:567
uint32_t nquads
Definition: apriltag.h:186
Definition: matd.h:51
image_u8x3_t * image_u8x3_create(unsigned int width, unsigned int height)
Definition: image_u8x3.c:37
static void zarray_get(const zarray_t *za, int idx, void *p)
Definition: zarray.h:201
void workerpool_run(workerpool_t *wp)
Definition: workerpool.c:183
Definition: zarray.h:49
void workerpool_destroy(workerpool_t *wp)
Definition: workerpool.c:130
image_u8_t * im
Definition: apriltag.c:399
double C[3]
Definition: apriltag.c:77
void image_u8x3_destroy(image_u8x3_t *im)
Definition: image_u8x3.c:72
workerpool_t * wp
Definition: apriltag.h:197
#define HOMOGRAPHY_COMPUTE_FLAG_SVD
Definition: homography.h:135
struct quad * quad_copy(struct quad *quad)
Definition: apriltag.c:161
Definition: apriltag.h:51
uint16_t id
Definition: apriltag.c:114
void image_u8_destroy(image_u8_t *im)
Definition: image_u8.c:87
double quad_goodness(apriltag_family_t *family, image_u8_t *im, struct quad *quad)
Definition: apriltag.c:456
zarray_t * g2d_polygon_create_zeros(int sz)
Definition: g2d.c:66
static void refine_edges(apriltag_detector_t *td, image_u8_t *im_orig, struct quad *quad)
Definition: apriltag.c:816
workerpool_t * workerpool_create(int nthreads)
Definition: workerpool.c:103
float quad_decimate
Definition: apriltag.h:139
void quick_decode_init(apriltag_family_t *family, int maxhamming)
Definition: apriltag.c:196
int image_u8x3_write_pnm(const image_u8x3_t *im, const char *path)
Definition: image_u8x3.c:132
void apriltag_detector_destroy(apriltag_detector_t *td)
Definition: apriltag.c:382
static void postscript_image(FILE *f, image_u8_t *im)
static void zarray_clear(zarray_t *za)
Definition: zarray.h:391
image_u8_t * apriltag_to_image(apriltag_family_t *fam, int idx)
Definition: apriltag.c:1505
struct quick_decode_entry * entries
Definition: apriltag.c:122
zarray_t * apriltag_quad_gradient(apriltag_detector_t *td, image_u8_t *im)
void image_u8_darken(image_u8_t *im)
Definition: image_u8.c:293
float decision_margin
Definition: apriltag.h:232
void apriltag_detector_add_family_bits(apriltag_detector_t *td, apriltag_family_t *fam, int bits_corrected)
Definition: apriltag.c:330
static void timeprofile_clear(timeprofile_t *tp)
Definition: timeprofile.h:77
double optimize_quad_generic(apriltag_family_t *family, image_u8_t *im, struct quad *quad0, float *stepsizes, int nstepsizes, double(*score)(apriltag_family_t *family, image_u8_t *im, struct quad *quad, void *user), void *user)
Definition: apriltag.c:741
void apriltag_detector_clear_families(apriltag_detector_t *td)
Definition: apriltag.c:338
matd_t * homography_compute(zarray_t *correspondences, int flags)
Definition: homography.c:43
double A[3][3]
Definition: apriltag.c:75
void image_u8_draw_line(image_u8_t *im, float x0, float y0, float x1, float y1, int v, int width)
Definition: image_u8.c:270
static void timeprofile_destroy(timeprofile_t *tp)
Definition: timeprofile.h:71
static void quick_decode_codeword(apriltag_family_t *tf, uint64_t rcode, struct quick_decode_entry *entry)
Definition: apriltag.c:289
double score_decodability(apriltag_family_t *family, image_u8_t *im, struct quad *quad, void *user)
Definition: apriltag.c:730
static void zarray_add(zarray_t *za, const void *p)
Definition: zarray.h:185
void image_u8x3_draw_line(image_u8x3_t *im, float x0, float y0, float x1, float y1, uint8_t rgb[3], int width)
Definition: image_u8x3.c:160
zarray_t * apriltag_detector_detect(apriltag_detector_t *td, image_u8_t *im_orig)
Definition: apriltag.c:1094
apriltag_family_t * family
Definition: apriltag.h:209
#define W1
Definition: pjpeg-idct.c:273
int g2d_polygon_overlaps_polygon(const zarray_t *polya, const zarray_t *polyb)
Definition: g2d.c:614


apriltags2
Author(s): Danylo Malyuta
autogenerated on Fri Oct 19 2018 04:02:32