Recognizer.cpp
Go to the documentation of this file.
1 
18 //Global includes
19 #include <map>
20 #include <set>
21 #include <vector>
22 #include <list>
23 #include <iostream>
24 #include <sstream>
25 
26 //Local includes
27 #include "Recognizer.hpp"
29 #include "VotedPose.hpp"
30 #include "VotingSpace.hpp"
32 
33 #define SAME_REF_AND_RECOG_RESULT_CONFIDENCE_THRESH 0.01
34 
35 namespace ISM {
36 
37  Recognizer::Recognizer(const std::string& dbfilename, double bin_size, double maxProjectionAngleDeviation, bool enabledSelfVoteCheck, int raterType) :
38  bin_size(bin_size), maxProjectionAngleDeviation(maxProjectionAngleDeviation), enabledSelfVoteCheck(enabledSelfVoteCheck), mRaterType(raterType)
39  {
40  this->tableHelper = TableHelperPtr(new TableHelper(dbfilename));
41  this->objectTypes = this->tableHelper->getObjectTypes();
42  this->voteSpecifiersPerObject = this->tableHelper->getVoteSpecifiersForObjectTypes(this->objectTypes);
43  this->getPatternDefinitions();
45  }
46 
47  const std::vector<RecognitionResultPtr> Recognizer::recognizePattern(const ObjectSetPtr& objectSet,
48  const double filterThreshold, const int resultsPerPattern, const std::string targetPatternName) {
49  this->inputSet = ObjectSetPtr( new ObjectSet(*objectSet));
50  this->votingCache.clear();
51  this->ismResults.clear();
52 
53  //Scene recognition is an iterative process in which isms in trees are evaluated according to tree height.
54  TreeHeightToPatternName::reverse_iterator treeHeightIt;
55  //Trees are evaluated starting at the leaf with max tree height in the db, going until the roots of the trees.
56  for(treeHeightIt = patternPerTreeHeight.rbegin(); treeHeightIt != patternPerTreeHeight.rend(); treeHeightIt++) {
57  //Get voted poses (also from cache) for all objects in all isms.
59  //Search for RecognitionResults in all sub-ISMs at the current tree height
60  this->fillAndEvalVotingSpaceAtTreeHeight(treeHeightIt->first);
61 
62  }
63 
64  //Build up scene recognition results for ism trees from RecognitionResults of single sub-ISMs in tree.
65  return this->assembleIsmTrees(this->ismResults, filterThreshold, resultsPerPattern, targetPatternName);
66 
67  }
68 
70  {
71 
72  //Delete old voting results from last iteration step, since pattern content might have changed.
73  patternToVotedPoses.clear();
74 
75  //Start calculating reference pose votes by going through all object estimated we got as input.
76  for (ObjectPtr& object : this->inputSet->objects) {
77 
78  //Just copy VotedPoses from voting cache if already existing for current object.
79  std::map<ObjectPtr, std::vector<VotedPosePtr> >::iterator cacheIt = votingCache.find(object);
80  if (cacheIt != votingCache.end()) {
81  std::vector<VotedPosePtr> votedPoses = (*cacheIt).second;
82  for (VotedPosePtr& v : votedPoses) {
83  std::string patternName = v->vote->patternName;
84  PatternNameToVotedPoses::iterator vmit = patternToVotedPoses.find(patternName);
85  if (vmit == patternToVotedPoses.end()) {
86  vmit = patternToVotedPoses.insert(std::make_pair(patternName, std::vector<VotedPosePtr>())).first;
87  }
88  (*vmit).second.push_back(v);
89  }
90  continue;
91  }
92 
93  //When object has no type (ignore_type==true), it votes for all object types.
94  std::set<std::string> types;
95  if (object->type == "")
96  {
97  types = this->objectTypes;
98  }
99  //Otherwise just for its own type.
100  else
101  {
102  types.insert(object->type);
103  }
104 
105  //Match input object estimates to votes from ism table according to type and id information.
106  for (const std::string& objectType : types)
107  {
108  //Get all vote specifiers for that object type.
109  std::vector<VoteSpecifierPtr> votes = this->voteSpecifiersPerObject[objectType];
110  for (VoteSpecifierPtr& vote : votes)
111  {
112  //Just use vote specifiers for matching ids or all votes for that type in case ignore_ids==true.
113  if (object->observedId == "" || object->observedId == vote->observedId)
114  {
115 
116  PatternPtr pattern = this->patternDefinitions[vote->patternName];
117  //Calculate reference pose vote for given combination of input object estimate and vote (relative pose).
118  PosePtr pose = this->calculatePoseFromVote(object->pose, vote);
119  if (patternToVotedPoses.find(vote->patternName) == patternToVotedPoses.end())
120  {
121  patternToVotedPoses[vote->patternName] = std::vector<VotedPosePtr>();
122  }
123  VotedPosePtr v(new VotedPose(pose, vote, object, object->weight, pattern->expectedMaxWeight));
124  patternToVotedPoses[vote->patternName].push_back(v);
125 
126  //Fill voting cache for the following iterations in iterative scene recognition.
127  std::map<ObjectPtr, std::vector<VotedPosePtr> >::iterator cacheIt = votingCache.find(object);
128  if (cacheIt == votingCache.end()) {
129  cacheIt = votingCache.insert(std::make_pair(object, std::vector<VotedPosePtr>())).first;
130  }
131 
132  (*cacheIt).second.push_back(v);
133 
134  }
135  }
136  }
137  }
138  }
139 
141  {
142 
144 
145  //Each ISM in a tree is treated as a separate pattern. Fetching all isms for all trees in the db at a given height.
146  for (std::string patternName : patternPerTreeHeight.at(treeHeight)) {
147 
148  PatternNameToVotedPoses::iterator votedPosesForCurrentPattern = patternToVotedPoses.find(patternName);
149  //We can only evaluate patterns for which object estimates have been acquired.
150  if(votedPosesForCurrentPattern == patternToVotedPoses.end())
151  continue;
152 
153  //patternToVotedPoses is a container for voted poses (reference pose estimates) of all isms in the db.
154  //Insert all votedPoses (reference pose votes) into voxelgrid to discretize search space.
155  VotingResultPtrs vsresults = vsPtr->fillAndEvalVotingSpace(votedPosesForCurrentPattern->second, enabledSelfVoteCheck);
156 
157  // Buffer VotingSpace for its visualization if request exists.
159  {
160 
161  votingSpaceBuffer = std::make_pair(patternName, vsPtr);
162 
163  //Create a second voting space to revent the first (which is to be visualized) from being cleared for the next considered ISM.
165  }
166 
167  //Convert results from each voxel grid element into single Recognition result from sub-ISM and extend input object set.
168  for (VotingResultPtr& vsres : vsresults) {
169  RecognitionResultPtr res(new RecognitionResult(patternName, vsres->referencePose,
170  vsres->matchingObjects, vsres->confidence,
171  vsres->summarizedVotes));
172 
173  //Replace recognition results of sub-ISMs at same reference-pose if their rating improved during this step in the loop.
174  int resIdx = this->resultAlreadyExisting(res);
175 
176  if(resIdx >= 0) {
177  if(this->ismResults[resIdx]->confidence >= res->confidence)
178  continue;
179  else
180  this->ismResults[resIdx] = res;
181  }
182 
183  else
184  this->ismResults.push_back(res);
185 
186  //Insert RecognitionResults of sub-ISMs in tree into input object set to propagate ratings though the tree (preparation of next voting iteration).
187  if (this->voteSpecifiersPerObject.find(res->patternName) != this->voteSpecifiersPerObject.end()) {
188  // if we have an object on record with a name that matches a pattern name
189  // treat the referencePose as a new object and repeat the recognition to capture subscenes
190  ObjectPtr refObj(new Object(res->patternName, res->referencePose));
191  //Reference object confidence always corresponds to the confidence of the corresponding recognition result.
192  refObj->confidence = vsres->confidence;
193  //weight is the unnormalized confidence of this recognition result and used to calculate the confidence of potential recognition results in the next-heigher ism.
194  double weightSum = 0;
195  for (ObjectPtr& obj : vsres->matchingObjects->objects)
196  {
197  weightSum += obj->weight;
198  }
199  refObj->weight = weightSum;
200  //Look if we add a new object to the input object set or if we might replace an object estimate by an instance with a better confidence.
201  int inSetIdx = this->objectAlreadyInSet(refObj);
202  if (inSetIdx >= 0) {
203  ObjectPtr setObj = this->inputSet->objects[inSetIdx];
204  if (setObj->confidence < refObj->confidence || setObj->weight
205  < refObj->weight) {
206 
207  this->inputSet->objects.erase(this->inputSet->objects.begin() + inSetIdx);
208  inSetIdx = -1;
209  }
210  }
211  if (inSetIdx < 0)
212  this->inputSet->insert(refObj);
213 
214  }
215  }
216  }
217 
218  }
219 
221  for (size_t i = 0; i < this->ismResults.size(); i++)
222  {
223  if (this->ismResults[i]->patternName == res->patternName
224  && GeometryHelper::poseEqual(this->ismResults[i]->referencePose, res->referencePose))
225  {
226  return i;
227  }
228  }
229  return -1;
230  }
231 
233  for (size_t i = 0; i < this->inputSet->objects.size(); i++) {
234  ISM::ObjectPtr setObj = this->inputSet->objects[i];
235  if (setObj->type == o->type && setObj->observedId == o->observedId
236  && GeometryHelper::poseEqual(setObj->pose, o->pose)) {
237  return i;
238  }
239  }
240  return -1;
241  }
242 
244  PointPtr referencePoint = GeometryHelper::applyQuatAndRadiusToPose(pose, vote->objectToRefQuat, vote->radius);
245  return GeometryHelper::getReferencePose(pose, referencePoint, vote->objectToRefPoseQuat);
246  }
247 
249 
250  if(this->voteSpecifiersPerObject.empty())
251  this->voteSpecifiersPerObject = this->tableHelper->getVoteSpecifiersForObjectTypes(this->objectTypes);
252 
253  typedef std::pair<std::string, std::vector<VoteSpecifierPtr> > mapItemType;
254  std::set<std::string> patternNames;
255  for(mapItemType item : this->voteSpecifiersPerObject) {
256  for(VoteSpecifierPtr vote : item.second) {
257  patternNames.insert(vote->patternName);
258  }
259  }
260  this->patternDefinitions = this->tableHelper->getPatternDefinitionsByName(patternNames);
261  }
262 
264 
265  if(this->voteSpecifiersPerObject.empty())
266  this->voteSpecifiersPerObject = this->tableHelper->getVoteSpecifiersForObjectTypes(this->objectTypes);
267 
268  if(!this->patternPerTreeHeight.empty())
269  this->patternPerTreeHeight.clear();
270 
271  //Using just a set over object types since subpatterns have no id.
272  std::map<std::string, std::set<std::string> > patternToSubpatterns;
273  //All ISM that are at the roots of the ISM trees in the database.
274  std::vector<std::string> topLevelPatterns;
275 
276  //Construct mapping from pattern to subpatterns for each ISM in database.
277  typedef std::pair<std::string, std::vector<VoteSpecifierPtr> > mapItemType;
278  for(mapItemType item : this->voteSpecifiersPerObject) {
279  for(VoteSpecifierPtr vote : item.second) {
280 
281  std::map<std::string, std::set<std::string> >::iterator patternIt;
282  patternIt = patternToSubpatterns.find(vote->patternName);
283 
284  //Add additional subpattern to already known pattern.
285  if(patternIt != patternToSubpatterns.end()){
286  //The object voting is no subpattern of any ism, so we add nothing.
287  if(vote->objectType.find("_sub") == std::string::npos)
288  continue;
289  else
290  patternIt->second.insert(vote->objectType);
291  }
292  //Create a new mapping from pattern to subpattern with the current <pattern, subpattern> pair.
293  else{
294  std::set<std::string> newSubpatterns;
295  //Add an empty set, if we encounter a real object instead of a subpattern.
296  if(vote->objectType.find("_sub") != std::string::npos)
297  newSubpatterns.insert(vote->objectType);
298  patternToSubpatterns.insert(std::pair<std::string, std::set<std::string> >(vote->patternName, newSubpatterns));
299  }
300 
301  }
302  }
303 
304  //Go through all mappings from pattern to subpatterns to find root patterns in db.
305  for(auto& valuePair : patternToSubpatterns)
306  if (valuePair.first.find("_sub") == std::string::npos)
307  topLevelPatterns.push_back(valuePair.first);
308 
309  //Pattern which are to be inserted in the height to patternMapping
310  std::list<std::pair<std::string, unsigned int> > breadthFirstPatternQueue;
311 
312  //First all top level ism need to be processed.
313  for(std::string currentTopLevelPattern : topLevelPatterns)
314  breadthFirstPatternQueue.push_back(std::pair<std::string, unsigned int>(currentTopLevelPattern, 0));
315 
316  //Bread first search on pattern mappings to arrange patterns according to their height in any of the ISM trees in the db.
317  while(breadthFirstPatternQueue.size()) {
318 
319  //Get next item to be added to height mapping.
320  std::pair<std::string, unsigned int> patternAtHeight = breadthFirstPatternQueue.front();
321  //Delete item from queue that going to be added to the height mapping if not already done.
322  breadthFirstPatternQueue.pop_front();
323 
324  TreeHeightToPatternName::iterator heightMappingIt;
325 
326  //Are there any mappings for the height of the current pattern?
327  heightMappingIt = patternPerTreeHeight.find(patternAtHeight.second);
328  if(heightMappingIt != patternPerTreeHeight.end())
329  //Height already known in mapping, just adding Pattern.
330  heightMappingIt->second.insert(patternAtHeight.first);
331  //Create mapping from height to pattern.
332  else{
333 
334  std::set<std::string> newPattern;
335  newPattern.insert(patternAtHeight.first);
336  patternPerTreeHeight.insert(std::pair<unsigned int,std::set<std::string> >(patternAtHeight.second, newPattern));
337 
338  }
339 
340  //Get subpatterns of pattern that we added to height mapping.
341  std::map<std::string, std::set<std::string> >::iterator currentSubPatterns;
342  currentSubPatterns = patternToSubpatterns.find(patternAtHeight.first);
343  //Add all subpatterns to queue.
344  for(std::string subPattern : currentSubPatterns->second){
345 
346  //Add subpattern of current pattern to queue with its height.
347  breadthFirstPatternQueue.push_back(std::pair<std::string, unsigned int>(subPattern, patternAtHeight.second+1));
348 
349  }
350 
351  }
352 
353  }
354 
355  std::vector<RecognitionResultPtr> Recognizer::assembleIsmTrees(const std::vector<RecognitionResultPtr>& ismResults,
356  const double filterThreshold, const int resultsPerPattern, const std::string targetPatternName) {
357  std::map<std::string, std::vector<RecognitionResultPtr> > patternNameToResults;
358 
359  //Find root ism recognition results among recognition results for all isms in ism trees in database.
360  std::vector<RecognitionResultPtr> topLevelResults;
361  for (const RecognitionResultPtr& res : ismResults) {
362  if (res->patternName.find("_sub") == std::string::npos) {
363  if(targetPatternName.empty() || targetPatternName == res->patternName)
364  {
365  topLevelResults.push_back(res);
366  }
367  }
368  //Create map keys for all top-level pattern names present in recognition results.
369  std::map<std::string, std::vector<RecognitionResultPtr> >::iterator it = patternNameToResults.find(res->patternName);
370  if (it == patternNameToResults.end())
371  {
372  it = patternNameToResults.insert(std::make_pair(res->patternName, std::vector<RecognitionResultPtr>())).first;
373  }
374  (*it).second.push_back(res);
375  }
376 
377  //Sort recognition results for root isms according to patternName.
378  std::map<std::string, std::vector<RecognitionResultPtr> > patternNameToTopLevelResults;
379  for (RecognitionResultPtr& res : topLevelResults) {
380  std::map<std::string, std::vector<RecognitionResultPtr> >::iterator it = patternNameToTopLevelResults.find(res->patternName);
381  if (it == patternNameToTopLevelResults.end()) {
382  std::vector<RecognitionResultPtr> p;
383  p.push_back(res);
384  patternNameToTopLevelResults.insert(std::make_pair(res->patternName, p));
385  } else {
386  (*it).second.push_back(res);
387  }
388  }
389  std::vector<RecognitionResultPtr> ret;
390 
391  //sort results by confidence and gather the subpatterns for the requested number of results per pattern
392  for (const std::pair<std::string, std::vector<RecognitionResultPtr> >& patternPair : patternNameToTopLevelResults) {
393  std::vector<RecognitionResultPtr> rlist = patternPair.second;
394  //Sort results for a given pattern.
395  std::stable_sort(rlist.begin(), rlist.end(), [](const RecognitionResultPtr& o1, const RecognitionResultPtr& o2) {
396  return o1->confidence > o2->confidence;
397  });
398  //Make sure to only take the "n"-best recognition results for this pattern.
399  for (size_t i = 0; i < rlist.size() && (resultsPerPattern < 0 || (int)i < resultsPerPattern); i++) {
400  if (rlist[i]->confidence >= filterThreshold) {
401  RecognitionResultPtr r = rlist[i];
402  ret.push_back(r);
403  //Hang subpattern under currently considered recognition result of root ism.
404  r->subPatterns = Recognizer::getSubPatternsForResult(r, patternNameToResults);
405  } else {
406  break;
407  }
408  }
409  }
410  //Resort list of best recognition results for all patterns.
411  std::stable_sort(ret.begin(), ret.end(), [](const RecognitionResultPtr& o1, const RecognitionResultPtr& o2) {
412  return o1->confidence > o2->confidence;
413  });
414 
415  return ret;
416 
417  }
418 
419  std::vector<RecognitionResultPtr> Recognizer::getSubPatternsForResult(RecognitionResultPtr result,
420  std::map<std::string, std::vector<RecognitionResultPtr> > patternNameToResults) {
421  std::vector<RecognitionResultPtr> ret;
422  for (ObjectPtr& obj : result->recognizedSet->objects) {
423  std::map<std::string, std::vector<RecognitionResultPtr> >::iterator it = patternNameToResults.find(obj->type);
424  if (it == patternNameToResults.end()) {
425  continue;
426  }
427  for (RecognitionResultPtr& originalResult : (*it).second) {
428  PosePtr originalPose = originalResult->referencePose;
429  PosePtr currentPose = obj->pose;
430  //We link isms by searching pairs of reference objects and recognition results with identical poses and confidences.
431  if (GeometryHelper::poseEqual(currentPose, originalPose)
432  && fabs(obj->confidence - originalResult->confidence) < SAME_REF_AND_RECOG_RESULT_CONFIDENCE_THRESH) {
433  ret.push_back(originalResult);
434  break;
435  }
436  }
437  }
438  for (RecognitionResultPtr& subPattern : ret) {
439  subPattern->subPatterns = Recognizer::getSubPatternsForResult(subPattern, patternNameToResults);
440  }
441  return ret;
442  }
443 
444 }
445 
446 
PatternNameToVotedPoses patternToVotedPoses
Definition: Recognizer.hpp:57
void arrangePatternsAccordingToTreeHeight()
Definition: Recognizer.cpp:263
PatternNameToPatternMap patternDefinitions
Definition: Recognizer.hpp:52
static std::vector< RecognitionResultPtr > assembleIsmTrees(const std::vector< RecognitionResultPtr > &ismResults, const double filterThreshold, const int resultsPerPattern, const std::string targetPatternName)
Definition: Recognizer.cpp:355
const int mRaterType
Definition: Recognizer.hpp:62
ObjectSetPtr inputSet
Definition: Recognizer.hpp:40
TableHelperPtr tableHelper
Definition: Recognizer.hpp:38
boost::shared_ptr< Point > PointPtr
Definition: Point.hpp:45
static PointPtr applyQuatAndRadiusToPose(const PosePtr &pose, const QuaternionPtr &quat, double radius)
bool enabledSelfVoteCheck
Definition: Recognizer.hpp:59
std::string patternName
static std::vector< RecognitionResultPtr > getSubPatternsForResult(RecognitionResultPtr result, std::map< std::string, std::vector< RecognitionResultPtr > > patternNameToResults)
Definition: Recognizer.cpp:419
PatternNameAndVotingSpaceTuple votingSpaceBuffer
Definition: Recognizer.hpp:70
void calculateVotedPosesForAllObjects()
Definition: Recognizer.cpp:69
boost::shared_ptr< VotingResult > VotingResultPtr
Definition: typedef.hpp:37
boost::shared_ptr< TableHelper > TableHelperPtr
std::string patternForVotingSpaceViz
Definition: Recognizer.hpp:68
ObjectTypeToVoteMap voteSpecifiersPerObject
Definition: Recognizer.hpp:50
std::set< std::string > objectTypes
Definition: Recognizer.hpp:47
boost::shared_ptr< VotedPose > VotedPosePtr
Definition: typedef.hpp:31
std::map< ObjectPtr, std::vector< VotedPosePtr > > votingCache
Definition: Recognizer.hpp:66
PosePtr calculatePoseFromVote(const PosePtr &pose, const VoteSpecifierPtr &vote) const
Definition: Recognizer.cpp:243
boost::shared_ptr< Pattern > PatternPtr
Definition: Pattern.hpp:36
static bool poseEqual(const PosePtr &p1, const PosePtr &p2)
boost::shared_ptr< VoteSpecifier > VoteSpecifierPtr
std::vector< RecognitionResultPtr > ismResults
Definition: Recognizer.hpp:64
void getPatternDefinitions()
Definition: Recognizer.cpp:248
boost::shared_ptr< ObjectSet > ObjectSetPtr
Definition: ObjectSet.hpp:53
int objectAlreadyInSet(const ObjectPtr &o)
Definition: Recognizer.cpp:232
boost::shared_ptr< RecognitionResult > RecognitionResultPtr
int resultAlreadyExisting(const RecognitionResultPtr &res)
Definition: Recognizer.cpp:220
#define SAME_REF_AND_RECOG_RESULT_CONFIDENCE_THRESH
Definition: Recognizer.cpp:33
boost::shared_ptr< Pose > PosePtr
Definition: Pose.hpp:79
void fillAndEvalVotingSpaceAtTreeHeight(unsigned int treeHeight)
Definition: Recognizer.cpp:140
double maxProjectionAngleDeviation
Definition: Recognizer.hpp:44
std::vector< VotingResultPtr > VotingResultPtrs
Definition: typedef.hpp:60
const std::vector< RecognitionResultPtr > recognizePattern(const ObjectSetPtr &objectSet, const double filterThreshold=0.0, const int resultsPerPattern=-1, const std::string targetPatternName="")
Definition: Recognizer.cpp:47
static PosePtr getReferencePose(const PosePtr &source, const PointPtr &refPoint, const QuaternionPtr &objectToRefPoseQuat)
boost::shared_ptr< VotingSpace > VotingSpacePtr
Definition: typedef.hpp:34
this namespace contains all generally usable classes.
TreeHeightToPatternName patternPerTreeHeight
Definition: Recognizer.hpp:55
boost::shared_ptr< Object > ObjectPtr
Definition: Object.hpp:82
Recognizer(const std::string &dbfilename, double bin_size, double maxProjectionAngleDeviation, bool enabledSelfVoteCheck, int raterType=0)
Definition: Recognizer.cpp:37


asr_lib_ism
Author(s): Hanselmann Fabian, Heller Florian, Heizmann Heinrich, Kübler Marcel, Mehlhaus Jonas, Meißner Pascal, Qattan Mohamad, Reckling Reno, Stroh Daniel
autogenerated on Wed Jan 8 2020 04:02:40