00001
00002 #include "opencv2/opencv.hpp"
00003
00004 #include "TagDetection.h"
00005 #include "MathUtil.h"
00006
00007 #ifdef PLATFORM_APERIOS
00008
00009 namespace std {
00010 static bool isnan(float x) {
00011 const int EXP = 0x7f800000;
00012 const int FRAC = 0x007fffff;
00013 const int y = *((int*)(&x));
00014 return ((y&EXP)==EXP && (y&FRAC)!=0);
00015 }
00016 }
00017 #endif
00018
00019 namespace AprilTags {
00020
00021 TagDetection::TagDetection()
00022 : good(false), obsCode(), code(), id(), hammingDistance(), rotation(), p(),
00023 cxy(), observedPerimeter(), homography(), hxy() {
00024 homography.setZero();
00025 }
00026
00027 TagDetection::TagDetection(int _id)
00028 : good(false), obsCode(), code(), id(_id), hammingDistance(), rotation(), p(),
00029 cxy(), observedPerimeter(), homography(), hxy() {
00030 homography.setZero();
00031 }
00032
00033 float TagDetection::getXYOrientation() const {
00034
00035
00036
00037
00038
00039 std::pair<float,float> p0 = interpolate(-1,-1);
00040 std::pair<float,float> p1 = interpolate(1,-1);
00041 float orient = atan2(p1.second - p0.second, p1.first - p0.first);
00042 return ! std::isnan(float(orient)) ? orient : 0.;
00043 }
00044
00045 std::pair<float,float> TagDetection::interpolate(float x, float y) const {
00046 float z = homography(2,0)*x + homography(2,1)*y + homography(2,2);
00047 if ( z == 0 )
00048 return std::pair<float,float>(0,0);
00049 float newx = (homography(0,0)*x + homography(0,1)*y + homography(0,2))/z + hxy.first;
00050 float newy = (homography(1,0)*x + homography(1,1)*y + homography(1,2))/z + hxy.second;
00051 return std::pair<float,float>(newx,newy);
00052 }
00053
00054 bool TagDetection::overlapsTooMuch(const TagDetection &other) const {
00055
00056
00057
00058 float radius =
00059 ( MathUtil::distance2D(p[0], p[1]) +
00060 MathUtil::distance2D(p[1], p[2]) +
00061 MathUtil::distance2D(p[2], p[3]) +
00062 MathUtil::distance2D(p[3], p[0]) +
00063 MathUtil::distance2D(other.p[0], other.p[1]) +
00064 MathUtil::distance2D(other.p[1], other.p[2]) +
00065 MathUtil::distance2D(other.p[2], other.p[3]) +
00066 MathUtil::distance2D(other.p[3], other.p[0]) ) / 16.0f;
00067
00068
00069 float dist = MathUtil::distance2D(cxy, other.cxy);
00070
00071
00072
00073 return ( dist < radius );
00074 }
00075
00076 Eigen::Matrix4d TagDetection::getRelativeTransform(double tag_size, double fx, double fy, double px, double py) const {
00077 std::vector<cv::Point3f> objPts;
00078 std::vector<cv::Point2f> imgPts;
00079 double s = tag_size/2.;
00080 objPts.push_back(cv::Point3f(-s,-s, 0));
00081 objPts.push_back(cv::Point3f( s,-s, 0));
00082 objPts.push_back(cv::Point3f( s, s, 0));
00083 objPts.push_back(cv::Point3f(-s, s, 0));
00084
00085 std::pair<float, float> p1 = p[0];
00086 std::pair<float, float> p2 = p[1];
00087 std::pair<float, float> p3 = p[2];
00088 std::pair<float, float> p4 = p[3];
00089 imgPts.push_back(cv::Point2f(p1.first, p1.second));
00090 imgPts.push_back(cv::Point2f(p2.first, p2.second));
00091 imgPts.push_back(cv::Point2f(p3.first, p3.second));
00092 imgPts.push_back(cv::Point2f(p4.first, p4.second));
00093
00094 cv::Mat rvec, tvec;
00095 cv::Matx33f cameraMatrix(
00096 fx, 0, px,
00097 0, fy, py,
00098 0, 0, 1);
00099 cv::Vec4f distParam(0,0,0,0);
00100 cv::solvePnP(objPts, imgPts, cameraMatrix, distParam, rvec, tvec);
00101 cv::Matx33d r;
00102 cv::Rodrigues(rvec, r);
00103 Eigen::Matrix3d wRo;
00104 wRo << r(0,0), r(0,1), r(0,2), r(1,0), r(1,1), r(1,2), r(2,0), r(2,1), r(2,2);
00105
00106 Eigen::Matrix4d T;
00107 T.topLeftCorner(3,3) = wRo;
00108 T.col(3).head(3) << tvec.at<double>(0), tvec.at<double>(1), tvec.at<double>(2);
00109 T.row(3) << 0,0,0,1;
00110
00111 return T;
00112 }
00113
00114 void TagDetection::getRelativeTranslationRotation(double tag_size, double fx, double fy, double px, double py,
00115 Eigen::Vector3d& trans, Eigen::Matrix3d& rot) const {
00116 Eigen::Matrix4d T =
00117 getRelativeTransform(tag_size, fx, fy, px, py);
00118
00119
00120
00121 Eigen::Matrix4d M;
00122 M <<
00123 0, 0, 1, 0,
00124 -1, 0, 0, 0,
00125 0, -1, 0, 0,
00126 0, 0, 0, 1;
00127 Eigen::Matrix4d MT = M*T;
00128
00129 trans = MT.col(3).head(3);
00130
00131
00132
00133 rot = T.block(0,0,3,3);
00134 }
00135
00136
00137 void TagDetection::draw(cv::Mat& image) const {
00138
00139 std::pair<float, float> p1 = p[0];
00140 std::pair<float, float> p2 = p[1];
00141 std::pair<float, float> p3 = p[2];
00142 std::pair<float, float> p4 = p[3];
00143
00144
00145 cv::line(image, cv::Point2f(p1.first, p1.second), cv::Point2f(p2.first, p2.second), cv::Scalar(255,0,0,0) );
00146 cv::line(image, cv::Point2f(p2.first, p2.second), cv::Point2f(p3.first, p3.second), cv::Scalar(0,255,0,0) );
00147 cv::line(image, cv::Point2f(p3.first, p3.second), cv::Point2f(p4.first, p4.second), cv::Scalar(0,0,255,0) );
00148 cv::line(image, cv::Point2f(p4.first, p4.second), cv::Point2f(p1.first, p1.second), cv::Scalar(255,0,255,0) );
00149
00150
00151 cv::circle(image, cv::Point2f(cxy.first, cxy.second), 8, cv::Scalar(0,0,255,0), 2);
00152
00153
00154 std::ostringstream strSt;
00155 strSt << "#" << id;
00156 cv::putText(image, strSt.str(),
00157 cv::Point2f(cxy.first + 10, cxy.second + 10),
00158 cv::FONT_HERSHEY_PLAIN, 1, cv::Scalar(0,0,255));
00159 }
00160
00161 }