00001
00002
00003 #include <assert.h>
00004 #include <sys/time.h>
00005 #include <angles/angles.h>
00006
00007 #include <opencv2/highgui/highgui_c.h>
00008
00009 #include "Camera_Tag.hpp"
00010 #include "CRC.hpp"
00011 #include "CV.hpp"
00012 #include "File.hpp"
00013 #include "FEC.hpp"
00014 #include "Fiducials.hpp"
00015 #include "Map.hpp"
00016 #include "String.hpp"
00017 #include "Tag.hpp"
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00410
00411
00412
00413
00414 void Fiducials__arc_announce(void *announce_object,
00415 int from_id, double from_x, double from_y, double from_z,
00416 int to_id, double to_x, double to_y, double to_z,
00417 double goodness, bool in_spanning_tree) {
00418 File__format(stderr,
00419 "Arc: from=(%d, %f, %f, %f,) to=(%d, %f, %f, %f) %f %d\n",
00420 from_id, from_x, from_y, from_z,
00421 to_id, to_x, to_y, to_z,
00422 goodness, in_spanning_tree);
00423 }
00424
00436
00437
00438
00439 void Fiducials__location_announce(void *announce_object, int id,
00440 double x, double y, double z, double bearing) {
00441 File__format(stderr,
00442 "Location: id=%d x=%f y=%f bearing=%f\n", id, x, y, bearing);
00443 }
00444
00463
00464 void Fiducials__fiducial_announce(void *announce_object,
00465 int id, int direction, double world_diagonal,
00466 double x1, double y1, double x2, double y2,
00467 double x3, double y3, double x4, double y4) {
00468 File__format(stderr,
00469 "Fiducial: id=%d dir=%d diag=%.2f (%.2f,%.2f), "
00470 "(%.2f,%.2f), (%.2f,%.2f), (%.2f,%.2f)",
00471 id, direction, world_diagonal, x1, y1, x2, y2, x3, y3, x4, y4);
00472 }
00473
00480
00481 void Fiducials__image_set(Fiducials fiducials, CV_Image image)
00482 {
00483 fiducials->original_image = image;
00484 }
00485
00502
00503
00504
00505 void Fiducials__image_show(Fiducials fiducials, bool show) {
00506
00507 CV_Image debug_image = fiducials->debug_image;
00508 CV_Image gray_image = fiducials->gray_image;
00509 CV_Image original_image = fiducials->original_image;
00510
00511
00512 String_Const window_name = "Example1";
00513 if (show) {
00514 cvNamedWindow(window_name, CV__window_auto_size);
00515 }
00516
00517
00518
00519 unsigned int debug_index = 0;
00520 unsigned int previous_debug_index = debug_index;
00521 bool done = (bool)0;
00522 while (!done) {
00523
00524 Fiducials__process(fiducials);
00525
00526
00527 if (show) {
00528 cvShowImage(window_name, debug_image);
00529 }
00530
00531
00532 char control_character = '\0';
00533 if (show) {
00534 control_character = (char)(cvWaitKey(0) & 0xff);
00535 }
00536
00537
00538 switch (control_character) {
00539 case '\33':
00540
00541 done = (bool)1;
00542 File__format(stderr, "done\n");
00543 break;
00544 case '+':
00545
00546 debug_index += 1;
00547 break;
00548 case '-':
00549
00550 if (debug_index > 0) {
00551 debug_index -= 1;
00552 }
00553 break;
00554 case '<':
00555
00556 debug_index = 0;
00557 break;
00558 case '>':
00559
00560 debug_index = 100;
00561 break;
00562 case 'b':
00563
00564 fiducials->blur = !fiducials->blur;
00565 File__format(stderr, "blur = %d\n", fiducials->blur);
00566 break;
00567 case 'f':
00568
00569 fiducials->y_flip = !fiducials->y_flip;
00570 File__format(stderr, "y_flip = %d\n", fiducials->y_flip);
00571 break;
00572 default:
00573
00574 if ((unsigned int)control_character <= 127) {
00575 File__format(stderr,
00576 "Unknown control character %d\n", control_character);
00577 }
00578 break;
00579 }
00580
00581
00582 fiducials->debug_index = debug_index;
00583
00584
00585 if (debug_index != previous_debug_index) {
00586 File__format(stderr,
00587 "****************************debug_index = %d\n", debug_index);
00588 previous_debug_index = debug_index;
00589 }
00590 }
00591
00592
00593 CV__release_image(original_image);
00594 if (show) {
00595 cvDestroyWindow(window_name);
00596 }
00597 }
00598
00606
00607
00608
00609
00610
00611 Fiducials Fiducials__create(
00612 CV_Image original_image, Fiducials_Create fiducials_create)
00613 {
00614
00615 unsigned int width = CV_Image__width_get(original_image);
00616 unsigned int height = CV_Image__height_get(original_image);
00617 CV_Size image_size = CV_Size__create(width, height);
00618 CV_Memory_Storage storage = CV_Memory_Storage__create(0);
00619
00620
00621 String_Const fiducials_path = fiducials_create->fiducials_path;
00622 String_Const lens_calibrate_file_name =
00623 fiducials_create->lens_calibrate_file_name;
00624 Memory announce_object = fiducials_create->announce_object;
00625 Fiducials_Arc_Announce_Routine arc_announce_routine =
00626 fiducials_create->arc_announce_routine;
00627 Fiducials_Location_Announce_Routine location_announce_routine =
00628 fiducials_create->location_announce_routine;
00629 Fiducials_Tag_Announce_Routine tag_announce_routine =
00630 fiducials_create->tag_announce_routine;
00631 Fiducials_Fiducial_Announce_Routine fiducial_announce_routine =
00632 fiducials_create->fiducial_announce_routine;
00633 String_Const log_file_name = fiducials_create->log_file_name;
00634 String_Const map_base_name = fiducials_create->map_base_name;
00635 String_Const tag_heights_file_name =
00636 fiducials_create->tag_heights_file_name;
00637
00638
00639 File log_file = stderr;
00640 if (log_file_name != (String_Const)0) {
00641 String full_log_file_name =
00642 String__format("%s/%s", fiducials_path, log_file_name);
00643 log_file = File__open(log_file_name, "w");
00644 String__free(full_log_file_name);
00645 }
00646 File__format(log_file, "CV width=%d CV height = %d\n", width, height);
00647
00648 int term_criteria_type =
00649 CV__term_criteria_iterations | CV__term_criteria_eps;
00650
00651
00652
00653
00654 static int north_mapping[64] = {
00655
00656 0, 1, 2, 3, 4, 5, 6, 7,
00657 8, 9, 10, 11, 12, 13, 14, 15,
00658 16, 17, 18, 19, 20, 21, 22, 23,
00659 24, 25, 26, 27, 28, 29, 30, 31,
00660 32, 33, 34, 35, 36, 37, 38, 39,
00661 40, 41, 42, 43, 44, 45, 46, 47,
00662 48, 49, 50, 51, 52, 53, 54, 55,
00663 56, 57, 58, 59, 60, 61, 62, 63,
00664
00665 };
00666
00667 static int west_mapping[64] = {
00668
00669 7, 15, 23, 31, 39, 47, 55, 63,
00670 6, 14, 22, 30, 38, 46, 54, 62,
00671 5, 13, 21, 29, 37, 45, 53, 61,
00672 4, 12, 20, 28, 36, 44, 52, 60,
00673 3, 11, 19, 27, 35, 43, 51, 59,
00674 2, 10, 18, 26, 34, 42, 50, 58,
00675 1, 9, 17, 25, 33, 41, 49, 57,
00676 0, 8, 16, 24, 32, 40, 48, 56,
00677
00678 };
00679
00680 static int south_mapping[64] = {
00681
00682 63, 62, 61, 60, 59, 58, 57, 56,
00683 55, 54, 53, 52, 51, 50, 49, 48,
00684 47, 46, 45, 44, 43, 42, 41, 40,
00685 39, 38, 37, 36, 35, 34, 33, 32,
00686 31, 30, 29, 28, 27, 26, 25, 24,
00687 23, 22, 21, 20, 19, 18, 17, 16,
00688 15, 14, 13, 12, 11, 10, 9, 8,
00689 7, 6, 5, 4, 3, 2, 1, 0,
00690
00691 };
00692
00693 static int east_mapping[64] = {
00694
00695 56, 48, 40, 32, 24, 16, 8, 0,
00696 57, 49, 41, 33, 25, 17, 9, 1,
00697 58, 50, 42, 34, 26, 18, 10, 2,
00698 59, 51, 43, 35, 27, 19, 11, 3,
00699 60, 52, 44, 36, 28, 20, 12, 4,
00700 61, 53, 45, 37, 29, 21, 13, 5,
00701 62, 54, 46, 38, 30, 22, 14, 6,
00702 63, 55, 47, 39, 31, 23, 15, 7,
00703
00704 };
00705
00706 static int north_mapping_flipped[64] = {
00707
00708 7, 6, 5, 4, 3, 2, 1, 0,
00709 15, 14, 13, 12, 11, 10, 9, 8,
00710 23, 22, 21, 20, 19, 18, 17, 16,
00711 31, 30, 29, 28, 27, 26, 25, 24,
00712 39, 38, 37, 36, 35, 34, 33, 32,
00713 47, 46, 45, 44, 43, 42, 41, 40,
00714 55, 54, 53, 52, 51, 50, 49, 48,
00715 63, 62, 61, 60, 59, 58, 57, 56,
00716
00717 };
00718
00719 static int west_mapping_flipped[64] = {
00720
00721 63, 55, 47, 39, 31, 23, 15, 7,
00722 62, 54, 46, 38, 30, 22, 14, 6,
00723 61, 53, 45, 37, 29, 21, 13, 5,
00724 60, 52, 44, 36, 28, 20, 12, 4,
00725 59, 51, 43, 35, 27, 19, 11, 3,
00726 58, 50, 42, 34, 26, 18, 10, 2,
00727 57, 49, 41, 33, 25, 17, 9, 1,
00728 56, 48, 40, 32, 24, 16, 8, 0,
00729
00730 };
00731
00732 static int south_mapping_flipped[64] = {
00733
00734 56, 57, 58, 59, 60, 61, 62, 63,
00735 48, 49, 50, 51, 52, 53, 54, 55,
00736 40, 41, 42, 43, 44, 45, 46, 47,
00737 32, 33, 34, 35, 36, 37, 38, 39,
00738 24, 25, 26, 27, 28, 29, 30, 31,
00739 16, 17, 18, 19, 20, 21, 22, 23,
00740 8, 9, 10, 11, 12, 13, 14, 15,
00741 0, 1, 2, 3, 4, 5, 6, 7,
00742
00743 };
00744
00745 static int east_mapping_flipped[64] = {
00746
00747 0, 8, 16, 24, 32, 40, 48, 56,
00748 1, 9, 17, 25, 33, 41, 49, 57,
00749 2, 10, 18, 26, 34, 42, 50, 58,
00750 3, 11, 19, 27, 35, 43, 51, 59,
00751 4, 13, 20, 28, 36, 44, 52, 60,
00752 5, 13, 21, 29, 37, 45, 53, 61,
00753 6, 14, 22, 30, 38, 46, 54, 62,
00754 7, 15, 23, 31, 39, 47, 55, 63,
00755
00756 };
00757
00758
00759
00760
00761 static int *mappings[4] = {
00762 &north_mapping_flipped[0],
00763 &west_mapping_flipped[0],
00764 &south_mapping_flipped[0],
00765 &east_mapping_flipped[0],
00766 };
00767
00768
00769
00770
00771
00772 CV_Image map_x = (CV_Image)0;
00773 CV_Image map_y = (CV_Image)0;
00774 if (lens_calibrate_file_name != (String)0) {
00775 String full_lens_calibrate_file_name =
00776 String__format("%s/%s", fiducials_path, lens_calibrate_file_name);
00777 assert (CV__undistortion_setup(
00778 full_lens_calibrate_file_name, width, height, &map_x, &map_y) == 0);
00779 String__free(full_lens_calibrate_file_name);
00780 }
00781
00782
00783 Map map = (Map)0;
00784 if (fiducials_create->do_2d_slam) {
00785 Map map = Map__create(fiducials_path, map_base_name, announce_object,
00786 arc_announce_routine, tag_announce_routine,
00787 tag_heights_file_name, "Fiducials__new:Map__create");
00788 }
00789
00790 Fiducials_Results results =
00791 Memory__new(Fiducials_Results, "Fiducials__create");
00792 results->map_changed = (bool)0;
00793
00794
00795 Fiducials fiducials = Memory__new(Fiducials, "Fiducials__create");
00796 fiducials = new(fiducials) Fiducials__Struct();
00797 fiducials->arc_announce_routine = arc_announce_routine;
00798 if (fiducial_announce_routine != NULL)
00799 fiducials->fiducial_announce_routine = fiducial_announce_routine;
00800 else
00801 fiducials->fiducial_announce_routine = Fiducials__fiducial_announce;
00802 fiducials->announce_object = announce_object;
00803 fiducials->blue = CV_Scalar__rgb(0.0, 0.0, 1.0);
00804 fiducials->blur = (bool)0;
00805 fiducials->corners = CV_Point2D32F_Vector__create(4);
00806 fiducials->cyan = CV_Scalar__rgb(0.0, 1.0, 1.0);
00807 fiducials->debug_image = CV_Image__create(image_size, CV__depth_8u, 3);
00808 fiducials->debug_index = 0;
00809 fiducials->edge_image = CV_Image__create(image_size, CV__depth_8u, 1);
00810 fiducials->fec = FEC__create(8, 4, 4);
00811 fiducials->gray_image = CV_Image__create(image_size, CV__depth_8u, 1);
00812 fiducials->green = CV_Scalar__rgb(0.0, 255.0, 0.0);
00813 fiducials->image_size = image_size;
00814 fiducials->last_x = 0.0;
00815 fiducials->last_y = 0.0;
00816 fiducials->location_announce_routine = location_announce_routine;
00817 fiducials->log_file = log_file;
00818 fiducials->map = map;
00819 fiducials->map_x = map_x;
00820 fiducials->map_y = map_y;
00821 fiducials->mappings = &mappings[0];
00822 fiducials->origin = CV_Point__create(0, 0);
00823 fiducials->original_image = original_image;
00824 fiducials->path = fiducials_path;
00825 fiducials->purple = CV_Scalar__rgb(255.0, 0.0, 255.0);
00826 fiducials->red = CV_Scalar__rgb(255.0, 0.0, 0.0);
00827 fiducials->references = CV_Point2D32F_Vector__create(8);
00828 fiducials->results = results;
00829 fiducials->sample_points = CV_Point2D32F_Vector__create(64);
00830 fiducials->size_5x5 = CV_Size__create(5, 5);
00831 fiducials->size_m1xm1 = CV_Size__create(-1, -1);
00832 fiducials->sequence_number = 0;
00833 fiducials->storage = storage;
00834 fiducials->temporary_gray_image =
00835 CV_Image__create(image_size, CV__depth_8u, 1);
00836 fiducials->weights_index = 0;
00837 fiducials->term_criteria =
00838 CV_Term_Criteria__create(term_criteria_type, 5, 0.2);
00839 fiducials->y_flip = (bool)0;
00840 fiducials->black = CV_Scalar__rgb(0, 0, 0);
00841
00842 return fiducials;
00843 }
00844
00849
00850 void Fiducials__free(Fiducials fiducials) {
00851
00852 if (fiducials->map)
00853 Map__save(fiducials->map);
00854
00855
00856 CV_Scalar__free(fiducials->blue);
00857 CV_Scalar__free(fiducials->cyan);
00858 CV_Scalar__free(fiducials->green);
00859 CV_Scalar__free(fiducials->purple);
00860 CV_Scalar__free(fiducials->red);
00861 CV_Scalar__free(fiducials->black);
00862
00863
00864 CV_Size__free(fiducials->image_size);
00865 CV_Size__free(fiducials->size_5x5);
00866 CV_Size__free(fiducials->size_m1xm1);
00867
00868
00869 unsigned int locations_size = fiducials->locations.size();
00870 for (unsigned int index = 0; index < locations_size; index++) {
00871 Location * location = fiducials->locations[index];
00872
00873
00874 }
00875
00876 unsigned int locations_path_size = fiducials->locations_path.size();
00877 for (unsigned int index = 0; index < locations_path_size; index++) {
00878 Location * location = fiducials->locations_path[index];
00879
00880
00881 }
00882
00883
00884 if (fiducials->map)
00885 Map__free(fiducials->map);
00886
00887
00888 Memory__free((Memory)fiducials);
00889 }
00890
00896
00897 void Fiducials__map_save(Fiducials fiducials) {
00898 if (fiducials->map)
00899 Map__save(fiducials->map);
00900 }
00901
00909
00910 Fiducials_Results Fiducials__process(Fiducials fiducials) {
00911
00912 CV_Memory_Storage storage = fiducials->storage;
00913 CV_Memory_Storage__clear(storage);
00914
00915
00916 CV_Image debug_image = fiducials->debug_image;
00917 unsigned int debug_index = fiducials->debug_index;
00918 CV_Image edge_image = fiducials->edge_image;
00919 CV_Image gray_image = fiducials->gray_image;
00920 File log_file = fiducials->log_file;
00921 CV_Image original_image = fiducials->original_image;
00922 Fiducials_Results results = fiducials->results;
00923 CV_Image temporary_gray_image = fiducials->temporary_gray_image;
00924 Fiducials_Location_Announce_Routine location_announce_routine =
00925 fiducials->location_announce_routine;
00926 unsigned int sequence_number = fiducials->sequence_number++;
00927
00928
00929 if (debug_index == 0) {
00930 CV_Image__copy(original_image, debug_image, (CV_Image)0);
00931 }
00932
00933
00934 int channels = CV_Image__channels_get(original_image);
00935
00936
00937 if (debug_index == 0) {
00938 if (channels == 3) {
00939
00940 CV_Image__copy(original_image, debug_image, (CV_Image)0);
00941 } else if (channels == 1) {
00942
00943 CV_Image__convert_color(original_image,
00944 debug_image, CV__gray_to_rgb);
00945 }
00946 }
00947
00948
00949 if (channels == 3) {
00950
00951 CV_Image__convert_color(original_image, gray_image, CV__rgb_to_gray);
00952 } else if (channels == 1) {
00953
00954 CV_Image__copy(original_image, gray_image, (CV_Image)0);
00955 } else {
00956 assert(0);
00957 }
00958
00959
00960 if (debug_index == 1) {
00961 CV_Image__convert_color(gray_image, debug_image, CV__gray_to_rgb);
00962 }
00963
00964
00965 if (fiducials->map_x != (CV_Image)0) {
00966 int flags = CV_INTER_NN | CV_WARP_FILL_OUTLIERS;
00967 CV_Image__copy(gray_image, temporary_gray_image, (CV_Image)0);
00968 CV_Image__remap(temporary_gray_image, gray_image,
00969 fiducials->map_x, fiducials->map_y, flags, fiducials->black);
00970 }
00971
00972
00973 if (debug_index == 2) {
00974 CV_Image__convert_color(gray_image, debug_image, CV__gray_to_rgb);
00975 }
00976
00977
00978 if (fiducials->blur) {
00979 CV_Image__smooth(gray_image, gray_image, CV__gaussian, 3, 0, 0.0, 0.0);
00980 }
00981
00982
00983 if (debug_index == 3) {
00984 CV_Image__convert_color(gray_image, debug_image, CV__gray_to_rgb);
00985 }
00986
00987
00988 CV_Image__adaptive_threshold(gray_image, edge_image, 255.0,
00989 CV__adaptive_thresh_gaussian_c, CV__thresh_binary, 45, 5.0);
00990
00991
00992 if (debug_index == 4) {
00993 CV_Image__convert_color(edge_image, debug_image, CV__gray_to_rgb);
00994 }
00995
00996
00997 CV_Point origin = fiducials->origin;
00998 int header_size = 128;
00999 CV_Sequence contours = CV_Image__find_contours(edge_image, storage,
01000 header_size, CV__retr_list, CV__chain_approx_simple, origin);
01001 if (contours == (CV_Sequence)0) {
01002 File__format(log_file, "no contours found\n");
01003 }
01004
01005
01006 if (debug_index == 5) {
01007
01008 CV_Scalar red = fiducials->red;
01009 CV_Image__convert_color(gray_image, debug_image, CV__gray_to_rgb);
01010 CV_Image__draw_contours(debug_image,
01011 contours, red, red, 2, 2, 8, origin);
01012 }
01013
01014
01015 if (debug_index >= 5) {
01016 CV_Image__convert_color(gray_image, debug_image, CV__gray_to_rgb);
01017 }
01018
01019
01020 Map map = fiducials->map;
01021 unsigned int contours_count = 0;
01022 for (CV_Sequence contour = contours; contour != (CV_Sequence)0;
01023 contour = CV_Sequence__next_get(contour)) {
01024
01025 contours_count += 1;
01026
01027
01028 static CvSlice whole_sequence;
01029 CV_Slice CV__whole_seq = &whole_sequence;
01030 whole_sequence = CV_WHOLE_SEQ;
01031
01032
01033 int arc_length =
01034 (int)(CV_Sequence__arc_length(contour, CV__whole_seq, 1) * 0.02);
01035 CV_Sequence polygon_contour =
01036 CV_Sequence__approximate_polygon(contour,
01037 header_size, storage, CV__poly_approx_dp, arc_length, 0.0);
01038 if (debug_index == 6) {
01039
01040 CV_Scalar green = fiducials->green;
01041 CV_Image__draw_contours(debug_image,
01042 polygon_contour, green, green, 2, 2, 1, origin);
01043 }
01044
01045
01046
01047 if (CV_Sequence__total_get(polygon_contour) == 4 &&
01048 fabs(CV_Sequence__contour_area(polygon_contour,
01049 CV__whole_seq, 0)) > 500.0 &&
01050 CV_Sequence__check_contour_convexity(polygon_contour)) {
01051
01052
01053
01054
01055 if (debug_index == 7) {
01056 CV_Scalar red = fiducials->red;
01057 CV_Image__draw_contours(debug_image,
01058 polygon_contour, red, red, 2, 2, 1, origin);
01059 }
01060
01061
01062 CV_Point2D32F_Vector corners = fiducials->corners;
01063 for (unsigned int index = 0; index < 4; index++) {
01064 CV_Point2D32F corner =
01065 CV_Point2D32F_Vector__fetch1(corners, index);
01066 CV_Point point =
01067 CV_Sequence__point_fetch1(polygon_contour, index);
01068 CV_Point2D32F__point_set(corner, point);
01069
01070 if (debug_index == 7) {
01071
01072
01073 }
01074 }
01075
01076
01077 CV_Image__find_corner_sub_pix(gray_image, corners, 4,
01078 fiducials->size_5x5, fiducials->size_m1xm1,
01079 fiducials->term_criteria);
01080
01081
01082 CV_Point2D32F_Vector__corners_normalize(corners);
01083
01084
01085
01086 if (debug_index == 8) {
01087 for (unsigned int index = 0; index < 4; index++) {
01088 CV_Point point =
01089 CV_Sequence__point_fetch1(polygon_contour, index);
01090 int x = CV_Point__x_get(point);
01091 int y = CV_Point__y_get(point);
01092 CV_Scalar color = (CV_Scalar)0;
01093 String_Const text = (String)0;
01094 switch (index) {
01095 case 0:
01096 color = fiducials->red;
01097 text = "red";
01098 break;
01099 case 1:
01100 color = fiducials->green;
01101 text = "green";
01102 break;
01103 case 2:
01104 color = fiducials->blue;
01105 text = "blue";
01106 break;
01107 case 3:
01108 color = fiducials->purple;
01109 text = "purple";
01110 break;
01111 default:
01112 assert(0);
01113 }
01114 CV_Image__cross_draw(debug_image, x, y, color);
01115 File__format(log_file,
01116 "poly_point[%d]=(%d:%d) %s\n", index, x, y, text);
01117 }
01118 }
01119
01120
01121
01122 CV_Point2D32F_Vector references =
01123 Fiducials__references_compute(fiducials, corners);
01124
01125
01126
01127
01128
01129
01130
01131
01132 int white_darkest =
01133 Fiducials__points_minimum(fiducials, references, 0, 3);
01134 int black_lightest =
01135 Fiducials__points_maximum(fiducials, references, 4, 7);
01136
01137
01138 int threshold = (white_darkest + black_lightest) / 2;
01139
01140
01141
01142
01143 if (debug_index == 9) {
01144 CV_Scalar red = fiducials->red;
01145 CV_Scalar green = fiducials->green;
01146 for (unsigned int index = 0; index < 8; index++) {
01147 CV_Point2D32F reference =
01148 CV_Point2D32F_Vector__fetch1(references, index);
01149 int x = CV__round(CV_Point2D32F__x_get(reference));
01150 int y = CV__round(CV_Point2D32F__y_get(reference));
01151
01152
01153 int value =
01154 Fiducials__point_sample(fiducials, reference);
01155 CV_Scalar color = red;
01156 if (value < threshold) {
01157 color = green;
01158 }
01159 CV_Image__cross_draw(debug_image, x, y, color);
01160 File__format(log_file, "ref[%d:%d]:%d\n", x, y, value);
01161 }
01162 }
01163
01164
01165 if (black_lightest < white_darkest) {
01166
01167
01168
01169 CV_Point2D32F_Vector sample_points = fiducials->sample_points;
01170
01171
01172 Fiducials__sample_points_compute(corners, sample_points);
01173
01174
01175 bool *tag_bits = &fiducials->tag_bits[0];
01176 for (unsigned int index = 0; index < 64; index++) {
01177
01178 CV_Point2D32F sample_point =
01179 CV_Point2D32F_Vector__fetch1(sample_points, index);
01180
01181
01182 int value =
01183 Fiducials__point_sample(fiducials, sample_point);
01184 int bit = (value < threshold);
01185 tag_bits[index] = bit;
01186
01187
01188 if (debug_index == 10) {
01189 CV_Scalar red = fiducials->red;
01190 CV_Scalar green = fiducials->green;
01191 CV_Scalar cyan = fiducials->cyan;
01192 CV_Scalar blue = fiducials->blue;
01193
01194
01195 CV_Scalar color = red;
01196 if (bit) {
01197 color = green;
01198 }
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211 int x =
01212 CV__round(CV_Point2D32F__x_get(sample_point));
01213 int y =
01214 CV__round(CV_Point2D32F__y_get(sample_point));
01215 CV_Image__cross_draw(debug_image, x, y, color);
01216 }
01217 }
01218
01219
01220
01221
01222
01223
01224
01225 int **mappings = fiducials->mappings;
01226 unsigned int mappings_size = 4;
01227 for (unsigned int direction_index = 0;
01228 direction_index < mappings_size; direction_index++) {
01229
01230 int *mapping = mappings[direction_index];
01231
01232
01233
01234
01235 int mapped_bits[64];
01236 for (unsigned int i = 0; i < 64; i++) {
01237 mapped_bits[mapping[i]] = tag_bits[i];
01238 }
01239
01240
01241 unsigned int tag_bytes[8];
01242 for (unsigned int i = 0; i < 8; i++) {
01243 unsigned int byte = 0;
01244 for (unsigned int j = 0; j < 8; j++) {
01245 if (mapped_bits[(i<<3) + j]) {
01246
01247 byte |= 1 << (7 - j);
01248 }
01249 }
01250 tag_bytes[i] = byte;
01251 }
01252 if (debug_index == 11) {
01253 File__format(log_file,
01254 "dir=%d Tag[0]=0x%x Tag[1]=0x%x\n",
01255 direction_index, tag_bytes[0], tag_bytes[1]);
01256 }
01257
01258
01259 FEC fec = fiducials->fec;
01260 if (FEC__correct(fec, tag_bytes, 8)) {
01261
01262 if (debug_index == 11) {
01263 File__format(log_file, "FEC correct\n");
01264 }
01265
01266
01267 unsigned int computed_crc = CRC__compute(tag_bytes, 2);
01268 unsigned int tag_crc = (tag_bytes[3] << 8) | tag_bytes[2];
01269 if (computed_crc == tag_crc) {
01270
01271
01272
01273 unsigned int tag_id =
01274 (tag_bytes[1] << 8) | tag_bytes[0];
01275
01276 if (debug_index == 11) {
01277 File__format(log_file,
01278 "CRC correct, Tag=%d\n", tag_id);
01279 }
01280
01281
01282 CameraTag * camera_tag = new CameraTag();
01283
01284 double vertices[4][2];
01285 for (unsigned int index = 0; index < 4; index++) {
01286 CV_Point2D32F pt = CV_Point2D32F_Vector__fetch1(corners, index);
01287 vertices[index][0] = pt->x;
01288 vertices[index][1] = pt->y;
01289 }
01290 fiducials->fiducial_announce_routine(
01291 fiducials->announce_object, tag_id,
01292 direction_index, 0.0,
01293 vertices[0][0], vertices[0][1],
01294 vertices[1][0], vertices[1][1],
01295 vertices[2][0], vertices[2][1],
01296 vertices[3][0], vertices[3][1]);
01297
01298 if (map) {
01299
01300 Tag * tag = Map__tag_lookup(map, tag_id);
01301 if (debug_index == 11) {
01302 camera_tag->initialize(tag,
01303 direction_index, corners, debug_image);
01304 } else {
01305 camera_tag->initialize(tag,
01306 direction_index, corners, (CV_Image)0);
01307 }
01308 fiducials->current_visibles.push_back(tag);
01309 File__format(log_file, "Tag: %d x=%f y=%f\n",
01310 tag->id, tag->x, tag->y);
01311
01312
01313 double camera_diagonal = camera_tag->diagonal;
01314 double diagonal =
01315 camera_diagonal;
01316 if (diagonal > tag->diagonal) {
01317 tag->diagonal = diagonal;
01318 tag->updated = (bool)1;
01319 }
01320
01321
01322 fiducials->camera_tags.push_back(camera_tag);
01323
01324
01325 }
01326 }
01327 }
01328 }
01329 }
01330 }
01331 }
01332
01333 if (!map) {
01334 return results;
01335 }
01336
01337
01338 std::sort(fiducials->camera_tags.begin(), fiducials->camera_tags.end(),
01339 CameraTag::less);
01340
01341
01342 unsigned int camera_tags_size = fiducials->camera_tags.size();
01343 if (camera_tags_size >= 2) {
01344
01345 for (unsigned int tag1_index = 0;
01346 tag1_index < camera_tags_size - 1; tag1_index++) {
01347 CameraTag * camera_tag1 = fiducials->camera_tags[tag1_index];
01348
01349 for (unsigned int tag2_index = tag1_index + 1;
01350 tag2_index < camera_tags_size; tag2_index++) {
01351 CameraTag * camera_tag2 = fiducials->camera_tags[tag2_index];
01352 assert (camera_tag1->tag->id != camera_tag2->tag->id);
01353 if (Map__arc_update(map,
01354 camera_tag1, camera_tag2, gray_image, sequence_number) > 0) {
01355 results->map_changed = (bool)1;
01356 }
01357 }
01358 }
01359 }
01360
01361 fiducials->locations.clear();
01362 results->image_interesting = (bool)0;
01363 if (camera_tags_size > 0) {
01364 double pi = 3.14159265358979323846264;
01365 unsigned int half_width = CV_Image__width_get(gray_image) >> 1;
01366 unsigned int half_height = CV_Image__height_get(gray_image) >> 1;
01367
01368
01369 for (unsigned int index = 0; index < camera_tags_size; index++) {
01370 CameraTag * camera_tag = fiducials->camera_tags[index];
01371 Tag * tag = camera_tag->tag;
01372
01373
01374
01375 double camera_dx = camera_tag->x - half_width;
01376 double camera_dy = camera_tag->y - half_height;
01377
01378
01379
01380 double polar_distance = hypot(camera_dx, camera_dy);
01381 double polar_angle = atan2(camera_dy, camera_dx);
01382
01383
01384
01385 double floor_distance =
01386 polar_distance * tag->world_diagonal / tag->diagonal;
01387 double angle =
01388 angles::normalize_angle(polar_angle + pi - camera_tag->twist);
01389
01390
01391
01392 double x = tag->x + floor_distance * cos(angle);
01393 double y = tag->y + floor_distance * sin(angle);
01394 double bearing =
01395 angles::normalize_angle(camera_tag->twist + tag->twist);
01396
01397
01398
01399
01400 bearing = angles::normalize_angle(bearing - pi / 2.0);
01401 bearing = -bearing;
01402 bearing = angles::normalize_angle(bearing + pi / 2.0);
01403
01404
01405
01406 unsigned int location_index = fiducials->locations.size();
01407 Location * location = new Location(tag->id,
01408 x, y, bearing, floor_distance, location_index);
01409 fiducials->locations.push_back(location);
01410 }
01411
01412
01413 Location * closest_location = NULL;
01414 unsigned int locations_size = fiducials->locations.size();
01415 for (unsigned int index = 0; index < locations_size; index++) {
01416 Location * location = fiducials->locations[index];
01417 if (closest_location == NULL) {
01418 closest_location = location;
01419 } else {
01420 if (location->goodness < closest_location->goodness) {
01421 closest_location = location;
01422 }
01423 }
01424 }
01425
01426 if (closest_location != NULL) {
01427 fiducials->locations_path.push_back(closest_location);
01428
01429
01430
01431
01432
01433
01434 double change_dx = closest_location->x - fiducials->last_x;
01435 double change_dy = closest_location->y - fiducials->last_y;
01436 double change = hypot(change_dx, change_dy);
01437 if (change > 0.1) {
01438 results->image_interesting = (bool)1;
01439 }
01440 fiducials->last_x = closest_location->x;
01441 fiducials->last_y = closest_location->y;
01442
01443
01444 File__format(log_file,
01445 "Location: id=%d x=%f y=%f bearing=%f\n",
01446 closest_location->id, closest_location->x, closest_location->y,
01447 closest_location->bearing);
01448 location_announce_routine(fiducials->announce_object,
01449 closest_location->id, closest_location->x, closest_location->y,
01450 0.0, closest_location->bearing);
01451 }
01452 }
01453
01454
01455 unsigned int current_visibles_size = fiducials->current_visibles.size();
01456 for (unsigned int current_visibles_index = 0;
01457 current_visibles_index < current_visibles_size;
01458 current_visibles_index++) {
01459 Tag * current_visible =
01460 fiducials->current_visibles[current_visibles_index];
01461
01462
01463
01464
01465 current_visible->visible = (bool)1;
01466 if( current_visible->updated ) {
01467 Map__tag_announce(map, current_visible,
01468 (bool)1, original_image, sequence_number);
01469 current_visible->updated = (bool)0;
01470 }
01471 }
01472
01473
01474 unsigned int previous_visibles_size = fiducials->previous_visibles.size();
01475 for (unsigned int previous_visibles_index = 0;
01476 previous_visibles_index < previous_visibles_size;
01477 previous_visibles_index++) {
01478 Tag * previous_visible =
01479 fiducials->previous_visibles[previous_visibles_index];
01480
01481
01482
01483
01484 Tag * current_visible = NULL;
01485 for (unsigned int current_visibles_index = 0;
01486 current_visibles_index < current_visibles_size;
01487 current_visibles_index++) {
01488 current_visible =
01489 fiducials->current_visibles[current_visibles_index];
01490 if (current_visible == previous_visible) {
01491 break;
01492 }
01493 current_visible = NULL;
01494 }
01495
01496
01497 if (current_visible == NULL) {
01498
01499 previous_visible->visible = (bool)0;
01500 Map__tag_announce(map,
01501 previous_visible, (bool)0, original_image, sequence_number);
01502 }
01503 }
01504
01505
01506 fiducials->current_visibles = fiducials->previous_visibles;
01507 fiducials->previous_visibles.clear();
01508
01509
01510
01511
01512 for( unsigned int i=0; i<fiducials->camera_tags.size(); i++ ) {
01513 delete fiducials->camera_tags[i];
01514 }
01515 fiducials->camera_tags.clear();
01516
01517
01518 if (fiducials->y_flip) {
01519 CV_Image__flip(debug_image, debug_image, 0);
01520 }
01521
01522
01523 Map__update(map, original_image, sequence_number);
01524
01525 File__format(log_file, "\n");
01526 File__flush(log_file);
01527
01528 return results;
01529 }
01530
01540
01541 int Fiducials__point_sample(Fiducials fiducials, CV_Point2D32F point) {
01542
01543
01544
01545 int x = CV__round(CV_Point2D32F__x_get(point));
01546 int y = CV__round(CV_Point2D32F__y_get(point));
01547 CV_Image image = fiducials->gray_image;
01548
01549 static int weights0[9] = {
01550 0, 0, 0,
01551 0, 100, 0,
01552 0, 0, 0};
01553
01554 static int weights1[9] = {
01555 0, 15, 0,
01556 15, 40, 15,
01557 0, 15, 0};
01558
01559 static int weights2[9] = {
01560 5, 10, 5,
01561 10, 40, 10,
01562 5, 10, 5};
01563
01564
01565 static int x_offsets[9] = {
01566 -1, 0, 1,
01567 -1, 0, 1,
01568 -1, 0, 1};
01569 static int y_offsets[9] = {
01570 -1, -1, -1,
01571 0, 0, 0,
01572 1, 1, 1};
01573
01574
01575 int *weights = (int *)0;
01576 switch (fiducials->weights_index) {
01577 case 1:
01578 weights = weights1;
01579 break;
01580 case 2:
01581 weights = weights2;
01582 break;
01583 default:
01584 weights = weights0;
01585 break;
01586 }
01587
01588
01589 int numerator = 0;
01590 int denominator = 0;
01591 for (int index = 0; index < 9; index++) {
01592 int sample = CV_Image__gray_fetch(image,
01593 x + x_offsets[index], y + y_offsets[index]);
01594 if (sample >= 0) {
01595 int weight = weights[index];
01596 numerator += sample * weight;
01597 denominator += weight;
01598 }
01599 }
01600
01601
01602 int result = 0;
01603 if (denominator > 0) {
01604 result = numerator / denominator;
01605 }
01606 return result;
01607 }
01608
01615
01616
01617
01618
01619 void CV_Point2D32F_Vector__corners_normalize(CV_Point2D32F_Vector corners) {
01620
01621
01622
01623 if (CV_Point2D32F_Vector__is_clockwise(corners)) {
01624
01625 CV_Point2D32F corner1 = CV_Point2D32F_Vector__fetch1(corners, 1);
01626 CV_Point2D32F corner3 = CV_Point2D32F_Vector__fetch1(corners, 3);
01627
01628
01629 double x1 = CV_Point2D32F__x_get(corner1);
01630 double y1 = CV_Point2D32F__y_get(corner1);
01631 double x3 = CV_Point2D32F__x_get(corner3);
01632 double y3 = CV_Point2D32F__y_get(corner3);
01633
01634
01635 CV_Point2D32F__x_set(corner1, x3);
01636 CV_Point2D32F__y_set(corner1, y3);
01637 CV_Point2D32F__x_set(corner3, x1);
01638 CV_Point2D32F__y_set(corner3, y1);
01639 }
01640 }
01641
01648
01649 bool CV_Point2D32F_Vector__is_clockwise(CV_Point2D32F_Vector corners) {
01650
01651
01652 CV_Point2D32F corner0 = CV_Point2D32F_Vector__fetch1(corners, 0);
01653 CV_Point2D32F corner1 = CV_Point2D32F_Vector__fetch1(corners, 1);
01654 CV_Point2D32F corner2 = CV_Point2D32F_Vector__fetch1(corners, 2);
01655
01656
01657 double x0 = CV_Point2D32F__x_get(corner0);
01658 double y0 = CV_Point2D32F__y_get(corner0);
01659 double x1 = CV_Point2D32F__x_get(corner1);
01660 double y1 = CV_Point2D32F__y_get(corner1);
01661 double x2 = CV_Point2D32F__x_get(corner2);
01662 double y2 = CV_Point2D32F__y_get(corner2);
01663
01664
01665 double v1x = x1 - x0;
01666 double v1y = y1 - y0;
01667 double v2x = x2 - x1;
01668 double v2y = y2 - y1;
01669
01670
01671 double z = v1x * v2y - v2x * v1y;
01672
01673
01674 return z < 0.0;
01675 }
01676
01690
01691 CV_Point2D32F_Vector Fiducials__references_compute(
01692 Fiducials fiducials, CV_Point2D32F_Vector corners) {
01693
01694
01695 CV_Point2D32F_Vector references = fiducials->references;
01696 CV_Point2D32F reference0 = CV_Point2D32F_Vector__fetch1(references, 0);
01697 CV_Point2D32F reference1 = CV_Point2D32F_Vector__fetch1(references, 1);
01698 CV_Point2D32F reference2 = CV_Point2D32F_Vector__fetch1(references, 2);
01699 CV_Point2D32F reference3 = CV_Point2D32F_Vector__fetch1(references, 3);
01700 CV_Point2D32F reference4 = CV_Point2D32F_Vector__fetch1(references, 4);
01701 CV_Point2D32F reference5 = CV_Point2D32F_Vector__fetch1(references, 5);
01702 CV_Point2D32F reference6 = CV_Point2D32F_Vector__fetch1(references, 6);
01703 CV_Point2D32F reference7 = CV_Point2D32F_Vector__fetch1(references, 7);
01704
01705
01706 CV_Point2D32F corner0 = CV_Point2D32F_Vector__fetch1(corners, 0);
01707 CV_Point2D32F corner1 = CV_Point2D32F_Vector__fetch1(corners, 1);
01708 CV_Point2D32F corner2 = CV_Point2D32F_Vector__fetch1(corners, 2);
01709 CV_Point2D32F corner3 = CV_Point2D32F_Vector__fetch1(corners, 3);
01710
01711
01712 double x0 = CV_Point2D32F__x_get(corner0);
01713 double y0 = CV_Point2D32F__y_get(corner0);
01714 double x1 = CV_Point2D32F__x_get(corner1);
01715 double y1 = CV_Point2D32F__y_get(corner1);
01716 double x2 = CV_Point2D32F__x_get(corner2);
01717 double y2 = CV_Point2D32F__y_get(corner2);
01718 double x3 = CV_Point2D32F__x_get(corner3);
01719 double y3 = CV_Point2D32F__y_get(corner3);
01720
01721 double dx21 = x2 - x1;
01722 double dy21 = y2 - y1;
01723 double dx30 = x3 - x0;
01724 double dy30 = y3 - y0;
01725
01726
01727
01728 double xx0 = x1 + dx21 * 5.0 / 20.0;
01729 double yy0 = y1 + dy21 * 5.0 / 20.0;
01730 double xx1 = x0 + dx30 * 5.0 / 20.0;
01731 double yy1 = y0 + dy30 * 5.0 / 20.0;
01732
01733
01734
01735 double dxx10 = xx1 - xx0;
01736 double dyy10 = yy1 - yy0;
01737 CV_Point2D32F__x_set(reference0, xx0 + dxx10 * -1.0 / 20.0);
01738 CV_Point2D32F__y_set(reference0, yy0 + dyy10 * -1.0 / 20.0);
01739 CV_Point2D32F__x_set(reference4, xx0 + dxx10 * 1.0 / 20.0);
01740 CV_Point2D32F__y_set(reference4, yy0 + dyy10 * 1.0 / 20.0);
01741 CV_Point2D32F__x_set(reference1, xx0 + dxx10 * 21.0 / 20.0);
01742 CV_Point2D32F__y_set(reference1, yy0 + dyy10 * 21.0 / 20.0);
01743 CV_Point2D32F__x_set(reference5, xx0 + dxx10 * 19.0 / 20.0);
01744 CV_Point2D32F__y_set(reference5, yy0 + dyy10 * 19.0 / 20.0);
01745
01746
01747
01748 double xx2 = x1 + dx21 * 15.0 / 20.0;
01749 double yy2 = y1 + dy21 * 15.0 / 20.0;
01750 double xx3 = x0 + dx30 * 15.0 / 20.0;
01751 double yy3 = y0 + dy30 * 15.0 / 20.0;
01752
01753
01754
01755 double dxx32 = xx3 - xx2;
01756 double dyy32 = yy3 - yy2;
01757 CV_Point2D32F__x_set(reference2, xx2 + dxx32 * -1.0 / 20.0);
01758 CV_Point2D32F__y_set(reference2, yy2 + dyy32 * -1.0 / 20.0);
01759 CV_Point2D32F__x_set(reference6, xx2 + dxx32 * 1.0 / 20.0);
01760 CV_Point2D32F__y_set(reference6, yy2 + dyy32 * 1.0 / 20.0);
01761 CV_Point2D32F__x_set(reference3, xx2 + dxx32 * 21.0 / 20.0);
01762 CV_Point2D32F__y_set(reference3, yy2 + dyy32 * 21.0 / 20.0);
01763 CV_Point2D32F__x_set(reference7, xx2 + dxx32 * 19.0 / 20.0);
01764 CV_Point2D32F__y_set(reference7, yy2 + dyy32 * 19.0 / 20.0);
01765
01766 return references;
01767 }
01768
01781
01782 int Fiducials__points_maximum(Fiducials fiducials,
01783 CV_Point2D32F_Vector points, unsigned int start_index, unsigned int end_index) {
01784
01785
01786 int result = 0;
01787
01788
01789 for (unsigned int index = start_index; index <= end_index; index++) {
01790 CV_Point2D32F point = CV_Point2D32F_Vector__fetch1(points, index);
01791 int value = Fiducials__point_sample(fiducials, point);
01792
01793
01794 if (value > result) {
01795
01796 result = value;
01797 }
01798 }
01799 return result;
01800 }
01801
01813
01814 int Fiducials__points_minimum(Fiducials fiducials,
01815 CV_Point2D32F_Vector points, unsigned int start_index, unsigned int end_index) {
01816
01817
01818 int result = 0x7fffffff;
01819
01820
01821 for (unsigned int index = start_index; index <= end_index; index++) {
01822 CV_Point2D32F point = CV_Point2D32F_Vector__fetch1(points, index);
01823 int value = Fiducials__point_sample(fiducials, point);
01824 if (value < result) {
01825
01826 result = value;
01827 }
01828 }
01829 return result;
01830 }
01831
01844
01845
01846
01847
01848 void Fiducials__sample_points_compute(
01849 CV_Point2D32F_Vector corners, CV_Point2D32F_Vector sample_points) {
01850
01851 CV_Point2D32F corner0 = CV_Point2D32F_Vector__fetch1(corners, 0);
01852 CV_Point2D32F corner1 = CV_Point2D32F_Vector__fetch1(corners, 1);
01853 CV_Point2D32F corner2 = CV_Point2D32F_Vector__fetch1(corners, 2);
01854 CV_Point2D32F corner3 = CV_Point2D32F_Vector__fetch1(corners, 3);
01855
01856
01857 double x0 = CV_Point2D32F__x_get(corner0);
01858 double y0 = CV_Point2D32F__y_get(corner0);
01859 double x1 = CV_Point2D32F__x_get(corner1);
01860 double y1 = CV_Point2D32F__y_get(corner1);
01861 double x2 = CV_Point2D32F__x_get(corner2);
01862 double y2 = CV_Point2D32F__y_get(corner2);
01863 double x3 = CV_Point2D32F__x_get(corner3);
01864 double y3 = CV_Point2D32F__y_get(corner3);
01865
01866
01867
01868
01869 double dx21 = x2 - x1;
01870 double dy21 = y2 - y1;
01871 double dx30 = x3 - x0;
01872 double dy30 = y3 - y0;
01873
01874
01875 unsigned int index = 0;
01876
01877
01878
01879
01880
01881
01882
01883 double i_fraction = 3.0 / 20.0;
01884 double i_increment = 2.0 / 20.0;
01885
01886
01887 unsigned int i = 0;
01888 while (i < 8) {
01889
01890
01891
01892
01893 double xx1 = x1 + dx21 * i_fraction;
01894 double yy1 = y1 + dy21 * i_fraction;
01895 double xx2 = x0 + dx30 * i_fraction;
01896 double yy2 = y0 + dy30 * i_fraction;
01897
01898
01899 double dxx21 = xx2 - xx1;
01900 double dyy21 = yy2 - yy1;
01901
01902
01903
01904
01905 double j_fraction = 3.0 / 20.0;
01906 double j_increment = 2.0 / 20.0;
01907
01908
01909 unsigned int j = 0;
01910 while (j < 8) {
01911
01912 CV_Point2D32F sample_point =
01913 CV_Point2D32F_Vector__fetch1(sample_points, index);
01914 index = index + 1;
01915
01916
01917 CV_Point2D32F__x_set(sample_point, xx1 + dxx21 * j_fraction);
01918 CV_Point2D32F__y_set(sample_point, yy1 + dyy21 * j_fraction);
01919
01920
01921 j_fraction = j_fraction + j_increment;
01922 j = j + 1;
01923 }
01924
01925
01926 i_fraction = i_fraction + i_increment;
01927 i = i + 1;
01928 }
01929
01930 CV_Point2D32F sample_point0 =
01931 CV_Point2D32F_Vector__fetch1(sample_points, 0);
01932 CV_Point2D32F sample_point7 =
01933 CV_Point2D32F_Vector__fetch1(sample_points, 7);
01934 CV_Point2D32F sample_point56 =
01935 CV_Point2D32F_Vector__fetch1(sample_points, 56);
01936 CV_Point2D32F sample_point63 =
01937 CV_Point2D32F_Vector__fetch1(sample_points, 63);
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947 }
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01978
01979 void Fiducials__tag_announce(void *announce_object, int id,
01980 double x, double y, double z, double twist, double diagonal,
01981 double distance_per_pixel, bool visible, int hop_count) {
01982 String_Const visible_text = "";
01983 if (!visible) {
01984 visible_text = "*** No longer visible ***";
01985 }
01986 File__format(stderr, "id=%d x=%f y=%f twist=%f %s\n",
01987 id, x, y, twist, visible_text);
01988 }
01989
01990 static struct Fiducials_Create__Struct fiducials_create_struct =
01991 {
01992 (String_Const)0,
01993 (String_Const)0,
01994 (void *)0,
01995 (Fiducials_Arc_Announce_Routine)0,
01996 (Fiducials_Location_Announce_Routine)0,
01997 (Fiducials_Tag_Announce_Routine)0,
01998 (Fiducials_Fiducial_Announce_Routine)0,
01999 (String_Const)0,
02000 (String_Const)0,
02001 (String_Const)0,
02002 };
02003
02010
02011 Fiducials_Create Fiducials_Create__one_and_only(void)
02012 {
02013 return &fiducials_create_struct;
02014 }