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
33 
36 
37 // IVT
38 #include <Calibration/Calibration.h>
39 
40 // IVTRecognition
41 #include <TexturedRecognition/TexturedFeatureSet.h>
42 #include <TexturedRecognition/TexturedObjectDatabase.h>
43 #include <TexturedRecognition/TexturedRecognition.h>
44 
45 using namespace armarx;
46 using namespace visionx;
47 using namespace memoryx;
48 using namespace memoryx::EntityWrappers;
49 
50 bool
51 TexturedObjectRecognition::initRecognizer()
52 {
53  float SIFTThreshold = getProperty<float>("SIFTThreshold").getValue();
54 
55  texturedRecognition = new CTexturedRecognition(
56  getImageFormat().dimension.width, getImageFormat().dimension.height, SIFTThreshold);
57  texturedRecognition->SetVerbose(true);
58  texturedRecognition->SetStereo(true);
59  texturedRecognition->SetQualityThreshold(getProperty<float>("QualityThreshold").getValue());
60  texturedRecognition->SetRecognitionThresholds(getProperty<int>("nMinValidFeatures").getValue(),
61  getProperty<float>("MaxError").getValue());
62 
63 
64  Eigen::Vector3f minPoint = getProperty<Eigen::Vector3f>("MinPoint").getValue();
65  Eigen::Vector3f maxPoint = getProperty<Eigen::Vector3f>("MaxPoint").getValue();
66 
67  Math3d::SetVec(validResultBoundingBoxMin, minPoint(0), minPoint(1), minPoint(2));
68  Math3d::SetVec(validResultBoundingBoxMax, maxPoint(0), maxPoint(1), maxPoint(2));
69 
70 
71  correlationWindowSize = getProperty<int>("StereoCorrelationWindowSize").getValue();
72  correlationThreshold = getProperty<float>("StereoCorrelationThreshold").getValue();
73 
74  texturedRecognition->GetObjectDatabase()->InitCameraParameters(getStereoCalibration(), true);
75  texturedRecognition->GetObjectDatabase()->SetCorrelationParameters(
76  correlationWindowSize, minPoint(2), maxPoint(2), correlationThreshold);
77 
78  return true;
79 }
80 
81 bool
82 TexturedObjectRecognition::addObjectClass(const memoryx::EntityPtr& objectClassEntity,
83  const memoryx::GridFileManagerPtr& fileManager)
84 {
85  TexturedRecognitionWrapperPtr recognitionWrapper =
86  objectClassEntity->addWrapper(new TexturedRecognitionWrapper(fileManager));
87  std::string fileName = recognitionWrapper->getFeatureFile();
88 
89  if (fileName != "")
90  {
91  std::string className = objectClassEntity->getName();
92 
93  if (texturedRecognition->GetObjectDatabase()->AddClass(className, fileName))
94  {
95  return true;
96  }
97  }
98  else
99  {
100  ARMARX_WARNING_S << "No descriptor file defined for object "
101  << objectClassEntity->getName();
102  }
103 
104  return false;
105 }
106 
107 memoryx::ObjectLocalizationResultList
108 TexturedObjectRecognition::localizeObjectClasses(const std::vector<std::string>& objectClassNames,
109  CByteImage** cameraImages,
110  armarx::MetaInfoSizeBasePtr imageMetaInfo,
111  CByteImage** resultImages)
112 {
113  std::string allObjectNames;
114 
115  for (size_t i = 0; i < objectClassNames.size(); i++)
116  {
117  allObjectNames.append(objectClassNames.at(i));
118  allObjectNames.append(" ");
119  }
120 
121  ARMARX_DEBUG_S << "Localizing " << allObjectNames;
122 
123  // result images
124  CByteImage** tmpResultImages = getResultImagesEnabled() ? resultImages : NULL;
125 
126  if (objectClassNames.size() == 1)
127  {
128  texturedRecognition->DoRecognitionSingleObject(cameraImages,
129  tmpResultImages,
130  objectClassNames.at(0).c_str(),
131  true,
132  50,
133  getImagesAreUndistorted());
134  }
135  else
136  {
137  // TODO: multiple is not implemented so searching for all classes
138  texturedRecognition->DoRecognition(
139  cameraImages, tmpResultImages, true, 50, getImagesAreUndistorted());
140  }
141 
142  Object3DList objectList = texturedRecognition->GetObject3DList();
143 
144  ARMARX_DEBUG_S << "Localized " << objectList.size() << " objects";
145  const auto agentName = getProperty<std::string>("AgentName").getValue();
146 
147  memoryx::ObjectLocalizationResultList resultList;
148 
149  for (Object3DList::iterator iter = objectList.begin(); iter < objectList.end(); iter++)
150  {
151  // assure instance belongs to queried class
152  bool queriedClass =
153  (std::find(objectClassNames.begin(), objectClassNames.end(), iter->sName) !=
154  objectClassNames.end());
155 
156  if (iter->localizationValid && queriedClass)
157  {
158  float x = iter->pose.translation.x;
159  float y = iter->pose.translation.y;
160  float z = iter->pose.translation.z;
161 
162  StringVariantBaseMap mapValues;
163  mapValues["x"] = new Variant(x);
164  mapValues["y"] = new Variant(y);
165  mapValues["z"] = new Variant(z);
166  mapValues["name"] = new Variant(iter->sName);
167  mapValues["sequence"] = new Variant(seq++);
168  mapValues["timestamp"] = new Variant(imageMetaInfo->timeProvided / 1000.0 / 1000.0);
169  debugObserver->setDebugChannel("ObjectRecognition", mapValues);
170 
171 
172  // only accept realistic positions
173  if (x > validResultBoundingBoxMin.x && y > validResultBoundingBoxMin.y &&
174  z > validResultBoundingBoxMin.z && x < validResultBoundingBoxMax.x &&
175  y < validResultBoundingBoxMax.y && z < validResultBoundingBoxMax.z)
176  {
177  // assemble result
178  memoryx::ObjectLocalizationResult result;
179 
180  // position and orientation
181  Eigen::Vector3f position(x, y, z);
182  Eigen::Matrix3f orientation;
183  orientation << iter->pose.rotation.r1, iter->pose.rotation.r2,
184  iter->pose.rotation.r3, iter->pose.rotation.r4, iter->pose.rotation.r5,
185  iter->pose.rotation.r6, iter->pose.rotation.r7, iter->pose.rotation.r8,
186  iter->pose.rotation.r9;
187 
188  result.position =
189  new armarx::FramedPosition(position, referenceFrameName, agentName);
190  result.orientation =
191  new armarx::FramedOrientation(orientation, referenceFrameName, agentName);
192 
193  // calculate recognition certainty
194  result.recognitionCertainty =
195  0.5f + 0.5f * calculateRecognitionCertainty(iter->sName, *iter);
196 
197  // calculate position uncertainty
199  calculateLocalizationUncertainty(position);
200  Eigen::MatrixXf cov = posUncertainty->toEigenCovariance();
201  cov *= 4.0f / pow(result.recognitionCertainty, 4);
202  result.positionNoise = memoryx::MultivariateNormalDistributionPtr(
203  new memoryx::MultivariateNormalDistribution(posUncertainty->toEigenMean(),
204  cov));
205 
206  result.objectClassName = iter->sName;
207  result.timeStamp = new TimestampVariant(imageMetaInfo->timeProvided);
208 
209  resultList.push_back(result);
210 
211  FramedPose objectPose(orientation, position, referenceFrameName, agentName);
212  ARMARX_DEBUG_S << "Localized object at pose: " << objectPose;
213  }
214  else
215  {
216  ARMARX_DEBUG_S << "Refused unrealistic localization at position: " << x << " " << y
217  << " " << z;
218  }
219  }
220  }
221 
222  return resultList;
223 }
224 
225 float
226 TexturedObjectRecognition::calculateRecognitionCertainty(const std::string& objectClassName,
227  const Object3DEntry& entry)
228 {
229  //**************************************************************************************************
230  // calculate recognition certainty (ask David Schiebener about that part !!!!)
231  // quality: mean of pixel error
232  // quality2: found number of feature correspondences
233  //**************************************************************************************************
234  // retrieve number of known features for this object
235  int objectIndex = -1;
236  int n = texturedRecognition->GetObjectDatabase()->GetSize();
237 
238  for (int i = 0; i < n; i++)
239  {
240  if (objectClassName.compare(
241  texturedRecognition->GetObjectDatabase()->GetFeatureSet(i)->GetName()) == 0)
242  {
243  objectIndex = i;
244  break;
245  }
246  }
247 
248  if (objectIndex == -1)
249  {
250  return 0.0f;
251  }
252 
253  int numberObjectFeatures =
254  texturedRecognition->GetObjectDatabase()->GetFeatureSet(objectIndex)->GetSize();
255 
256  // rate with 1 if pixel error <= 0.7, rate with 1/e if error = 2.2
257  float temp = (entry.quality > 0.7f) ? entry.quality - 0.7f : 0;
258  float ratingPixelError = expf(-(4.0f / 9.0f) * temp * temp);
259  ratingPixelError = 0.15f + 0.7f * ratingPixelError;
260 
261  // rate with 0.15 if 10 matched features, with 0.85 if 30 matched features
262  temp = 0.1f * (entry.quality2 - 20.0f);
263  float ratingMatchedFeaturesAbsolute = 0.5f + 0.5f * (temp / sqrtf(1.0f + temp * temp));
264  ratingMatchedFeaturesAbsolute = 0.15f + 0.7f * ratingMatchedFeaturesAbsolute;
265 
266  // rate with 1 if number of matched features >= 0.15 * total number of features
267  if (numberObjectFeatures > 300)
268  {
269  numberObjectFeatures = 300;
270  }
271 
272  temp = entry.quality2;
273 
274  if (temp > (float)numberObjectFeatures)
275  {
276  temp = (float)numberObjectFeatures;
277  }
278 
279  float ratingMatchedFeaturesRelative = temp / (0.15f * (float)numberObjectFeatures);
280  ratingMatchedFeaturesRelative =
281  (ratingMatchedFeaturesRelative > 1.0f) ? 1.0f : ratingMatchedFeaturesRelative;
282  ratingMatchedFeaturesRelative = 0.15f + 0.7f * ratingMatchedFeaturesRelative;
283 
284  // division is no problem because fRatingPixelError*fRatingMatchedFeaturesAbsolute*fRatingMatchedFeaturesRelative > 0
285  float recognitionCertainty =
286  (ratingPixelError * ratingMatchedFeaturesAbsolute * ratingMatchedFeaturesRelative) /
287  ((ratingPixelError * ratingMatchedFeaturesAbsolute * ratingMatchedFeaturesRelative) +
288  ((1 - ratingPixelError) * (1 - ratingMatchedFeaturesAbsolute) *
289  (1 - ratingMatchedFeaturesRelative)));
290 
291  return recognitionCertainty;
292 }
armarx::Variant
The Variant class is described here: Variants.
Definition: Variant.h:223
RemoteRobot.h
armarx::StringVariantBaseMap
std::map< std::string, VariantBasePtr > StringVariantBaseMap
Definition: ManagedIceObject.h:110
visionx
ArmarX headers.
Definition: OpenPoseStressTest.h:38
armarx::FramedPose
The FramedPose class.
Definition: FramedPose.h:280
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:205
memoryx::MultivariateNormalDistribution
The MultivariateNormalDistribution class.
Definition: ProbabilityMeasures.h:285
TimestampVariant.h
memoryx::EntityWrappers::TexturedRecognitionWrapper
TexturedRecognitionWrapper offers a simplified access to the data of an object class or instance rela...
Definition: ObjectRecognitionWrapper.h:63
MemoryXCoreObjectFactories.h
ARMARX_WARNING_S
#define ARMARX_WARNING_S
Definition: Logging.h:213
memoryx::MultivariateNormalDistributionPtr
IceInternal::Handle< MultivariateNormalDistribution > MultivariateNormalDistributionPtr
Definition: ProbabilityMeasures.h:279
TexturedObjectRecognition.h
memoryx::EntityWrappers
Definition: AbstractEntityWrapper.cpp:30
armarx::VariantType::FramedOrientation
const VariantTypeId FramedOrientation
Definition: FramedPose.h:39
float
#define float
Definition: 16_Level.h:22
memoryx::GridFileManagerPtr
std::shared_ptr< GridFileManager > GridFileManagerPtr
Definition: AbstractEntityWrapper.h:33
GfxTL::Matrix3f
MatrixXX< 3, 3, float > Matrix3f
Definition: MatrixXX.h:649
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:38
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27