Пример #1
0
    void Marker::calculateExtrinsics(float markerSizeMeters, cv::Mat camMatrix, cv::Mat distCoeff,
                                     bool setYPerpendicular)
    {
        if (!isValid())
            throw cv::Exception(9004, "!isValid(): invalid marker. It is not possible to calculate extrinsics",
                                "calculateExtrinsics", __FILE__, __LINE__);
        if (markerSizeMeters <= 0)
            throw cv::Exception(9004, "markerSize<=0: invalid markerSize", "calculateExtrinsics", __FILE__, __LINE__);
        if (camMatrix.rows == 0 || camMatrix.cols == 0)
            throw cv::Exception(9004, "CameraMatrix is empty", "calculateExtrinsics", __FILE__, __LINE__);

        vector<cv::Point3f> objpoints = get3DPoints(markerSizeMeters);


        cv::Mat raux, taux;
//        cv::solvePnP(objpoints, *this, camMatrix, distCoeff, raux, taux);
        solvePnP(objpoints, *this,camMatrix, distCoeff,raux,taux);
        raux.convertTo(Rvec, CV_32F);
        taux.convertTo(Tvec, CV_32F);
        // rotate the X axis so that Y is perpendicular to the marker plane
        if (setYPerpendicular)
            rotateXAxis(Rvec);
        ssize = markerSizeMeters;
        // cout<<(*this)<<endl;

//        auto setPrecision=[](double f, double prec){
//            int x=roundf(f*prec);
//            return  double(x)/prec;
//        };
//        for(int i=0;i<3;i++){
//            Rvec.ptr<float>(0)[i]=setPrecision(Rvec.ptr<float>(0)[i],100);
//            Tvec.ptr<float>(0)[i]=setPrecision(Tvec.ptr<float>(0)[i],1000);
//        }

    }
