00001 #include "aruco/boarddetector.h"
00002 #include <cstdlib>
00003 #include <ctime>
00004 #include <cassert>
00005 #include <fstream>
00006 using namespace std;
00007 namespace aruco
00008 {
00013 float BoardDetector::detect(const vector<Marker> &detectedMarkers,const BoardConfiguration &BConf, Board &Bdetected, CameraParameters cp, float markerSizeMeters )throw (cv::Exception)
00014 {
00015 return detect(detectedMarkers, BConf,Bdetected,cp.CameraMatrix,cp.Distorsion,markerSizeMeters);
00016 }
00021 float BoardDetector::detect(const vector<Marker> &detectedMarkers,const BoardConfiguration &BConf, Board &Bdetected, Mat camMatrix,Mat distCoeff,float markerSizeMeters)throw (cv::Exception)
00022 {
00023
00025 Mat detected(BConf._markersId.size(),CV_32SC1);
00026 detected.setTo(Scalar(-1));
00027 int nMarkInBoard=0;
00028 for (unsigned int i=0;i<detectedMarkers.size();i++) {
00029 bool found=false;
00030 int id=detectedMarkers[i].id;
00031
00032 for ( int j=0;j<detected.size().height && ! found;j++)
00033 for ( int k=0;k<detected.size().width && ! found;k++)
00034 if ( BConf._markersId.at<int>(j,k)==id) {
00035 detected.at<int>(j,k)=i;
00036 nMarkInBoard++;
00037 found=true;
00038 Bdetected.push_back(detectedMarkers[i]);
00039 if (markerSizeMeters>0)
00040 Bdetected.back().ssize=markerSizeMeters;
00041 }
00042 }
00043 Bdetected.conf=BConf;
00044 if (markerSizeMeters!=-1)
00045 Bdetected.markerSizeMeters=markerSizeMeters;
00046
00047 if (camMatrix.rows!=0 && markerSizeMeters>0 && detectedMarkers.size()>1) {
00048
00049 Mat objPoints(4*nMarkInBoard,3,CV_32FC1);
00050 Mat imagePoints(4*nMarkInBoard,2,CV_32FC1);
00051
00052 double markerDistanceMeters= double(BConf._markerDistancePix) * markerSizeMeters / double(BConf._markerSizePix);
00053
00054
00055
00056 int currIndex=0;
00057 for ( int y=0;y<detected.size().height;y++)
00058 for ( int x=0;x<detected.size().width;x++) {
00059 if ( detected.at<int>(y,x)!=-1 ) {
00060
00061 vector<Point2f> points =detectedMarkers[ detected.at<int>(y,x) ];
00062
00063 for (int p=0;p<4;p++) {
00064 imagePoints.at<float>(currIndex+p,0)=points[p].x;
00065 imagePoints.at<float>(currIndex+p,1)=points[p].y;
00066 }
00067
00068
00069 float TX=-( ((detected.size().height-1)*(markerDistanceMeters+markerSizeMeters) +markerSizeMeters) /2) ;
00070 float TY=-( ((detected.size().width-1)*(markerDistanceMeters+markerSizeMeters) +markerSizeMeters)/2);
00071
00072 float AY=x*(markerDistanceMeters+markerSizeMeters ) +TY;
00073 float AX=y*(markerDistanceMeters+markerSizeMeters )+TX;
00074 objPoints.at<float>( currIndex,0)= AX;
00075 objPoints.at<float>( currIndex,1)= AY;
00076 objPoints.at<float>( currIndex,2)= 0;
00077 objPoints.at<float>( currIndex+1,0)= AX;
00078 objPoints.at<float>( currIndex+1,1)= AY+markerSizeMeters;
00079 objPoints.at<float>( currIndex+1,2)= 0;
00080 objPoints.at<float>( currIndex+2,0)= AX+markerSizeMeters;
00081 objPoints.at<float>( currIndex+2,1)= AY+markerSizeMeters;
00082 objPoints.at<float>( currIndex+2,2)= 0;
00083 objPoints.at<float>( currIndex+3,0)= AX+markerSizeMeters;
00084 objPoints.at<float>( currIndex+3,1)= AY;
00085 objPoints.at<float>( currIndex+3,2)= 0;
00086 currIndex+=4;
00087 }
00088 }
00089
00090 CvMat cvCamMatrix=camMatrix;
00091 CvMat cvDistCoeffs;
00092 Mat zeros=Mat::zeros(4,1,CV_32FC1);
00093 if (distCoeff.rows>=4) cvDistCoeffs=distCoeff;
00094 else cvDistCoeffs=zeros;
00095 CvMat cvImgPoints=imagePoints;
00096 CvMat cvObjPoints=objPoints;
00097
00098 CvMat cvRvec=Bdetected.Rvec;
00099 CvMat cvTvec=Bdetected.Tvec;
00100 cvFindExtrinsicCameraParams2(&cvObjPoints, &cvImgPoints, &cvCamMatrix, &cvDistCoeffs,&cvRvec,&cvTvec);
00101
00102 rotateXAxis(Bdetected.Rvec);
00103
00104
00105 }
00106 return double(nMarkInBoard)/double( BConf._markersId.size().width*BConf._markersId.size().height);
00107 }
00108
00109 void BoardDetector::rotateXAxis(Mat &rotation)
00110 {
00111 cv::Mat R(3,3,CV_32FC1);
00112 Rodrigues(rotation, R);
00113
00114 cv::Mat RX=cv::Mat::eye(3,3,CV_32FC1);
00115 float angleRad=M_PI/2;
00116 RX.at<float>(1,1)=cos(angleRad);
00117 RX.at<float>(1,2)=-sin(angleRad);
00118 RX.at<float>(2,1)=sin(angleRad);
00119 RX.at<float>(2,2)=cos(angleRad);
00120
00121 R=R*RX;
00122
00123 Rodrigues(R,rotation);
00124
00125 }
00126
00127
00128 void Board::glGetModelViewMatrix( double modelview_matrix[16])throw(cv::Exception)
00129 {
00130
00131 bool invalid=false;
00132 for (int i=0;i<3 && !invalid ;i++)
00133 {
00134 if (Tvec.at<float>(i,0)!=-999999) invalid|=false;
00135 if (Rvec.at<float>(i,0)!=-999999) invalid|=false;
00136 }
00137 if (invalid) throw cv::Exception(9002,"extrinsic parameters are not set","Marker::getModelViewMatrix",__FILE__,__LINE__);
00138 Mat Rot(3,3,CV_32FC1),Jacob;
00139 Rodrigues(Rvec, Rot, Jacob);
00140
00141 double para[3][4];
00142 for (int i=0;i<3;i++)
00143 for (int j=0;j<3;j++) para[i][j]=Rot.at<float>(i,j);
00144
00145 para[0][3]=Tvec.at<float>(0,0);
00146 para[1][3]=Tvec.at<float>(1,0);
00147 para[2][3]=Tvec.at<float>(2,0);
00148 double scale=1;
00149
00150 modelview_matrix[0 + 0*4] = para[0][0];
00151
00152 modelview_matrix[0 + 1*4] = para[0][1];
00153 modelview_matrix[0 + 2*4] = para[0][2];
00154 modelview_matrix[0 + 3*4] = para[0][3];
00155
00156 modelview_matrix[1 + 0*4] = para[1][0];
00157 modelview_matrix[1 + 1*4] = para[1][1];
00158 modelview_matrix[1 + 2*4] = para[1][2];
00159 modelview_matrix[1 + 3*4] = para[1][3];
00160
00161 modelview_matrix[2 + 0*4] = -para[2][0];
00162 modelview_matrix[2 + 1*4] = -para[2][1];
00163 modelview_matrix[2 + 2*4] = -para[2][2];
00164 modelview_matrix[2 + 3*4] = -para[2][3];
00165 modelview_matrix[3 + 0*4] = 0.0;
00166 modelview_matrix[3 + 1*4] = 0.0;
00167 modelview_matrix[3 + 2*4] = 0.0;
00168 modelview_matrix[3 + 3*4] = 1.0;
00169 if (scale != 0.0)
00170 {
00171 modelview_matrix[12] *= scale;
00172 modelview_matrix[13] *= scale;
00173 modelview_matrix[14] *= scale;
00174 }
00175
00176
00177 }
00178
00179 };
00180