Home | History | Annotate | Download | only in src
      1 /*
      2  * Utils.cpp
      3  *
      4  *  Created on: Mar 28, 2014
      5  *      Author: Edgar Riba
      6  */
      7 
      8 #include <iostream>
      9 
     10 #include "PnPProblem.h"
     11 #include "ModelRegistration.h"
     12 #include "Utils.h"
     13 
     14 #include <opencv2/imgproc/imgproc.hpp>
     15 #include <opencv2/calib3d/calib3d.hpp>
     16 
     17 // For text
     18 int fontFace = cv::FONT_ITALIC;
     19 double fontScale = 0.75;
     20 int thickness_font = 2;
     21 
     22 // For circles
     23 int lineType = 8;
     24 int radius = 4;
     25 double thickness_circ = -1;
     26 
     27 // Draw a text with the question point
     28 void drawQuestion(cv::Mat image, cv::Point3f point, cv::Scalar color)
     29 {
     30   std::string x = IntToString((int)point.x);
     31   std::string y = IntToString((int)point.y);
     32   std::string z = IntToString((int)point.z);
     33 
     34   std::string text = " Where is point (" + x + ","  + y + "," + z + ") ?";
     35   cv::putText(image, text, cv::Point(25,50), fontFace, fontScale, color, thickness_font, 8);
     36 }
     37 
     38 // Draw a text with the number of entered points
     39 void drawText(cv::Mat image, std::string text, cv::Scalar color)
     40 {
     41   cv::putText(image, text, cv::Point(25,50), fontFace, fontScale, color, thickness_font, 8);
     42 }
     43 
     44 // Draw a text with the number of entered points
     45 void drawText2(cv::Mat image, std::string text, cv::Scalar color)
     46 {
     47   cv::putText(image, text, cv::Point(25,75), fontFace, fontScale, color, thickness_font, 8);
     48 }
     49 
     50 // Draw a text with the frame ratio
     51 void drawFPS(cv::Mat image, double fps, cv::Scalar color)
     52 {
     53   std::string fps_str = IntToString((int)fps);
     54   std::string text = fps_str + " FPS";
     55   cv::putText(image, text, cv::Point(500,50), fontFace, fontScale, color, thickness_font, 8);
     56 }
     57 
     58 // Draw a text with the frame ratio
     59 void drawConfidence(cv::Mat image, double confidence, cv::Scalar color)
     60 {
     61   std::string conf_str = IntToString((int)confidence);
     62   std::string text = conf_str + " %";
     63   cv::putText(image, text, cv::Point(500,75), fontFace, fontScale, color, thickness_font, 8);
     64 }
     65 
     66 // Draw a text with the number of entered points
     67 void drawCounter(cv::Mat image, int n, int n_max, cv::Scalar color)
     68 {
     69   std::string n_str = IntToString(n);
     70   std::string n_max_str = IntToString(n_max);
     71   std::string text = n_str + " of " + n_max_str + " points";
     72   cv::putText(image, text, cv::Point(500,50), fontFace, fontScale, color, thickness_font, 8);
     73 }
     74 
     75 // Draw the points and the coordinates
     76 void drawPoints(cv::Mat image, std::vector<cv::Point2f> &list_points_2d, std::vector<cv::Point3f> &list_points_3d, cv::Scalar color)
     77 {
     78   for (unsigned int i = 0; i < list_points_2d.size(); ++i)
     79   {
     80     cv::Point2f point_2d = list_points_2d[i];
     81     cv::Point3f point_3d = list_points_3d[i];
     82 
     83     // Draw Selected points
     84     cv::circle(image, point_2d, radius, color, -1, lineType );
     85 
     86     std::string idx = IntToString(i+1);
     87     std::string x = IntToString((int)point_3d.x);
     88     std::string y = IntToString((int)point_3d.y);
     89     std::string z = IntToString((int)point_3d.z);
     90     std::string text = "P" + idx + " (" + x + "," + y + "," + z +")";
     91 
     92     point_2d.x = point_2d.x + 10;
     93     point_2d.y = point_2d.y - 10;
     94     cv::putText(image, text, point_2d, fontFace, fontScale*0.5, color, thickness_font, 8);
     95   }
     96 }
     97 
     98 // Draw only the 2D points
     99 void draw2DPoints(cv::Mat image, std::vector<cv::Point2f> &list_points, cv::Scalar color)
    100 {
    101   for( size_t i = 0; i < list_points.size(); i++)
    102   {
    103     cv::Point2f point_2d = list_points[i];
    104 
    105     // Draw Selected points
    106     cv::circle(image, point_2d, radius, color, -1, lineType );
    107   }
    108 }
    109 
    110 // Draw an arrow into the image
    111 void drawArrow(cv::Mat image, cv::Point2i p, cv::Point2i q, cv::Scalar color, int arrowMagnitude, int thickness, int line_type, int shift)
    112 {
    113   //Draw the principle line
    114   cv::line(image, p, q, color, thickness, line_type, shift);
    115   const double PI = CV_PI;
    116   //compute the angle alpha
    117   double angle = atan2((double)p.y-q.y, (double)p.x-q.x);
    118   //compute the coordinates of the first segment
    119   p.x = (int) ( q.x +  arrowMagnitude * cos(angle + PI/4));
    120   p.y = (int) ( q.y +  arrowMagnitude * sin(angle + PI/4));
    121   //Draw the first segment
    122   cv::line(image, p, q, color, thickness, line_type, shift);
    123   //compute the coordinates of the second segment
    124   p.x = (int) ( q.x +  arrowMagnitude * cos(angle - PI/4));
    125   p.y = (int) ( q.y +  arrowMagnitude * sin(angle - PI/4));
    126   //Draw the second segment
    127   cv::line(image, p, q, color, thickness, line_type, shift);
    128 }
    129 
    130 // Draw the 3D coordinate axes
    131 void draw3DCoordinateAxes(cv::Mat image, const std::vector<cv::Point2f> &list_points2d)
    132 {
    133   cv::Scalar red(0, 0, 255);
    134   cv::Scalar green(0,255,0);
    135   cv::Scalar blue(255,0,0);
    136   cv::Scalar black(0,0,0);
    137 
    138   cv::Point2i origin = list_points2d[0];
    139   cv::Point2i pointX = list_points2d[1];
    140   cv::Point2i pointY = list_points2d[2];
    141   cv::Point2i pointZ = list_points2d[3];
    142 
    143   drawArrow(image, origin, pointX, red, 9, 2);
    144   drawArrow(image, origin, pointY, blue, 9, 2);
    145   drawArrow(image, origin, pointZ, green, 9, 2);
    146   cv::circle(image, origin, radius/2, black, -1, lineType );
    147 
    148 }
    149 
    150 // Draw the object mesh
    151 void drawObjectMesh(cv::Mat image, const Mesh *mesh, PnPProblem *pnpProblem, cv::Scalar color)
    152 {
    153   std::vector<std::vector<int> > list_triangles = mesh->getTrianglesList();
    154   for( size_t i = 0; i < list_triangles.size(); i++)
    155   {
    156     std::vector<int> tmp_triangle = list_triangles.at(i);
    157 
    158     cv::Point3f point_3d_0 = mesh->getVertex(tmp_triangle[0]);
    159     cv::Point3f point_3d_1 = mesh->getVertex(tmp_triangle[1]);
    160     cv::Point3f point_3d_2 = mesh->getVertex(tmp_triangle[2]);
    161 
    162     cv::Point2f point_2d_0 = pnpProblem->backproject3DPoint(point_3d_0);
    163     cv::Point2f point_2d_1 = pnpProblem->backproject3DPoint(point_3d_1);
    164     cv::Point2f point_2d_2 = pnpProblem->backproject3DPoint(point_3d_2);
    165 
    166     cv::line(image, point_2d_0, point_2d_1, color, 1);
    167     cv::line(image, point_2d_1, point_2d_2, color, 1);
    168     cv::line(image, point_2d_2, point_2d_0, color, 1);
    169   }
    170 }
    171 
    172 // Computes the norm of the translation error
    173 double get_translation_error(const cv::Mat &t_true, const cv::Mat &t)
    174 {
    175   return cv::norm( t_true - t );
    176 }
    177 
    178 // Computes the norm of the rotation error
    179 double get_rotation_error(const cv::Mat &R_true, const cv::Mat &R)
    180 {
    181   cv::Mat error_vec, error_mat;
    182   error_mat = R_true * cv::Mat(R.inv()).mul(-1);
    183   cv::Rodrigues(error_mat, error_vec);
    184 
    185   return cv::norm(error_vec);
    186 }
    187 
    188 // Converts a given Rotation Matrix to Euler angles
    189 cv::Mat rot2euler(const cv::Mat & rotationMatrix)
    190 {
    191   cv::Mat euler(3,1,CV_64F);
    192 
    193   double m00 = rotationMatrix.at<double>(0,0);
    194   double m02 = rotationMatrix.at<double>(0,2);
    195   double m10 = rotationMatrix.at<double>(1,0);
    196   double m11 = rotationMatrix.at<double>(1,1);
    197   double m12 = rotationMatrix.at<double>(1,2);
    198   double m20 = rotationMatrix.at<double>(2,0);
    199   double m22 = rotationMatrix.at<double>(2,2);
    200 
    201   double x, y, z;
    202 
    203   // Assuming the angles are in radians.
    204   if (m10 > 0.998) { // singularity at north pole
    205     x = 0;
    206     y = CV_PI/2;
    207     z = atan2(m02,m22);
    208   }
    209   else if (m10 < -0.998) { // singularity at south pole
    210     x = 0;
    211     y = -CV_PI/2;
    212     z = atan2(m02,m22);
    213   }
    214   else
    215   {
    216     x = atan2(-m12,m11);
    217     y = asin(m10);
    218     z = atan2(-m20,m00);
    219   }
    220 
    221   euler.at<double>(0) = x;
    222   euler.at<double>(1) = y;
    223   euler.at<double>(2) = z;
    224 
    225   return euler;
    226 }
    227 
    228 // Converts a given Euler angles to Rotation Matrix
    229 cv::Mat euler2rot(const cv::Mat & euler)
    230 {
    231   cv::Mat rotationMatrix(3,3,CV_64F);
    232 
    233   double x = euler.at<double>(0);
    234   double y = euler.at<double>(1);
    235   double z = euler.at<double>(2);
    236 
    237   // Assuming the angles are in radians.
    238   double ch = cos(z);
    239   double sh = sin(z);
    240   double ca = cos(y);
    241   double sa = sin(y);
    242   double cb = cos(x);
    243   double sb = sin(x);
    244 
    245   double m00, m01, m02, m10, m11, m12, m20, m21, m22;
    246 
    247   m00 = ch * ca;
    248   m01 = sh*sb - ch*sa*cb;
    249   m02 = ch*sa*sb + sh*cb;
    250   m10 = sa;
    251   m11 = ca*cb;
    252   m12 = -ca*sb;
    253   m20 = -sh*ca;
    254   m21 = sh*sa*cb + ch*sb;
    255   m22 = -sh*sa*sb + ch*cb;
    256 
    257   rotationMatrix.at<double>(0,0) = m00;
    258   rotationMatrix.at<double>(0,1) = m01;
    259   rotationMatrix.at<double>(0,2) = m02;
    260   rotationMatrix.at<double>(1,0) = m10;
    261   rotationMatrix.at<double>(1,1) = m11;
    262   rotationMatrix.at<double>(1,2) = m12;
    263   rotationMatrix.at<double>(2,0) = m20;
    264   rotationMatrix.at<double>(2,1) = m21;
    265   rotationMatrix.at<double>(2,2) = m22;
    266 
    267   return rotationMatrix;
    268 }
    269 
    270 // Converts a given string to an integer
    271 int StringToInt ( const std::string &Text )
    272 {
    273    std::istringstream ss(Text);
    274    int result;
    275    return ss >> result ? result : 0;
    276 }
    277 
    278 // Converts a given float to a string
    279 std::string FloatToString ( float Number )
    280 {
    281   std::ostringstream ss;
    282   ss << Number;
    283   return ss.str();
    284 }
    285 
    286 // Converts a given integer to a string
    287 std::string IntToString ( int Number )
    288 {
    289   std::ostringstream ss;
    290   ss << Number;
    291   return ss.str();
    292 }
    293