TexturedObjectRecognition.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package VisionX::Component
19  * @author Kai Welke (welke at kit dot edu)
20  * @date 2013
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
26 
27 // RobotState
30 
31 // MemoryX
35 
36 // IVT
37 #include <Calibration/Calibration.h>
38 
39 // IVTRecognition
40 #include <TexturedRecognition/TexturedRecognition.h>
41 #include <TexturedRecognition/TexturedObjectDatabase.h>
42 #include <TexturedRecognition/TexturedFeatureSet.h>
43 
44 using namespace armarx;
45 using namespace visionx;
46 using namespace memoryx;
47 using namespace memoryx::EntityWrappers;
48 
49 
50 bool TexturedObjectRecognition::initRecognizer()
51 {
52  float SIFTThreshold = getProperty<float>("SIFTThreshold").getValue();
53 
54  texturedRecognition = new CTexturedRecognition(getImageFormat().dimension.width, getImageFormat().dimension.height, SIFTThreshold);
55  texturedRecognition->SetVerbose(true);
56  texturedRecognition->SetStereo(true);
57  texturedRecognition->SetQualityThreshold(getProperty<float>("QualityThreshold").getValue());
58  texturedRecognition->SetRecognitionThresholds(getProperty<int>("nMinValidFeatures").getValue(), getProperty<float>("MaxError").getValue());
59 
60 
61  Eigen::Vector3f minPoint = getProperty<Eigen::Vector3f>("MinPoint").getValue();
62  Eigen::Vector3f maxPoint = getProperty<Eigen::Vector3f>("MaxPoint").getValue();
63 
64  Math3d::SetVec(validResultBoundingBoxMin, minPoint(0), minPoint(1), minPoint(2));
65  Math3d::SetVec(validResultBoundingBoxMax, maxPoint(0), maxPoint(1), maxPoint(2));
66 
67 
68  correlationWindowSize = getProperty<int>("StereoCorrelationWindowSize").getValue();
69  correlationThreshold = getProperty<float>("StereoCorrelationThreshold").getValue();
70 
71  texturedRecognition->GetObjectDatabase()->InitCameraParameters(getStereoCalibration(), true);
72  texturedRecognition->GetObjectDatabase()->SetCorrelationParameters(correlationWindowSize, minPoint(2), maxPoint(2), correlationThreshold);
73 
74  return true;
75 }
76 
77 bool TexturedObjectRecognition::addObjectClass(const memoryx::EntityPtr& objectClassEntity, const memoryx::GridFileManagerPtr& fileManager)
78 {
79  TexturedRecognitionWrapperPtr recognitionWrapper = objectClassEntity->addWrapper(new TexturedRecognitionWrapper(fileManager));
80  std::string fileName = recognitionWrapper->getFeatureFile();
81 
82  if (fileName != "")
83  {
84  std::string className = objectClassEntity->getName();
85 
86  if (texturedRecognition->GetObjectDatabase()->AddClass(className, fileName))
87  {
88  return true;
89  }
90  }
91  else
92  {
93  ARMARX_WARNING_S << "No descriptor file defined for object " << objectClassEntity->getName();
94  }
95 
96  return false;
97 }
98 
99 memoryx::ObjectLocalizationResultList TexturedObjectRecognition::localizeObjectClasses(const std::vector<std::string>& objectClassNames, CByteImage** cameraImages, armarx::MetaInfoSizeBasePtr imageMetaInfo, CByteImage** resultImages)
100 {
101  std::string allObjectNames;
102 
103  for (size_t i = 0; i < objectClassNames.size(); i++)
104  {
105  allObjectNames.append(objectClassNames.at(i));
106  allObjectNames.append(" ");
107  }
108 
109  ARMARX_DEBUG_S << "Localizing " << allObjectNames;
110 
111  // result images
112  CByteImage** tmpResultImages = getResultImagesEnabled() ? resultImages : NULL;
113 
114  if (objectClassNames.size() == 1)
115  {
116  texturedRecognition->DoRecognitionSingleObject(cameraImages, tmpResultImages, objectClassNames.at(0).c_str(), true, 50, getImagesAreUndistorted());
117  }
118  else
119  {
120  // TODO: multiple is not implemented so searching for all classes
121  texturedRecognition->DoRecognition(cameraImages, tmpResultImages, true, 50, getImagesAreUndistorted());
122  }
123 
124  Object3DList objectList = texturedRecognition->GetObject3DList();
125 
126  ARMARX_DEBUG_S << "Localized " << objectList.size() << " objects";
127  const auto agentName = getProperty<std::string>("AgentName").getValue();
128 
129  memoryx::ObjectLocalizationResultList resultList;
130 
131  for (Object3DList::iterator iter = objectList.begin() ; iter < objectList.end() ; iter++)
132  {
133  // assure instance belongs to queried class
134  bool queriedClass = (std::find(objectClassNames.begin(), objectClassNames.end(), iter->sName) != objectClassNames.end());
135 
136  if (iter->localizationValid && queriedClass)
137  {
138  float x = iter->pose.translation.x;
139  float y = iter->pose.translation.y;
140  float z = iter->pose.translation.z;
141 
142  StringVariantBaseMap mapValues;
143  mapValues["x"] = new Variant(x);
144  mapValues["y"] = new Variant(y);
145  mapValues["z"] = new Variant(z);
146  mapValues["name"] = new Variant(iter->sName);
147  mapValues["sequence"] = new Variant(seq++);
148  mapValues["timestamp"] = new Variant(imageMetaInfo->timeProvided / 1000.0 / 1000.0);
149  debugObserver->setDebugChannel("ObjectRecognition", mapValues);
150 
151 
152  // only accept realistic positions
153  if (x > validResultBoundingBoxMin.x && y > validResultBoundingBoxMin.y && z > validResultBoundingBoxMin.z &&
154  x < validResultBoundingBoxMax.x && y < validResultBoundingBoxMax.y && z < validResultBoundingBoxMax.z)
155  {
156  // assemble result
157  memoryx::ObjectLocalizationResult result;
158 
159  // position and orientation
160  Eigen::Vector3f position(x, y, z);
161  Eigen::Matrix3f orientation;
162  orientation << iter->pose.rotation.r1, iter->pose.rotation.r2, iter->pose.rotation.r3,
163  iter->pose.rotation.r4, iter->pose.rotation.r5, iter->pose.rotation.r6,
164  iter->pose.rotation.r7, iter->pose.rotation.r8, iter->pose.rotation.r9;
165 
166  result.position = new armarx::FramedPosition(position, referenceFrameName, agentName);
167  result.orientation = new armarx::FramedOrientation(orientation, referenceFrameName, agentName);
168 
169  // calculate recognition certainty
170  result.recognitionCertainty = 0.5f + 0.5f * calculateRecognitionCertainty(iter->sName, *iter);
171 
172  // calculate position uncertainty
173  memoryx::MultivariateNormalDistributionPtr posUncertainty = calculateLocalizationUncertainty(position);
174  Eigen::MatrixXf cov = posUncertainty->toEigenCovariance();
175  cov *= 4.0f / pow(result.recognitionCertainty, 4);
176  result.positionNoise = memoryx::MultivariateNormalDistributionPtr(new memoryx::MultivariateNormalDistribution(posUncertainty->toEigenMean(), cov));
177 
178  result.objectClassName = iter->sName;
179  result.timeStamp = new TimestampVariant(imageMetaInfo->timeProvided);
180 
181  resultList.push_back(result);
182 
183  FramedPose objectPose(orientation, position, referenceFrameName, agentName);
184  ARMARX_DEBUG_S << "Localized object at pose: " << objectPose;
185  }
186  else
187  {
188  ARMARX_DEBUG_S << "Refused unrealistic localization at position: " << x << " " << y << " " << z;
189  }
190  }
191  }
192 
193  return resultList;
194 }
195 
196 
197 
198 float TexturedObjectRecognition::calculateRecognitionCertainty(const std::string& objectClassName, const Object3DEntry& entry)
199 {
200  //**************************************************************************************************
201  // calculate recognition certainty (ask David Schiebener about that part !!!!)
202  // quality: mean of pixel error
203  // quality2: found number of feature correspondences
204  //**************************************************************************************************
205  // retrieve number of known features for this object
206  int objectIndex = -1;
207  int n = texturedRecognition->GetObjectDatabase()->GetSize();
208 
209  for (int i = 0; i < n; i++)
210  {
211  if (objectClassName.compare(texturedRecognition->GetObjectDatabase()->GetFeatureSet(i)->GetName()) == 0)
212  {
213  objectIndex = i;
214  break;
215  }
216  }
217 
218  if (objectIndex == -1)
219  {
220  return 0.0f;
221  }
222 
223  int numberObjectFeatures = texturedRecognition->GetObjectDatabase()->GetFeatureSet(objectIndex)->GetSize();
224 
225  // rate with 1 if pixel error <= 0.7, rate with 1/e if error = 2.2
226  float temp = (entry.quality > 0.7f) ? entry.quality - 0.7f : 0;
227  float ratingPixelError = expf(-(4.0f / 9.0f) * temp * temp);
228  ratingPixelError = 0.15f + 0.7f * ratingPixelError;
229 
230  // rate with 0.15 if 10 matched features, with 0.85 if 30 matched features
231  temp = 0.1f * (entry.quality2 - 20.0f);
232  float ratingMatchedFeaturesAbsolute = 0.5f + 0.5f * (temp / sqrtf(1.0f + temp * temp));
233  ratingMatchedFeaturesAbsolute = 0.15f + 0.7f * ratingMatchedFeaturesAbsolute;
234 
235  // rate with 1 if number of matched features >= 0.15 * total number of features
236  if (numberObjectFeatures > 300)
237  {
238  numberObjectFeatures = 300;
239  }
240 
241  temp = entry.quality2;
242 
243  if (temp > (float)numberObjectFeatures)
244  {
245  temp = (float)numberObjectFeatures;
246  }
247 
248  float ratingMatchedFeaturesRelative = temp / (0.15f * (float)numberObjectFeatures);
249  ratingMatchedFeaturesRelative = (ratingMatchedFeaturesRelative > 1.0f) ? 1.0f : ratingMatchedFeaturesRelative;
250  ratingMatchedFeaturesRelative = 0.15f + 0.7f * ratingMatchedFeaturesRelative;
251 
252  // division is no problem because fRatingPixelError*fRatingMatchedFeaturesAbsolute*fRatingMatchedFeaturesRelative > 0
253  float recognitionCertainty = (ratingPixelError * ratingMatchedFeaturesAbsolute * ratingMatchedFeaturesRelative)
254  / ((ratingPixelError * ratingMatchedFeaturesAbsolute * ratingMatchedFeaturesRelative)
255  + ((1 - ratingPixelError) * (1 - ratingMatchedFeaturesAbsolute) * (1 - ratingMatchedFeaturesRelative)));
256 
257  return recognitionCertainty;
258 }
armarx::Variant
The Variant class is described here: Variants.
Definition: Variant.h:224
RemoteRobot.h
armarx::StringVariantBaseMap
std::map< std::string, VariantBasePtr > StringVariantBaseMap
Definition: ManagedIceObject.h:111
visionx
ArmarX headers.
Definition: OpenPoseStressTest.h:38
armarx::FramedPose
The FramedPose class.
Definition: FramedPose.h:258
Pose.h
armarx::TimestampVariant
Definition: TimestampVariant.h:54
memoryx
VirtualRobot headers.
Definition: CommonPlacesTester.cpp:48
ObjectRecognitionWrapper.h
IceInternal::Handle
Definition: forward_declarations.h:8
ARMARX_DEBUG_S
#define ARMARX_DEBUG_S
Definition: Logging.h:198
memoryx::MultivariateNormalDistribution
The MultivariateNormalDistribution class.
Definition: ProbabilityMeasures.h:236
TimestampVariant.h
memoryx::EntityWrappers::TexturedRecognitionWrapper
TexturedRecognitionWrapper offers a simplified access to the data of an object class or instance rela...
Definition: ObjectRecognitionWrapper.h:66
MemoryXCoreObjectFactories.h
ARMARX_WARNING_S
#define ARMARX_WARNING_S
Definition: Logging.h:206
memoryx::MultivariateNormalDistributionPtr
IceInternal::Handle< MultivariateNormalDistribution > MultivariateNormalDistributionPtr
Definition: ProbabilityMeasures.h:231
TexturedObjectRecognition.h
GfxTL::Matrix3f
MatrixXX< 3, 3, float > Matrix3f
Definition: MatrixXX.h:600
memoryx::EntityWrappers
Definition: AbstractEntityWrapper.cpp:28
armarx::VariantType::FramedOrientation
const VariantTypeId FramedOrientation
Definition: FramedPose.h:40
float
#define float
Definition: 16_Level.h:22
memoryx::GridFileManagerPtr
std::shared_ptr< GridFileManager > GridFileManagerPtr
Definition: AbstractEntityWrapper.h:32
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:39
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28