/* * registration implementation * * Copyright (C) HamidReza Houshiar * * Released under the GPL version 3. * */ #include "slam6d/fbr/registration.h" using namespace std; namespace fbr{ registration::registration(unsigned int minD, double minE, unsigned int minI, registration_method method){ minDistance = minD; minError = minE; minInlier = minI; rMethod = method; bestError = minError; bestErrorIndex = 0; for(int i = 0; i < 16; i++) bestAlign[i] = 0; } registration::registration(){ minDistance = 50; minError = 50; minInlier = 5; rMethod = RANSAC; bestError = minError; bestErrorIndex = 0; for(int i = 0; i < 16; i++) bestAlign[i] = 0; } int registration::getCoord(vector fKeypoints, vector sKeypoints, vector matches, cv::Mat fPMap, cv::Mat sPMap, int idx, cv::Point3f& cq, cv::Point3f& ct){ int x, y; y = fKeypoints[matches[idx].queryIdx].pt.x; x = fKeypoints[matches[idx].queryIdx].pt.y; if(fKeypoints[matches[idx].queryIdx].pt.x - x > 0.5) x++; if(fKeypoints[matches[idx].queryIdx].pt.y - y > 0.5) y++; cv::Mat_ _fPMap = fPMap; float sqr = sqrt (_fPMap(x,y)[0] * _fPMap(x,y)[0] + _fPMap(x,y)[1] * _fPMap(x,y)[1] + _fPMap(x,y)[2] * _fPMap(x,y)[2]); if(sqr != 0){ cq.x = _fPMap(x,y)[0]; cq.y = _fPMap(x,y)[1]; cq.z = _fPMap(x,y)[2]; } else return 0; y = sKeypoints[matches[idx].trainIdx].pt.x; x = sKeypoints[matches[idx].trainIdx].pt.y; if(sKeypoints[matches[idx].trainIdx].pt.x - x > 0.5) x++; if(sKeypoints[matches[idx].trainIdx].pt.y - y > 0.5) y++; cv::Mat_ _sPMap = sPMap; sqr = sqrt (_sPMap(x,y)[0] * _sPMap(x,y)[0] + _sPMap(x,y)[1] * _sPMap(x,y)[1] + _sPMap(x,y)[2] * _sPMap(x,y)[2]); if(sqr != 0){ ct.x = _sPMap(x,y)[0]; ct.y = _sPMap(x,y)[1]; ct.z = _sPMap(x,y)[2]; } else return 0; return 1; } void registration::pointToArray(cv::Point3f c, double* cd){ cd[0] = c.x; cd[1] = c.y; cd[2] = c.z; } cv::Point3f registration::coordTransform(cv::Point3f p, double* align){ cv::Point3f tp; tp.x = align[0]*p.x + align[4]*p.y + align[8]*p.z + align[12]; tp.y = align[1]*p.x + align[5]*p.y + align[9]*p.z + align[13]; tp.z = align[2]*p.x + align[6]*p.y + align[10]*p.z + align[14]; return tp; } int registration::findAlign(unsigned int i, unsigned int j, unsigned int k, cv::Mat fPMap, vector fKeypoints, cv::Mat sPMap, vector sKeypoints, vector matches){ cv::Point3f c1q, c2q, c3q, c1t, c2t, c3t; if(i == j || i == k || j == k) return 0; //get the coordinates if(getCoord(fKeypoints, sKeypoints, matches, fPMap, sPMap, i, c1q, c1t) == 0) return 0; if(getCoord(fKeypoints, sKeypoints, matches, fPMap, sPMap, j, c2q, c2t) == 0) return 0; if(getCoord(fKeypoints, sKeypoints, matches, fPMap, sPMap, k, c3q, c3t) == 0) return 0; //check for min distance if(norm(c1q - c2q) < minDistance || norm(c1q - c3q) < minDistance || norm(c2q - c3q) < minDistance || norm(c1t - c2t) < minDistance || norm(c1t - c3t) < minDistance || norm(c2t - c3t) < minDistance) return 0; //calculate the centroids cv::Point3f centroidq, centroidt; centroidq = (c1q + c2q + c3q); centroidt = (c1t + c2t + c3t); centroidq.x = centroidq.x / 3; centroidq.y = centroidq.y / 3; centroidq.z = centroidq.z / 3; centroidt.x = centroidt.x / 3; centroidt.y = centroidt.y / 3; centroidt.z = centroidt.z / 3; //put each point into double array double c1qd[3], c2qd[3], c3qd[3], c1td[3], c2td[3], c3td[3]; cv::Point3f temp; pointToArray(c1q, c1qd); pointToArray(c2q, c2qd); pointToArray(c3q, c3qd); pointToArray(c1t, c1td); pointToArray(c2t, c2td); pointToArray(c3t, c3td); //create PtPair and calc the align with icp6D_QUAT vector pairs; pairs.push_back(PtPair(c1qd, c1td)); pairs.push_back(PtPair(c2qd, c2td)); pairs.push_back(PtPair(c3qd, c3td)); double align[16]; double centroidqd[3], centroidtd[3]; pointToArray(centroidq, centroidqd); pointToArray(centroidt, centroidtd); icp6D_QUAT q(true); q.Point_Point_Align(pairs, align, centroidqd, centroidtd); //transform the matches with align if the error is less than minerror double iError = 0; unsigned int eIdx = 0; for(unsigned int p = 0; p < matches.size(); p++){ if(p == i || p == j || p == k) continue; cv::Point3f cq, ct, ct_trans; if(getCoord(fKeypoints, sKeypoints, matches, fPMap, sPMap, p, cq, ct) == 0) continue; ct_trans = coordTransform(ct, align); if(norm(ct_trans - cq) < minError){ iError += norm(ct_trans - cq); eIdx++; } } //check for mininlier and find the best align if(eIdx > minInlier){ double aError = iError / eIdx; if(aError - iInfluence*eIdx < bestError - iInfluence*bestErrorIndex){ bestError = aError; bestErrorIndex = eIdx; for(int a = 0; a < 16; a++) bestAlign[a] = align[a]; } } return 1; } void registration::findRegistration(cv::Mat fPMap, vector fKeypoints, cv::Mat sPMap, vector sKeypoints, vector matches){ //go through all matches if(rMethod == ALL){ for(unsigned int i = 0; i < matches.size(); i++) for(unsigned int j = 0; j < matches.size(); j++) for(unsigned int k = 0; k < matches.size(); k++){ findAlign(i, j, k, fPMap, fKeypoints, sPMap, sKeypoints, matches); } } //RANSAC if(rMethod == RANSAC) for(int r = 0; r < RANSACITR; r++){ if((r % (RANSACITR/10)) == 0){ cout<<"RANSAC iteration: "<<(r / (RANSACITR/10) + 1) * 10 <<"%"< 0){ cout<