Пример #2
0
void Camera::addMouseLookDelta( float deltaX, float deltaY )
{
    if ( deltaY != 0.0f )
    {
        rotateYAxis( deltaY );
    }

    if ( deltaX != 0.0f )
    {
        rotateXAxis( deltaX );
    }
}
Пример #3
0
void Marker::calculateExtrinsics(float markerSizeMeters,cv::Mat  camMatrix,cv::Mat distCoeff ,bool setYPerpendicular)throw(cv::Exception)
{
    if (!isValid()) throw cv::Exception(9004,"!isValid(): invalid marker. It is not possible to calculate extrinsics","calculateExtrinsics",__FILE__,__LINE__);
    if (markerSizeMeters<=0)throw cv::Exception(9004,"markerSize<=0: invalid markerSize","calculateExtrinsics",__FILE__,__LINE__);
    if ( camMatrix.rows==0 || camMatrix.cols==0) throw cv::Exception(9004,"CameraMatrix is empty","calculateExtrinsics",__FILE__,__LINE__);
 
     double halfSize=markerSizeMeters/2.;
    cv::Mat ObjPoints(4,3,CV_32FC1);
    ObjPoints.at<float>(1,0)=-halfSize;
    ObjPoints.at<float>(1,1)=halfSize;
    ObjPoints.at<float>(1,2)=0;
    ObjPoints.at<float>(2,0)=halfSize;
    ObjPoints.at<float>(2,1)=halfSize;
    ObjPoints.at<float>(2,2)=0;
    ObjPoints.at<float>(3,0)=halfSize;
    ObjPoints.at<float>(3,1)=-halfSize;
    ObjPoints.at<float>(3,2)=0;
    ObjPoints.at<float>(0,0)=-halfSize;
    ObjPoints.at<float>(0,1)=-halfSize;
    ObjPoints.at<float>(0,2)=0;

    cv::Mat ImagePoints(4,2,CV_32FC1);

    //Set image points from the marker
    for (int c=0;c<4;c++)
    {
        ImagePoints.at<float>(c,0)=((*this)[c].x);
        ImagePoints.at<float>(c,1)=((*this)[c].y);
    }
    
    cv::Mat raux,taux;
    cv::solvePnP(ObjPoints, ImagePoints, camMatrix, distCoeff,raux,taux);
    raux.convertTo(Rvec,CV_32F);
    taux.convertTo(Tvec ,CV_32F);
    //rotate the X axis so that Y is perpendicular to the marker plane
    if (setYPerpendicular)
        rotateXAxis(Rvec);
    ssize=markerSizeMeters; 

#ifndef NO_DEBUG_ARUCO
    cout<<(*this)<<endl;
#endif
    
}
Пример #4
0
void Marker::calculateExtrinsics(float markerSizeMeters, cv::Mat camMatrix, cv::Mat distCoeff,
                                 bool setYPerpendicular) throw(cv::Exception) {
    if (!isValid())
        throw cv::Exception(9004, "!isValid(): invalid marker. It is not possible to calculate extrinsics",
                            "calculateExtrinsics", __FILE__, __LINE__);
    if (markerSizeMeters <= 0)
        throw cv::Exception(9004, "markerSize<=0: invalid markerSize", "calculateExtrinsics", __FILE__,
                            __LINE__);
    if (camMatrix.rows == 0 || camMatrix.cols == 0)
        throw cv::Exception(9004, "CameraMatrix is empty", "calculateExtrinsics", __FILE__, __LINE__);

    double halfSize = markerSizeMeters / 2.;
    cv::Matx<float, 4, 3> ObjPoints;
    ObjPoints(1, 0) = -halfSize;
    ObjPoints(1, 1) = halfSize;
    ObjPoints(1, 2) = 0;
    ObjPoints(2, 0) = halfSize;
    ObjPoints(2, 1) = halfSize;
    ObjPoints(2, 2) = 0;
    ObjPoints(3, 0) = halfSize;
    ObjPoints(3, 1) = -halfSize;
    ObjPoints(3, 2) = 0;
    ObjPoints(0, 0) = -halfSize;
    ObjPoints(0, 1) = -halfSize;
    ObjPoints(0, 2) = 0;

    cv::Matx<float, 4, 2> ImagePoints;

    // Set image points from the marker
    for (int c = 0; c < 4; c++) {
        ImagePoints(c, 0) = ((*this)[c].x);
        ImagePoints(c, 1) = ((*this)[c].y);
    }

    cv::Vec3d raux, taux;
    cv::solvePnP(ObjPoints, ImagePoints, camMatrix, distCoeff, raux, taux);
    Rvec = raux;
    Tvec = taux;
    // rotate the X axis so that Y is perpendicular to the marker plane
    if (setYPerpendicular)
        rotateXAxis(Rvec);
    ssize = markerSizeMeters;
    // cout<<(*this)<<endl;
}
Пример #5
0
float BoardDetector::detect(const vector< Marker > &detectedMarkers, const BoardConfiguration &BConf, Board &Bdetected, Mat camMatrix, Mat distCoeff,
                            float markerSizeMeters) throw(cv::Exception) {
    if (BConf.size() == 0)
        throw cv::Exception(8881, "BoardDetector::detect", "Invalid BoardConfig that is empty", __FILE__, __LINE__);
    if (BConf[0].size() < 2)
        throw cv::Exception(8881, "BoardDetector::detect", "Invalid BoardConfig that is empty 2", __FILE__, __LINE__);
    // compute the size of the markers in meters, which is used for some routines(mostly drawing)
    float ssize;
    if (BConf.mInfoType == BoardConfiguration::PIX && markerSizeMeters > 0)
        ssize = markerSizeMeters;
    else if (BConf.mInfoType == BoardConfiguration::METERS) {
        ssize = cv::norm(BConf[0][0] - BConf[0][1]);
    }

    // cout<<"markerSizeMeters="<<markerSizeMeters<<endl;
    Bdetected.clear();
    /// find among detected markers these that belong to the board configuration
    for (unsigned int i = 0; i < detectedMarkers.size(); i++) {
        int idx = BConf.getIndexOfMarkerId(detectedMarkers[i].id);
        if (idx != -1) {
            Bdetected.push_back(detectedMarkers[i]);
            Bdetected.back().ssize = ssize;
        }
    }
    // copy configuration
    Bdetected.conf = BConf;
    //

    bool hasEnoughInfoForRTvecCalculation = false;
    if (Bdetected.size() >= 1) {
        if (camMatrix.rows != 0) {
            if (markerSizeMeters > 0 && BConf.mInfoType == BoardConfiguration::PIX)
                hasEnoughInfoForRTvecCalculation = true;
            else if (BConf.mInfoType == BoardConfiguration::METERS)
                hasEnoughInfoForRTvecCalculation = true;
        }
    }

    // calculate extrinsic if there is information for that
    if (hasEnoughInfoForRTvecCalculation) {

        // calculate the size of the markers in meters if expressed in pixels
        double marker_meter_per_pix = 0;
        if (BConf.mInfoType == BoardConfiguration::PIX)
            marker_meter_per_pix = markerSizeMeters / cv::norm(BConf[0][0] - BConf[0][1]);
        else
            marker_meter_per_pix = 1; // to avoind interferring the process below

        // now, create the matrices for finding the extrinsics
        vector< cv::Point3f > objPoints;
        vector< cv::Point2f > imagePoints;
        for (size_t i = 0; i < Bdetected.size(); i++) {
            int idx = Bdetected.conf.getIndexOfMarkerId(Bdetected[i].id);
            assert(idx != -1);
            for (int p = 0; p < 4; p++) {
                imagePoints.push_back(Bdetected[i][p]);
                const aruco::MarkerInfo &Minfo = Bdetected.conf.getMarkerInfo(Bdetected[i].id);
                objPoints.push_back(Minfo[p] * marker_meter_per_pix);
                //  		cout<<objPoints.back()<<endl;
            }
        }
        if (distCoeff.total() == 0)
            distCoeff = cv::Mat::zeros(1, 4, CV_32FC1);

        // 	    for(size_t i=0;i< imagePoints.size();i++){
        // 		cout<<objPoints[i]<<" "<<imagePoints[i]<<endl;
        // 	    }
        // 	    cout<<"cam="<<camMatrix<<" "<<distCoeff<<endl;
        cv::Mat rvec, tvec;
        cv::solvePnP(objPoints, imagePoints, camMatrix, distCoeff, rvec, tvec);
        rvec.convertTo(Bdetected.Rvec, CV_32FC1);
        tvec.convertTo(Bdetected.Tvec, CV_32FC1);
        //             cout<<rvec<< " "<<tvec<<" _setYPerpendicular="<<_setYPerpendicular<<endl;

        {
            vector< cv::Point2f > reprojected;
            cv::projectPoints(objPoints, rvec, tvec, camMatrix, distCoeff, reprojected);
            double errSum = 0;
            // check now the reprojection error and
            for (size_t i = 0; i < reprojected.size(); i++) {
                errSum += cv::norm(reprojected[i] - imagePoints[i]);
            }
            //                  cout<<"AAA RE="<<errSum/double ( reprojected.size() ) <<endl;
        }
        // now, do a refinement and remove points whose reprojection error is above a threshold, then repeat calculation with the rest
        if (repj_err_thres > 0) {
            vector< cv::Point2f > reprojected;
            cv::projectPoints(objPoints, rvec, tvec, camMatrix, distCoeff, reprojected);

            vector< int > pointsThatPassTest; // indices
            // check now the reprojection error and
            for (size_t i = 0; i < reprojected.size(); i++) {
                float err = cv::norm(reprojected[i] - imagePoints[i]);
                if (err < repj_err_thres)
                    pointsThatPassTest.push_back(i);
            }
            // cerr<<"Number of points after reprjection test "<<pointsThatPassTest.size() <<"/"<<objPoints.size() <<endl;
            // copy these data to another vectors and repeat
            vector< cv::Point3f > objPoints_filtered;
            vector< cv::Point2f > imagePoints_filtered;
            for (size_t i = 0; i < pointsThatPassTest.size(); i++) {
                objPoints_filtered.push_back(objPoints[pointsThatPassTest[i]]);
                imagePoints_filtered.push_back(imagePoints[pointsThatPassTest[i]]);
            }

            cv::solvePnP(objPoints_filtered, imagePoints_filtered, camMatrix, distCoeff, rvec, tvec);
            rvec.convertTo(Bdetected.Rvec, CV_32FC1);
            tvec.convertTo(Bdetected.Tvec, CV_32FC1);
        }


        // now, rotate 90 deg in X so that Y axis points up
        if (_setYPerpendicular)
            rotateXAxis(Bdetected.Rvec);
        //         cout<<Bdetected.Rvec.at<float>(0,0)<<" "<<Bdetected.Rvec.at<float>(1,0)<<" "<<Bdetected.Rvec.at<float>(2,0)<<endl;
        //         cout<<Bdetected.Tvec.at<float>(0,0)<<" "<<Bdetected.Tvec.at<float>(1,0)<<" "<<Bdetected.Tvec.at<float>(2,0)<<endl;
    }

    float prob = float(Bdetected.size()) / double(Bdetected.conf.size());
    return prob;
}
Пример #6
0
float BoardDetector::detect(const vector<Marker> &detectedMarkers,const  BoardConfiguration &BConf, Board &Bdetected, Mat camMatrix,Mat distCoeff,float markerSizeMeters)throw (cv::Exception)
{
// cout<<"markerSizeMeters="<<markerSizeMeters<<endl;
    ///find among detected markers these that belong to the board configuration
    Mat detected(BConf._markersId.size(),CV_32SC1); //stores the indices of the makers
    detected.setTo(Scalar(-1));//-1 mean not detected
    int nMarkInBoard=0;//total number of markers detected
    for (unsigned int i=0;i<detectedMarkers.size();i++) {
        bool found=false;
        int id=detectedMarkers[i].id;
        //find it
        for (  int j=0;j<detected.size().height && ! found;j++)
            for (  int k=0;k<detected.size().width && ! found;k++)
                if ( BConf._markersId.at<int>(j,k)==id) {
                    detected.at<int>(j,k)=i;
                    nMarkInBoard++;
                    found=true;
                    Bdetected.push_back(detectedMarkers[i]);
                    if (markerSizeMeters>0)
                        Bdetected.back().ssize=markerSizeMeters;
                }
    }
    Bdetected.conf=BConf;
    if (markerSizeMeters!=-1)
        Bdetected.markerSizeMeters=markerSizeMeters;
//calculate extrinsic if there is information for that
    if (camMatrix.rows!=0 && markerSizeMeters>0 && detectedMarkers.size()>1) {
        // now, create the matrices for finding the extrinsics
        Mat objPoints(4*nMarkInBoard,3,CV_32FC1);
        Mat imagePoints(4*nMarkInBoard,2,CV_32FC1);
        //size in meters of inter-marker distance
        double markerDistanceMeters= double(BConf._markerDistancePix) * markerSizeMeters / double(BConf._markerSizePix);



        int currIndex=0;
        for (  int y=0;y<detected.size().height;y++)
            for (  int x=0;x<detected.size().width;x++) {
                if (  detected.at<int>(y,x)!=-1 ) {

                    vector<Point2f> points =detectedMarkers[ detected.at<int>(y,x) ];
                    //set first image points
                    for (int p=0;p<4;p++) {
                        imagePoints.at<float>(currIndex+p,0)=points[p].x;
                        imagePoints.at<float>(currIndex+p,1)=points[p].y;
                    }

                    //tranaltion to make the Ref System be in center
                    float TX=-(  ((detected.size().height-1)*(markerDistanceMeters+markerSizeMeters) +markerSizeMeters) /2) ;
                    float TY=-(  ((detected.size().width-1)*(markerDistanceMeters+markerSizeMeters) +markerSizeMeters)/2);
                    //points in real refernce system. We se the center in the bottom-left corner
                    float AY=x*(markerDistanceMeters+markerSizeMeters ) +TY;
                    float AX=y*(markerDistanceMeters+markerSizeMeters )+TX;
                    objPoints.at<float>( currIndex,0)= AX;
                    objPoints.at<float>( currIndex,1)= AY;
                    objPoints.at<float>( currIndex,2)= 0;
                    objPoints.at<float>( currIndex+1,0)= AX;
                    objPoints.at<float>( currIndex+1,1)= AY+markerSizeMeters;
                    objPoints.at<float>( currIndex+1,2)= 0;
                    objPoints.at<float>( currIndex+2,0)= AX+markerSizeMeters;
                    objPoints.at<float>( currIndex+2,1)= AY+markerSizeMeters;
                    objPoints.at<float>( currIndex+2,2)= 0;
                    objPoints.at<float>( currIndex+3,0)= AX+markerSizeMeters;
                    objPoints.at<float>( currIndex+3,1)= AY;
                    objPoints.at<float>( currIndex+3,2)= 0;
                    currIndex+=4;
                }
            }

        CvMat cvCamMatrix=camMatrix;
        CvMat cvDistCoeffs;
        Mat zeros=Mat::zeros(4,1,CV_32FC1);
        if (distCoeff.rows>=4)  cvDistCoeffs=distCoeff;
        else  cvDistCoeffs=zeros;
        CvMat cvImgPoints=imagePoints;
        CvMat cvObjPoints=objPoints;

        CvMat cvRvec=Bdetected.Rvec;
        CvMat cvTvec=Bdetected.Tvec;
        cvFindExtrinsicCameraParams2(&cvObjPoints, &cvImgPoints, &cvCamMatrix, &cvDistCoeffs,&cvRvec,&cvTvec);
        //now, rotate 90 deg in X so that Y axis points up
        rotateXAxis(Bdetected.Rvec);
        //cout<<Bdetected.Rvec.at<float>(0,0)<<" "<<Bdetected.Rvec.at<float>(1,0)<<Bdetected.Rvec.at<float>(2,0)<<endl;
        //cout<<Bdetected.Tvec.at<float>(0,0)<<" "<<Bdetected.Tvec.at<float>(1,0)<<Bdetected.Tvec.at<float>(2,0)<<endl;
    }
    return double(nMarkInBoard)/double( BConf._markersId.size().width*BConf._markersId.size().height);
}
float BoardDetector::detect ( const vector<Marker> &detectedMarkers,const  BoardConfiguration &BConf, Board &Bdetected, Mat camMatrix,Mat distCoeff,float markerSizeMeters ) throw ( cv::Exception )
{
    if (BConf.size()==0) throw cv::Exception(8881,"BoardDetector::detect","Invalid BoardConfig that is empty",__FILE__,__LINE__);
    if (BConf[0].size()<2) throw cv::Exception(8881,"BoardDetector::detect","Invalid BoardConfig that is empty 2",__FILE__,__LINE__);
    //compute the size of the markers in meters, which is used for some routines(mostly drawing)
    float ssize;
    if ( BConf.mInfoType==BoardConfiguration::PIX && markerSizeMeters>0 ) ssize=markerSizeMeters;
    else if ( BConf.mInfoType==BoardConfiguration::METERS )
    {
        ssize=cv::norm ( BConf[0][0]-BConf[0][1] );
    }

    // cout<<"markerSizeMeters="<<markerSizeMeters<<endl;
    Bdetected.clear();
    ///find among detected markers these that belong to the board configuration
    for ( unsigned int i=0;i<detectedMarkers.size();i++ )
    {
        int idx=BConf.getIndexOfMarkerId(detectedMarkers[i].id);
        if (idx!=-1) {
            Bdetected.push_back ( detectedMarkers[i] );
            Bdetected.back().ssize=ssize;
        }
    }
    //copy configuration
    Bdetected.conf=BConf;
//

    bool hasEnoughInfoForRTvecCalculation=false;
    if ( Bdetected.size() >=1 )
    {
        if ( camMatrix.rows!=0 )
        {
            if ( markerSizeMeters>0 && BConf.mInfoType==BoardConfiguration::PIX ) hasEnoughInfoForRTvecCalculation=true;
            else if ( BConf.mInfoType==BoardConfiguration::METERS ) hasEnoughInfoForRTvecCalculation=true;
        }
    }

//calculate extrinsic if there is information for that
    if ( hasEnoughInfoForRTvecCalculation )
    {

        //calculate the size of the markers in meters if expressed in pixels
        double marker_meter_per_pix=0;
        if ( BConf.mInfoType==BoardConfiguration::PIX ) marker_meter_per_pix=markerSizeMeters /  cv::norm ( BConf[0][0]-BConf[0][1] );
        else marker_meter_per_pix=1;//to avoind interferring the process below

        // now, create the matrices for finding the extrinsics
        Mat objPoints ( 4*Bdetected.size(),3,CV_32FC1 );
        Mat imagePoints ( 4*Bdetected.size(),2,CV_32FC1 );
        //size in meters of inter-marker distance

        for ( size_t i=0;i<Bdetected.size();i++ )
        {
            int idx=Bdetected.conf.getIndexOfMarkerId(Bdetected[i].id);
            assert(idx!=-1);
            for ( int p=0;p<4;p++ )
            {
                imagePoints.at<float> ( ( i*4 ) +p,0 ) =Bdetected[i][p].x;
                imagePoints.at<float> ( ( i*4 ) +p,1 ) =Bdetected[i][p].y;
                const aruco::MarkerInfo &Minfo=Bdetected.conf.getMarkerInfo( Bdetected[i].id);

                objPoints.at<float> ( ( i*4 ) +p,0 ) = Minfo[p].x*marker_meter_per_pix;
                objPoints.at<float> ( ( i*4 ) +p,1 ) = Minfo[p].y*marker_meter_per_pix;
                objPoints.at<float> ( ( i*4 ) +p,2 ) = Minfo[p].z*marker_meter_per_pix;
// 		cout<<objPoints.at<float>( (i*4)+p,0)<<" "<<objPoints.at<float>( (i*4)+p,1)<<" "<<objPoints.at<float>( (i*4)+p,2)<<endl;
            }
        }
        if (distCoeff.total()==0) distCoeff=cv::Mat::zeros(1,4,CV_32FC1 );

        cv::Mat rvec,tvec;
        cv::solvePnP(objPoints,imagePoints,camMatrix,distCoeff,rvec,tvec );
        rvec.convertTo(Bdetected.Rvec,CV_32FC1);
        tvec.convertTo(Bdetected.Tvec,CV_32FC1);
        //now, rotate 90 deg in X so that Y axis points up
        if (_setYPerperdicular)
            rotateXAxis ( Bdetected.Rvec );
//         cout<<Bdetected.Rvec.at<float>(0,0)<<" "<<Bdetected.Rvec.at<float>(1,0)<<" "<<Bdetected.Rvec.at<float>(2,0)<<endl;
//         cout<<Bdetected.Tvec.at<float>(0,0)<<" "<<Bdetected.Tvec.at<float>(1,0)<<" "<<Bdetected.Tvec.at<float>(2,0)<<endl;
    }

    float prob=float( Bdetected.size() ) /double ( Bdetected.conf.size() );
    return prob;
}