Camera_Tag.cpp
Go to the documentation of this file.
00001 // Copyright (c) 2013-2014 by Wayne C. Gramlich.  All rights reserved.
00002 
00003 #include "Camera_Tag.hpp"
00004 #include "Memory.hpp"
00005 #include "Tag.hpp"
00006 
00007 #include <angles/angles.h>
00008 
00016 
00017 bool CameraTag::less(CameraTag * tag1, CameraTag * tag2) {
00018   return Tag::less(tag1->tag, tag2->tag);
00019 }
00020 
00034 
00035 void CameraTag::initialize(Tag * tag, unsigned int direction,
00036     CV_Point2D32F_Vector corners, CV_Image debug_image) {
00037     // We need to remap the 4 corners in *corners* to be oriented as
00038     // in the crude ASCII art shown below:
00039     //
00040     //        2-----------3 ----> twist32 (=P3 - P2)
00041     //        |           |
00042     //        |           |
00043     //        |     C     |
00044     //        |           |
00045     //        |           |
00046     //        1-----------0 ----> twist01 (=P0 - P1)
00047     //
00048     // The *direction* argument provides the information to rotate the
00049     // X/Y valuds in *corners* into this orientation:
00050 
00051     // Fill up *x_corners* and *y_corners* using the *direction* to
00052     // properly index the 4 corners in *corners*.  I wish this code
00053     // were a little clearer, but it literally took several hours to
00054     // figure out.  Basically 4 different orientations of the same
00055     // fiducial were fed into this code to make sure it computed the
00056     // correct 4 corners:
00057     double x_corners[4];
00058     double y_corners[4];
00059     for (unsigned int index = 0; index < 4; index++) {
00060         unsigned corner_index = 0;
00061         switch (direction) {
00062           case 0:
00063             corner_index = (3 - index + 2) & 3;
00064             break;
00065           case 1:
00066             corner_index = (3 - index + 1) & 3;
00067             break;
00068           case 2:
00069             corner_index = (3 - index + 0) & 3;
00070             break;
00071           case 3:
00072             corner_index = (3 - index + 3) & 3;
00073             break;
00074           default:
00075             assert(0);
00076             break;
00077         }
00078         CV_Point2D32F corner =
00079           CV_Point2D32F_Vector__fetch1(corners, corner_index);
00080         x_corners[index] = CV_Point2D32F__x_get(corner);
00081         y_corners[index] = CV_Point2D32F__y_get(corner);
00082     }
00083 
00084     // Pull out the X and Y coordinates into separate variables:
00085     double x0 = x_corners[0];
00086     double y0 = y_corners[0];
00087     double x1 = x_corners[1];
00088     double y1 = y_corners[1];
00089     double x2 = x_corners[2];
00090     double y2 = y_corners[2];
00091     double x3 = x_corners[3];
00092     double y3 = y_corners[3];
00093 
00094     // For debugging plot the for colors
00095     if (debug_image != (CV_Image)0) {
00096         for (unsigned int index = 0; index < 4; index++) {
00097             int x = (int)x_corners[index];
00098             int y = (int)y_corners[index];
00099             CV_Scalar color = (CV_Scalar)0;
00100             String_Const text = (String)0;
00101             switch (index) {
00102               case 0:
00103                 color = CV_Scalar__rgb(255.0, 0.0, 0.0);
00104                 text = "red";
00105                 break;
00106               case 1:
00107                 color = CV_Scalar__rgb(0.0, 255.0, 0.0);
00108                 text = "green";
00109                 break;
00110               case 2:
00111                 color = CV_Scalar__rgb(0.0, 0.0, 255.0);
00112                 text = "blue";
00113                 break;
00114               case 3:
00115                 color = CV_Scalar__rgb(0.0, 255.0, 255.0);
00116                 text = "cyan";
00117                 break;
00118               default:
00119                 assert(0);
00120             }
00121             CV_Image__blob_draw(debug_image, x, y, color);
00122             File__format(stderr,
00123               "Corner[%d]=(%d:%d) %s\n", index, x, y, text);
00124         }
00125     }
00126 
00127     // Compute the angle of the tag bottom edge relative to the camera X axis:
00128     double dx01 = x0 - x1;
00129     double dy01 = y0 - y1;
00130     double twist01 = atan2(dy01, dx01);
00131     //File__format(stderr,
00132     //  "CT_init:id=%d x0:%.2f x1:%.2f dx01:%.2f y0:%.2f y1:%.2f dy01:%.2f\n",
00133     //  tag->id, x0, x1, dx01, y0, y1, dy01);
00134 
00135     // Compute the angle of the tag top edge relative to the camera X axis:
00136     double dx32 = x3 - x2;
00137     double dy32 = y3 - y2;
00138     double twist32 = atan2(dy32, dx32);
00139 
00140     // We want the average angle of *twist01* and *twist32*.  We have
00141     // be careful about modular arithmetic issues.  Compute the angle
00142     // change and add in half of that to get the average angle:
00143     double twist_change = angles::shortest_angular_distance(twist01, twist32);
00144     double twist = angles::normalize_angle(twist01 + twist_change / 2.0);
00145 
00146     double pi = (double)3.14159265358979323846264;
00147     double r2d = 180.0 / pi;
00148     //File__format(stderr, "CT_init:id:%d tw01:%.4f tw32:%.4f tw:%.4f\n",
00149     //  tag->id, twist01 * r2d , twist32 * r2d, twist * r2d);
00150 
00151     // Compute the average of the two diagonals:
00152     double dx02 = x0 - x2;
00153     double dy02 = y0 - y2;
00154     double diagonal02 = hypot(dx02, dy02);
00155     double dx13 = x1 - x3;
00156     double dy13 = y1 - y3;
00157     double diagonal13 = hypot(dx13, dy13);
00158     double diagonal = (diagonal02 + diagonal13) / 2.0;
00159 
00160     // Compute the tag center by averaging for all four corners:
00161     double center_x = (x0 + x1 + x2 + x3) / 4.0;
00162     double center_y = (y0 + y1 + y2 + y2) / 4.0;
00163 
00164     // Load up *carmera_tag*:
00165     this->diagonal = diagonal;
00166     this->direction = direction;
00167     this->tag = tag;
00168     this->twist = twist;
00169     this->x = center_x;
00170     this->y = center_y;
00171 }
00172 
00177 
00178 CameraTag::CameraTag() : diagonal(0.0), direction(0), tag(NULL),
00179     twist(0.0), x(0.0), y(0.0)
00180 {
00181 }
00182 
00183 std::vector<CameraTag*> CameraTag::free_pool;
00184 
00185 void* CameraTag::operator new(size_t sz) {
00186   if(sz == sizeof(CameraTag)) {
00187     if(free_pool.size() > 0) {
00188       void * tmp = free_pool.back();
00189       free_pool.pop_back();
00190       return tmp;
00191     } else {
00192       return ::new char[sz];
00193     }
00194   } else {
00195     assert(0 == sz%sizeof(CameraTag) );
00196     return ::new char[sz];
00197   }
00198 }
00199 
00200 void CameraTag::operator delete(void *p) {
00201   free_pool.push_back((CameraTag*)p);
00202 }


fiducial_lib
Author(s): Wayne Gramlich
autogenerated on Thu Jun 6 2019 18:08:04