deleted prints for debug. BranchAndBound is a stand alone function.

This commit is contained in:
Paolo Cignoni cignoni 2009-07-26 20:40:39 +00:00
parent 4fe5ff2a76
commit 616a4096a2
2 changed files with 71 additions and 54 deletions

View File

@ -382,6 +382,7 @@ template<class MESH_TYPE, class FEATURE_TYPE> class FeatureAlignment
int totalTime;
int baseSelectionTime;
int matchingTime;
int branchBoundTime;
int rankTime;
int shortConsTime;
int fullConsTime;
@ -403,6 +404,7 @@ template<class MESH_TYPE, class FEATURE_TYPE> class FeatureAlignment
shortConsTime = 0;
fullConsTime = 0;
baseSelectionTime = 0;
branchBoundTime = 0;
rankTime = 0;
errorMsg = "An unkown error occurred.";
}
@ -501,6 +503,7 @@ template<class MESH_TYPE, class FEATURE_TYPE> class FeatureAlignment
//auxiliary vectors needed inside the loop
vector<FeatureType**>* baseVec = new vector<FeatureType**>();
vector<vector<FeatureType*> > matches;
vector<CandidateType>* candidates = new vector<CandidateType>();
//variables needed for progress bar callback
@ -518,15 +521,23 @@ template<class MESH_TYPE, class FEATURE_TYPE> class FeatureAlignment
res.baseSelectionTime = timer.elapsed();
if(param.log) param.log(3,"%i bases found in %i msec.", baseVec->size(), res.baseSelectionTime);
timer.start();
for(int i = 0; i<baseVec->size(); i++)
{
int errCode = FeatureAlignment::Matching(*vecFFix, *vecFMov, fkdTree, (*baseVec)[i], *candidates, param);
timer.start();
int errCode = FeatureAlignment::Matching(*vecFFix, *vecFMov, fkdTree, (*baseVec)[i], matches, param);
res.matchingTime+= timer.elapsed();
timer.start();
errCode = FeatureAlignment::BranchAndBound((*baseVec)[i], matches, *candidates, param);
matches.clear(); //make matches vec ready for another iteration
res.branchBoundTime+= timer.elapsed();
if(cb){ progBar+=(20.0f/baseVec->size()); cb(int(progBar),"Matching..."); }
}
res.matchingTime = timer.elapsed();
res.numMatches = candidates->size();
if(param.log) param.log(3,"%i candidates found in %i msec.", candidates->size(), res.matchingTime);
if(param.log) param.log(3,"%matching performed in %i msec.", res.matchingTime);
if(param.log) param.log(3,"%Branch&Bound performed in %i msec.", res.branchBoundTime);
if(param.log) param.log(3,"%i candidates found in %i msec.", candidates->size(), res.matchingTime+res.branchBoundTime);
timer.start();
for(unsigned int j=0; j<candidates->size(); j++)
@ -546,12 +557,12 @@ template<class MESH_TYPE, class FEATURE_TYPE> class FeatureAlignment
if(cb){ progBar+=(20.0f/candidates->size()); cb(int(progBar),"Ranking candidates..."); }
}
//sort candidates by summed point distances
sort(candidates->begin(), candidates->end(), CandidateType::SortByDistance);
res.rankTime = timer.elapsed();
if(param.log) param.log(3,"Ranking performed in %i msec.", res.rankTime);
//sort candidates by summed point distances
sort(candidates->begin(), candidates->end(), CandidateType::SortByDistance);
for(int i=0; i<50;i++)if(param.log) param.log(3,"%i spd %.2f.", i,(*candidates)[i].summedPointDist);
//variable needed for progress bar callback
float offset = (20.0f/math::Min(param.maxNumShortConsensus,int(candidates->size())));
@ -565,15 +576,14 @@ for(int i=0; i<50;i++)if(param.log) param.log(3,"%i spd %.2f.", i,(*candidates)[
consParam.samples=param.short_cons_samples;
consParam.threshold = param.shortConsOffset*param.overlap/100.0f;
currCandidate.shortCons = cons.Check(consParam); //compute short consensus
if(param.log) param.log(3,"%i short cons %i.", j,currCandidate.shortCons);
ResetTransformation(mMov, oldTr); //restore old tranformation
ResetTransformation(mMov, oldTr); //restore old tranformation
if(currCandidate.shortCons >= short_cons_succ) res.numWonShortCons++; //count how many won, and use this as bound later
if(cb){ progBar+=offset; cb(int(progBar),"Short consensus..."); }
}
res.shortConsTime = timer.elapsed();
if(param.log) param.log(3,"Short consensus performed in %i msec.", res.shortConsTime);
if(param.log) param.log(3,"%i short consensus performed in %i msec.",(param.maxNumShortConsensus<int(candidates->size()))? param.maxNumShortConsensus : candidates->size(), res.shortConsTime);
//sort candidates by short consensus
sort(candidates->begin(), candidates->end(), CandidateType::SortByScore);
@ -591,8 +601,7 @@ for(int i=0; i<50;i++)if(param.log) param.log(3,"%i spd %.2f.", i,(*candidates)[
consParam.samples=param.fullConsensusSamples;
consParam.threshold = param.consOffset*param.overlap/100.0f;
consParam.bestScore = bestConsensus;
int consensus = cons.Check(consParam); //compute full consensus
if(param.log) param.log(3,"%i short cons %i.", j,consensus);
int consensus = cons.Check(consParam); //compute full consensus
ResetTransformation(mMov, oldTr); //restore old tranformation
if(consensus >= cons_succ) res.numWonFullCons++;
@ -612,7 +621,7 @@ for(int i=0; i<50;i++)if(param.log) param.log(3,"%i spd %.2f.", i,(*candidates)[
}
res.fullConsTime = timer.elapsed();
res.totalTime = tot_timer.elapsed();
if(param.log) param.log(3,"Full consensus performed in %i msec.", res.fullConsTime);
if(param.log) param.log(3,"%i full consensus performed in %i msec.", (param.maxNumFullConsensus<res.numWonShortCons)? param.maxNumFullConsensus : res.numWonShortCons, res.fullConsTime);
//if flag 'points' is checked, clear old picked points and save the new points
if(param.pickPoints){
@ -780,27 +789,23 @@ for(int i=0; i<50;i++)if(param.log) param.log(3,"%i spd %.2f.", i,(*candidates)[
return 0;
}
static int Matching(vector<FEATURE_TYPE*>& vecFFix, vector<FEATURE_TYPE*>& vecFMov, ANNkd_tree* kdTree, FEATURE_TYPE** base, vector<CandidateType>& candidates, Parameters& param, CallBackPos *cb=NULL)
static int Matching(vector<FEATURE_TYPE*>& vecFFix, vector<FEATURE_TYPE*>& vecFMov, ANNkd_tree* kdTree, FEATURE_TYPE** base, vector<vector<FeatureType*> >& matches, Parameters& param, CallBackPos *cb=NULL)
{
float pBar = 0, offset = 100.0f/param.nBase; //used for progresss bar callback
if(cb) cb(0, "Matching...");
assert(param.k<=int(vecFFix.size())); //not enough features in kdtree to pick k neighboors
//compute needed params
float errDist = param.mutualErrDist*(param.mMovBBoxDiag/100.0f);
assert(param.k<=int(vecFFix.size())); //not enough features in kdtree to pick k neighbors
assert((int)vecFFix.size()>=param.nBase);
assert(matches.size()==0); //matches vectors have to be provided empty
//fill fqueryPts with feature's descriptions in base
ANNpointArray fqueryPts;
FeatureAlignment::SetupKDTreeQuery(base, param.nBase, &fqueryPts, FeatureType::getFeatureDimension());
//additional variables needed
ANNidxArray fnnIdx = new ANNidx[param.k]; // allocate near neigh indices
ANNidxArray fnnIdx = new ANNidx[param.k]; // allocate near neigh indices
ANNdistArray fdists = new ANNdist[param.k]; // allocate near neigh dists
vector<vector<FeatureType*>* >* matchedVec = new vector<vector<FeatureType*>* >();
vector<FeatureType*> neighbors;
//foreach feature in the base find the best matching using fkdTree
for(int i = 0; i < param.nBase; i++)
{
@ -808,30 +813,30 @@ for(int i=0; i<50;i++)if(param.log) param.log(3,"%i spd %.2f.", i,(*candidates)[
assert(fdists[0]!=ANN_DIST_INF); //if this check fails, it means that no feature have been found!
vector<FeatureType*>* matches = new vector<FeatureType*>();
for(int j=0; j<param.k; j++) matches->push_back(vecFFix[fnnIdx[j]]); //store all features
matchedVec->push_back(matches);
for(int j=0; j<param.k; j++) neighbors.push_back(vecFFix[fnnIdx[j]]); //store all features
matches.push_back(neighbors); //copy neighbors vec into matches vec
neighbors.clear(); //make neighbors vec ready for another iteration
if(cb){ pBar+=offset; cb((int)pBar, "Matching..."); }
}
assert(int(matchedVec->size())==param.nBase);
//branch and bound
int* curSolution = new int[param.nBase];
for(int i=0; i<param.nBase; i++) curSolution[i] = 0; //initialization
FeatureAlignment::Match(base, *matchedVec, param.nBase, 0, curSolution, candidates, errDist);
assert(int(matches.size())==param.nBase);
//Cleaning ANN structures
FeatureAlignment::CleanKDTree(NULL, NULL, fqueryPts, fnnIdx, fdists, false);
//Cleaning matching structures
for(typename vector<vector<FeatureType*>* >::iterator it=matchedVec->begin(); it!=matchedVec->end(); it++){
if(*it!=NULL){ delete *it; *it = NULL; }
}
delete matchedVec; matchedVec = NULL;
return 0;
}
static int BranchAndBound(FEATURE_TYPE** base, vector<vector<FeatureType*> >& matches, vector<CandidateType>& candidates, Parameters& param)
{
//compute needed params
float errDist = param.mutualErrDist*(param.mMovBBoxDiag/100.0f);
//branch and bound
int curSolution[param.nBase];
for(int i=0; i<param.nBase; i++) curSolution[i] = 0; //initialization
FeatureAlignment::Match(base, matches, param.nBase, 0, curSolution, candidates, errDist);
return 0;
}
@ -940,34 +945,34 @@ for(int i=0; i<50;i++)if(param.log) param.log(3,"%i spd %.2f.", i,(*candidates)[
}
}
static void Match(FEATURE_TYPE** base, vector<vector<FEATURE_TYPE*>* >& matchedVec, int nBase, int level, int curSolution[], vector<CandidateType>& candidates, float errDist, CallBackPos *cb = NULL)
static void Match(FEATURE_TYPE** base, vector<vector<FEATURE_TYPE*> >& matches, int nBase, int level, int curSolution[], vector<CandidateType>& candidates, float errDist, CallBackPos *cb = NULL)
{
assert(level<nBase);
for(unsigned int j=0; j<matchedVec[level]->size(); j++){
for(unsigned int j=0; j<matches[level].size(); j++){
curSolution[level] = j;
if(MatchSolution(base, matchedVec, level, curSolution, errDist)){
if(MatchSolution(base, matches, level, curSolution, errDist)){
if(level==nBase-1){
FeatureType** solution = new FeatureType*[nBase];
for(int h=0; h<nBase; h++){
solution[h] = (*(matchedVec[h]))[curSolution[h]];
solution[h] = matches[h][curSolution[h]];
}
candidates.push_back(CandidateType(base,solution));
}
else
Match(base, matchedVec, nBase, level+1, curSolution, candidates, errDist);
Match(base, matches, nBase, level+1, curSolution, candidates, errDist);
}
}
curSolution[level] = 0;
}
static bool MatchSolution(FEATURE_TYPE** base, vector<vector<FEATURE_TYPE*>* >& matchedVec, int level, int curSolution[], float errDist)
static bool MatchSolution(FEATURE_TYPE** base, vector<vector<FEATURE_TYPE*> >& matches, int level, int curSolution[], float errDist)
{
if (level==0) return true;
for(int j=0; j<level; j++){
float distF = vcg::Distance(base[level]->pos, base[j]->pos);
float distM = vcg::Distance((*(matchedVec[level]))[curSolution[level]]->pos, (*(matchedVec[j]))[curSolution[j]]->pos);
float distF = Distance(base[level]->pos, base[j]->pos);
float distM = Distance(matches[level][curSolution[level]]->pos, matches[j][curSolution[j]]->pos);
if( math::Abs(distF-distM)>errDist) return false;
}
return true;

View File

@ -200,7 +200,7 @@ void FilterFeatureAlignment::initParameterSet(QAction *a, MeshDocument& md, Filt
par.addEnum("featureType", 0, l,"Feature type:", "The feature that you want to compute for the current mesh.");
par.addMesh("mFix", 0, "Fix mesh:", "The mesh that stays still and grow large after alignment.");
par.addMesh("mMov", 1, "Move mesh:", "The mesh that moves to fit Fix Mesh.");
par.addInt("ransacIter", 5000, "Iterations:", "Number of iterations of the RANSAC algorithm. Greater values provides a greater success probability but requires more time.");
par.addInt("ransacIter", 500, "Iterations:", "Number of iterations of the RANSAC algorithm. Greater values provides a greater success probability but requires more time.");
par.addFloat("overlap", 75.0, "Overlap:", "A measure, expressed in percentage, of how much Move Mesh overlaps with Fix Mesh. It is very important to provide an actual esteem: lower values can produce false positive results or too rough alignments; higher values produce a small success probability and no alignements at all.");
par.addFloat("consensusDist", 2, "Consensus distance:","Consensus distance expressed in percentage of Move Mesh bounding box diagonal. It states how close two verteces must be to be in consensus.");
par.addInt("k", 75, "Number of neighboors:", "Number of neighboor feature points picked by kNN search during matching. Greater values produce a greater success probability but make the alignment process slower.");
@ -211,6 +211,7 @@ void FilterFeatureAlignment::initParameterSet(QAction *a, MeshDocument& md, Filt
{
QStringList l;
l << "GMSmooth curvature"
<< "APSS curvature"
<< "RGB";
par.addEnum("featureType", 0, l,"Feature type:", "The feature that you want to compute for the current mesh.");
par.addMesh("mFix", 0, "Fix mesh:", "The mesh that stays still and grow large after alignment.");
@ -219,9 +220,9 @@ void FilterFeatureAlignment::initParameterSet(QAction *a, MeshDocument& md, Filt
par.addFloat("consensusDist", 2, "Consensus distance:","Consensus distance expressed in percentage of Move Mesh bounding box diagonal. It states how close two verteces must be to be in consensus.");
par.addInt("k", 75, "Number of neighboors:", "Number of neighboor feature points picked by kNN search during matching. Greater values produce a greater success probability but make the alignment process slower.");
par.addInt("trials", 100, "Trials:", "How many times the alignment process is repeated with the same amount of RANSAC iterations.");
par.addInt("from", 1000, "From iteration:", "Number of RANSAC iteration used to perform the first battery of alignments.");
par.addInt("to", 5000, "To iteration:", "Number of RANSAC iteration over which no more alignments are performed.");
par.addInt("step", 1000, "Step:", "Step used to increment RANSAC iterations after that the specified number of attempts has been done.");
par.addInt("from", 100, "From iteration:", "Number of RANSAC iteration used to perform the first battery of alignments.");
par.addInt("to", 1000, "To iteration:", "Number of RANSAC iteration over which no more alignments are performed.");
par.addInt("step", 100, "Step:", "Step used to increment RANSAC iterations after that the specified number of attempts has been done.");
break;
}
default: assert(0);
@ -480,6 +481,15 @@ bool FilterFeatureAlignment::applyFilter(QAction *filter, MeshDocument &md, Filt
return logResult<AlignerType>(ID(filter), res, errorMessage);
}
case 1:{
typedef APSSCurvatureFeature<MeshType, 3> FeatureType; //define needed typedef FeatureType
typedef FeatureAlignment<MeshType, FeatureType> AlignerType; //define the Aligner class
typedef AlignerType::Result ResultType;
AlignerType::Parameters alignerParam(mFix->cm, mMov->cm);
setAlignmentParameters<AlignerType>(mFix->cm, mMov->cm, par, alignerParam);
ResultType res = RansacDiagramOperation<AlignerType>(*mFix, *mMov, alignerParam, trials, from, to, step, cb);
return logResult<AlignerType>(ID(filter), res, errorMessage);
}
case 2:{
typedef FeatureRGB<MeshType, 3> FeatureType; //define needed typedef FeatureType
typedef FeatureAlignment<MeshType, FeatureType> AlignerType; //define the Aligner class
typedef AlignerType::Result ResultType;
@ -550,6 +560,7 @@ typename ALIGNER_TYPE::Result FilterFeatureAlignment::MatchingOperation(MeshMode
//create vectors to hold tuples of bases and matches
vector<FeatureType**>* baseVec = new vector<FeatureType**>();
vector<vector<FeatureType*> > matches;
vector<CandidateType>* candidates = new vector<CandidateType>();
AlignerType aligner;
@ -559,8 +570,8 @@ typename ALIGNER_TYPE::Result FilterFeatureAlignment::MatchingOperation(MeshMode
//execute matching procedure with requested parameters;
int errCode = AlignerType::SelectBase(*(aligner.vecFMov),*baseVec,param);
if(errCode){ AlignerType::setError(errCode, res); return res; }
errCode = AlignerType::Matching(*(aligner.vecFFix), *(aligner.vecFMov), aligner.fkdTree, (*baseVec)[baseVec->size()-1], *candidates, param, cb);
if(errCode){ AlignerType::setError(errCode, res); return res; }
errCode = AlignerType::Matching(*(aligner.vecFFix), *(aligner.vecFMov), aligner.fkdTree, (*baseVec)[baseVec->size()-1], matches, param, cb);
errCode = AlignerType::BranchAndBound((*baseVec)[baseVec->size()-1], matches, *candidates, param);
res.numMatches = candidates->size(); //store the numeber of matches found
@ -590,6 +601,7 @@ typename ALIGNER_TYPE::Result FilterFeatureAlignment::RigidTransformationOperati
//create vectors to hold tuples of bases and matches
vector<FeatureType**>* baseVec = new vector<FeatureType**>();
vector<vector<FeatureType*> > matches;
vector<CandidateType>* candidates = new vector<CandidateType>();
AlignerType aligner;
@ -599,8 +611,8 @@ typename ALIGNER_TYPE::Result FilterFeatureAlignment::RigidTransformationOperati
//execute matching procedure with requested parameters;
int errCode = AlignerType::SelectBase(*(aligner.vecFMov),*baseVec,param);
if(errCode){ AlignerType::setError(errCode, res); return res; }
errCode = AlignerType::Matching(*(aligner.vecFFix), *(aligner.vecFMov), aligner.fkdTree, (*baseVec)[baseVec->size()-1], *candidates, param, cb);
if(errCode){ AlignerType::setError(errCode, res); return res; }
errCode = AlignerType::Matching(*(aligner.vecFFix), *(aligner.vecFMov), aligner.fkdTree, (*baseVec)[baseVec->size()-1], matches, param, cb);
errCode = AlignerType::BranchAndBound((*baseVec)[baseVec->size()-1], matches, *candidates, param);
res.numMatches = candidates->size(); //store the numeber of matches found
assert(baseVec->size()==1); //now baseVec must hold exactly one base of features