35 #define _USE_MATH_DEFINES
58 static inline void srandom(
unsigned int seed)
63 static inline long int random(
void)
69 #define APRILTAG_U64_ONE ((uint64_t) 1)
104 gm->
B[0] += x * gray;
105 gm->
B[1] += y * gray;
116 return gm->
C[0]*x + gm->
C[1]*y + gm->
C[2];
141 if (numBits % 4 == 1) {
145 w = ((w >> l) << (p/4 + l)) | (w >> (3 * p/ 4 + l) << l) | (w & l);
162 struct quad *q = calloc(1,
sizeof(
struct quad));
163 memcpy(q,
quad,
sizeof(
struct quad));
173 uint32_t bucket = code % qd->
nentries;
176 bucket = (bucket + 1) % qd->
nentries;
197 assert(family->
impl == NULL);
198 assert(family->
ncodes < 65536);
201 int capacity = family->
ncodes;
203 int nbits = family->
nbits;
206 capacity += family->
ncodes * nbits;
209 capacity += family->
ncodes * nbits * (nbits-1);
212 capacity += family->
ncodes * nbits * (nbits-1) * (nbits-2);
221 debug_print(
"Failed to allocate hamming decode table\n");
226 for (
int i = 0; i < qd->
nentries; i++)
231 for (uint32_t i = 0; i < family->
ncodes; i++) {
232 uint64_t code = family->
codes[i];
237 if (maxhamming >= 1) {
239 for (
int j = 0; j < nbits; j++)
243 if (maxhamming >= 2) {
245 for (
int j = 0; j < nbits; j++)
246 for (
int k = 0; k < j; k++)
250 if (maxhamming >= 3) {
252 for (
int j = 0; j < nbits; j++)
253 for (
int k = 0; k < j; k++)
254 for (
int m = 0; m < k; m++)
258 if (maxhamming > 3) {
259 debug_print(
"\"maxhamming\" beyond 3 not supported\n");
276 for (
int i = 0; i < qd->
nentries; i++) {
285 longest_run =
imax(longest_run, run);
289 printf(
"quick decode: longest run: %d, average run %.3f\n", longest_run, 1.0 * run_sum / run_count);
300 for (
int ridx = 0; qd != NULL && ridx < 4; ridx++) {
302 for (
int bucket = rcode % qd->
nentries;
304 bucket = (bucket + 1) % qd->
nentries) {
327 return a->
id - b->
id;
372 pthread_mutex_init(&td->
mutex, NULL);
423 c[0][0], c[0][1], 1, 0, 0, 0, -c[0][0]*c[0][2], -c[0][1]*c[0][2], c[0][2],
424 0, 0, 0, c[0][0], c[0][1], 1, -c[0][0]*c[0][3], -c[0][1]*c[0][3], c[0][3],
425 c[1][0], c[1][1], 1, 0, 0, 0, -c[1][0]*c[1][2], -c[1][1]*c[1][2], c[1][2],
426 0, 0, 0, c[1][0], c[1][1], 1, -c[1][0]*c[1][3], -c[1][1]*c[1][3], c[1][3],
427 c[2][0], c[2][1], 1, 0, 0, 0, -c[2][0]*c[2][2], -c[2][1]*c[2][2], c[2][2],
428 0, 0, 0, c[2][0], c[2][1], 1, -c[2][0]*c[2][3], -c[2][1]*c[2][3], c[2][3],
429 c[3][0], c[3][1], 1, 0, 0, 0, -c[3][0]*c[3][2], -c[3][1]*c[3][2], c[3][2],
430 0, 0, 0, c[3][0], c[3][1], 1, -c[3][0]*c[3][3], -c[3][1]*c[3][3], c[3][3],
433 double epsilon = 1e-10;
436 for (
int col = 0; col < 8; col++) {
439 int max_val_idx = -1;
440 for (
int row = col; row < 8; row++) {
441 double val = fabs(A[row*9 + col]);
448 if (max_val_idx < 0) {
452 if (max_val < epsilon) {
458 if (max_val_idx != col) {
459 for (
int i = col; i < 9; i++) {
460 double tmp = A[col*9 + i];
461 A[col*9 + i] = A[max_val_idx*9 + i];
462 A[max_val_idx*9 + i] = tmp;
467 for (
int i = col + 1; i < 8; i++) {
468 double f = A[i*9 + col]/A[col*9 + col];
470 for (
int j = col + 1; j < 9; j++) {
471 A[i*9 + j] -= f*A[col*9 + j];
477 for (
int col = 7; col >=0; col--) {
479 for (
int i = col + 1; i < 8; i++) {
480 sum += A[col*9 + i]*A[i*9 + 8];
482 A[col*9 + 8] = (A[col*9 + 8] - sum)/A[col*9 + col];
484 return matd_create_data(3, 3, (
double[]) { A[8], A[17], A[26], A[35], A[44], A[53], A[62], A[71], 1 });
492 double corr_arr[4][4];
494 for (
int i = 0; i < 4; i++) {
495 corr_arr[i][0] = (i==0 || i==3) ? -1 : 1;
496 corr_arr[i][1] = (i==0 || i==1) ? -1 : 1;
497 corr_arr[i][2] =
quad->
p[i][0];
498 corr_arr[i][3] =
quad->
p[i][1];
508 if (
quad->
H != NULL) {
521 int x1 = floor(px - 0.5);
522 int x2 = ceil(px - 0.5);
523 double x = px - 0.5 - x1;
524 int y1 = floor(py - 0.5);
525 int y2 = ceil(py - 0.5);
526 double y = py - 0.5 - y1;
527 if (x1 < 0 || x2 >= im->
width || y1 < 0 || y2 >= im->
height) {
530 return im->
buf[y1*im->
stride + x1]*(1-x)*(1-y) +
537 double *sharpened = malloc(
sizeof(
double)*size*size);
544 for (
int y = 0; y < size; y++) {
545 for (
int x = 0; x < size; x++) {
546 sharpened[y*size + x] = 0;
547 for (
int i = 0; i < 3; i++) {
548 for (
int j = 0; j < 3; j++) {
549 if ((y + i - 1) < 0 || (y + i - 1) > size - 1 || (x + j - 1) < 0 || (x + j - 1) > size - 1) {
552 sharpened[y*size + x] += values[(y + i - 1)*size + (x + j - 1)]*kernel[i*3 + j];
559 for (
int y = 0; y < size; y++) {
560 for (
int x = 0; x < size; x++) {
561 values[y*size + x] = values[y*size + x] + td->
decode_sharpening*sharpened[y*size + x];
628 for (
long unsigned int pattern_idx = 0; pattern_idx <
sizeof(patterns)/(5*
sizeof(
float)); pattern_idx ++) {
629 float *pattern = &patterns[pattern_idx * 5];
631 int is_white = pattern[4];
634 double tagx01 = (pattern[0] + i*pattern[2]) / (family->
width_at_border);
635 double tagy01 = (pattern[1] + i*pattern[3]) / (family->
width_at_border);
637 double tagx = 2*(tagx01-0.5);
638 double tagy = 2*(tagy01-0.5);
646 if (ix < 0 || iy < 0 || ix >= im->
width || iy >= im->
height)
652 im_samples->
buf[iy*im_samples->
stride + ix] = (1-is_white)*255;
669 blackmodel.
C[2] = blackmodel.
B[2]/4;
683 float black_score = 0, white_score = 0;
684 float black_score_count = 1, white_score_count = 1;
689 for (uint32_t i = 0; i < family->
nbits; i++) {
690 int bity = family->
bit_y[i];
691 int bitx = family->
bit_x[i];
697 double tagx = 2*(tagx01-0.5);
698 double tagy = 2*(tagy01-0.5);
710 values[family->
total_width*(bity - min_coord) + bitx - min_coord] = v - thresh;
715 im_samples->
buf[iy*im_samples->
stride + ix] = (v < thresh) * 255;
722 for (uint32_t i = 0; i < family->
nbits; i++) {
723 int bity = family->
bit_y[i];
724 int bitx = family->
bit_x[i];
725 rcode = (rcode << 1);
726 double v = values[(bity - min_coord)*family->
total_width + bitx - min_coord];
740 return fmin(white_score / white_score_count, black_score / black_score_count);
747 for (
int edge = 0; edge < 4; edge++) {
748 int a = edge, b = (edge + 1) & 3;
753 double mag = sqrt(nx*nx + ny*ny);
765 int nsamples =
imax(16, mag / 8);
768 double Mx = 0, My = 0, Mxx = 0, Mxy = 0, Myy = 0, N = 0;
770 for (
int s = 0; s < nsamples; s++) {
774 double alpha = (1.0 + s) / (nsamples + 1);
775 double x0 = alpha*
quad->
p[a][0] + (1-alpha)*
quad->
p[b][0];
776 double y0 = alpha*
quad->
p[a][1] + (1-alpha)*
quad->
p[b][1];
797 int steps_per_unit = 4;
798 double step_length = 1.0 / steps_per_unit;
799 int max_steps = 2 * steps_per_unit * range + 1;
803 for (
int step = 0; step < max_steps; ++step) {
804 double n = -range + step_length * step;
815 double x1 = x0 + (n + grange)*nx - delta;
816 double y1 = y0 + (n + grange)*ny - delta;
817 double x1i_d, y1i_d, a1, b1;
818 a1 = modf(x1, &x1i_d);
819 b1 = modf(y1, &y1i_d);
820 int x1i = x1i_d, y1i = y1i_d;
822 if (x1i < 0 || x1i + 1 >= im_orig->
width || y1i < 0 || y1i + 1 >= im_orig->
height)
825 double x2 = x0 + (n - grange)*nx - delta;
826 double y2 = y0 + (n - grange)*ny - delta;
827 double x2i_d, y2i_d, a2, b2;
828 a2 = modf(x2, &x2i_d);
829 b2 = modf(y2, &y2i_d);
830 int x2i = x2i_d, y2i = y2i_d;
832 if (x2i < 0 || x2i + 1 >= im_orig->
width || y2i < 0 || y2i + 1 >= im_orig->
height)
836 double g1 = (1 - a1) * (1 - b1) * im_orig->
buf[y1i*im_orig->
stride + x1i] +
837 a1 * (1 - b1) * im_orig->
buf[y1i*im_orig->
stride + x1i + 1] +
838 (1 - a1) * b1 * im_orig->
buf[(y1i + 1)*im_orig->
stride + x1i] +
839 a1 * b1 * im_orig->
buf[(y1i + 1)*im_orig->
stride + x1i + 1];
840 double g2 = (1 - a2) * (1 - b2) * im_orig->
buf[y2i*im_orig->
stride + x2i] +
841 a2 * (1 - b2) * im_orig->
buf[y2i*im_orig->
stride + x2i + 1] +
842 (1 - a2) * b2 * im_orig->
buf[(y2i + 1)*im_orig->
stride + x2i] +
843 a2 * b2 * im_orig->
buf[(y2i + 1)*im_orig->
stride + x2i + 1];
847 double weight = (g2 - g1)*(g2 - g1);
858 double n0 = Mn / Mcount;
861 double bestx = x0 + n0*nx;
862 double besty = y0 + n0*ny;
874 double Ex = Mx / N, Ey = My / N;
875 double Cxx = Mxx / N - Ex*Ex;
876 double Cxy = Mxy / N - Ex*Ey;
877 double Cyy = Myy / N - Ey*Ey;
880 double normal_theta = .5 * atan2f(-2*Cxy, (Cyy - Cxx));
881 nx = cosf(normal_theta);
882 ny = sinf(normal_theta);
890 for (
int i = 0; i < 4; i++) {
893 double A00 = lines[i][3], A01 = -lines[(i+1)&3][3];
894 double A10 = -lines[i][2], A11 = lines[(i+1)&3][2];
895 double B0 = -lines[i][0] + lines[(i+1)&3][0];
896 double B1 = -lines[i][1] + lines[(i+1)&3][1];
898 double det = A00 * A11 - A10 * A01;
901 if (fabs(det) > 0.001) {
903 double W00 = A11 / det, W01 = -A01 / det;
905 double L0 = W00*B0 + W01*B1;
909 quad->
p[(i+1)&3][0] = lines[i][0] + L0*A00;
910 quad->
p[(i+1)&3][1] = lines[i][1] + L0*A10;
924 for (
int quadidx =
task->i0; quadidx < task->
i1; quadidx++) {
925 struct quad *quad_original;
955 if (decision_margin >= 0 && entry.
hamming < 255) {
963 double theta = entry.
rotation * M_PI / 2.0;
964 double c = cos(theta), s = sin(theta);
984 for (
int i = 0; i < 4; i++) {
985 int tcx = (i == 1 || i == 2) ? 1 : -1;
986 int tcy = (i < 2) ? 1 : -1;
996 pthread_mutex_lock(&td->
mutex);
998 pthread_mutex_unlock(&td->
mutex);
1040 if (td->
wp == NULL) {
1071 int ksz = 4 * sigma;
1085 for (
int y = 0; y < orig->
height; y++) {
1086 for (
int x = 0; x < orig->
width; x++) {
1087 int vorig = orig->
buf[y*orig->
stride + x];
1088 int vblur = quad_im->
buf[y*quad_im->
stride + x];
1090 int v = 2*vorig - vblur;
1096 quad_im->
buf[y*quad_im->
stride + x] = (uint8_t) v;
1118 for (
int j = 0; j < 4; j++) {
1125 if (quad_im != im_orig)
1145 const int bias = 100;
1146 int color = bias + (random() % (255-bias));
1169 tasks[ntasks].
i0 = i;
1172 tasks[ntasks].
td =
td;
1173 tasks[ntasks].
im = im_orig;
1203 const int bias = 100;
1204 int color = bias + (random() % (255-bias));
1226 for (
int i0 = 0; i0 <
zarray_size(detections); i0++) {
1231 for (
int k = 0; k < 4; k++)
1234 for (
int i1 = i0+1; i1 <
zarray_size(detections); i1++) {
1242 for (
int k = 0; k < 4; k++)
1254 for (
int i = 0; i < 4; i++) {
1262 debug_print(
"uh oh, no preference for overlappingdetection\n");
1301 FILE *f = fopen(
"debug_output.ps",
"w");
1302 fprintf(f,
"%%!PS\n\n");
1303 double scale = fmin(612.0/darker->
width, 792.0/darker->
height);
1304 fprintf(f,
"%f %f scale\n", scale, scale);
1305 fprintf(f,
"0 %d translate\n", darker->
height);
1306 fprintf(f,
"1 -1 scale\n");
1311 for (
int i = 0; i <
zarray_size(detections); i++) {
1318 for (
int j = 0; j < 3; j++) {
1319 rgb[j] = bias + (random() % (255-bias));
1322 fprintf(f,
"%f %f %f setrgbcolor\n", rgb[0]/255.0f, rgb[1]/255.0f, rgb[2]/255.0f);
1323 fprintf(f,
"%f %f moveto %f %f lineto %f %f lineto %f %f lineto %f %f lineto stroke\n",
1324 det->
p[0][0], det->
p[0][1],
1325 det->
p[1][0], det->
p[1][1],
1326 det->
p[2][0], det->
p[2][1],
1327 det->
p[3][0], det->
p[3][1],
1328 det->
p[0][0], det->
p[0][1]);
1331 fprintf(f,
"showpage\n");
1341 for (
int y = 0; y < im_orig->
height; y++) {
1342 for (
int x = 0; x < im_orig->
width; x++) {
1351 for (
int i = 0; i <
zarray_size(detections); i++) {
1358 for (
int j = 0; j < 3; j++) {
1359 rgb[j] = bias + (random() % (255-bias));
1362 for (
int j = 0; j < 4; j++) {
1363 int k = (j + 1) & 3;
1365 det->
p[j][0], det->
p[j][1], det->
p[k][0], det->
p[k][1],
1366 (uint8_t[]) { rgb[0], rgb[1], rgb[2] });
1376 FILE *f = fopen(
"debug_quads.ps",
"w");
1377 fprintf(f,
"%%!PS\n\n");
1384 double scale = fmin(612.0/darker->
width, 792.0/darker->
height);
1385 fprintf(f,
"%f %f scale\n", scale, scale);
1386 fprintf(f,
"0 %d translate\n", darker->
height);
1387 fprintf(f,
"1 -1 scale\n");
1400 for (
int j = 0; j < 3; j++) {
1401 rgb[j] = bias + (random() % (255-bias));
1404 fprintf(f,
"%f %f %f setrgbcolor\n", rgb[0]/255.0f, rgb[1]/255.0f, rgb[2]/255.0f);
1405 fprintf(f,
"%f %f moveto %f %f lineto %f %f lineto %f %f lineto %f %f lineto stroke\n",
1406 q->
p[0][0], q->
p[0][1],
1407 q->
p[1][0], q->
p[1][1],
1408 q->
p[2][0], q->
p[2][1],
1409 q->
p[3][0], q->
p[3][1],
1410 q->
p[0][0], q->
p[0][1]);
1413 fprintf(f,
"showpage\n");
1438 for (
int i = 0; i <
zarray_size(detections); i++) {
1450 assert(fam != NULL);
1451 assert(idx < fam->ncodes);
1453 uint64_t code = fam->
codes[idx];
1458 int white_border_start = (fam->
total_width - white_border_width)/2;
1460 for (
int i = 0; i < white_border_width - 1; i += 1) {
1461 im->
buf[white_border_start*im->
stride + white_border_start + i] = 255;
1462 im->
buf[(white_border_start + i)*im->
stride + fam->
total_width - 1 - white_border_start] = 255;
1463 im->
buf[(fam->
total_width - 1 - white_border_start)*im->
stride + white_border_start + i + 1] = 255;
1464 im->
buf[(white_border_start + 1 + i)*im->
stride + white_border_start] = 255;
1468 for (uint32_t i = 0; i < fam->
nbits; i++) {