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
45using namespace armarx;
46using namespace visionx;
47using namespace memoryx;
48using namespace memoryx::EntityWrappers;
49
50bool
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
81bool
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
107memoryx::ObjectLocalizationResultList
108TexturedObjectRecognition::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,
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
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
225float
226TexturedObjectRecognition::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}
#define float
Definition 16_Level.h:22
Property< PropertyType > getProperty(const std::string &name)
The FramedOrientation class.
Definition FramedPose.h:216
The FramedPose class.
Definition FramedPose.h:281
The FramedPosition class.
Definition FramedPose.h:158
Implements a Variant type for timestamps.
The Variant class is described here: Variants.
Definition Variant.h:224
TexturedRecognitionWrapper offers a simplified access to the data of an object class or instance rela...
The MultivariateNormalDistribution class.
ImageFormatInfo getImageFormat() const
Retrieve format of input images.
bool getImagesAreUndistorted() const
Retrieve whether images are undistorted.
bool getResultImagesEnabled() const
Retrieve whether result images are enabled.
memoryx::MultivariateNormalDistributionPtr calculateLocalizationUncertainty(Vec2d left_point, Vec2d right_point)
Calculate 3D uncertainty from two 2d points in left and right camera.
armarx::MetaInfoSizeBasePtr imageMetaInfo
CStereoCalibration * getStereoCalibration() const
Retrieve stereo calibration corresponding to image provider.
bool initRecognizer() override
Initializes textured recognition.
memoryx::ObjectLocalizationResultList localizeObjectClasses(const std::vector< std::string > &objectClassNames, CByteImage **cameraImages, armarx::MetaInfoSizeBasePtr imageMetaInfo, CByteImage **resultImages) override
localizes textured object instances
bool addObjectClass(const memoryx::EntityPtr &objectClassEntity, const memoryx::GridFileManagerPtr &fileManager) override
Add object class to textured object recognition.
#define ARMARX_DEBUG_S
The logging level for output that is only interesting while debugging.
Definition Logging.h:205
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:213
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::map< std::string, VariantBasePtr > StringVariantBaseMap
IceInternal::Handle< TexturedRecognitionWrapper > TexturedRecognitionWrapperPtr
VirtualRobot headers.
IceInternal::Handle< MultivariateNormalDistribution > MultivariateNormalDistributionPtr
IceInternal::Handle< Entity > EntityPtr
Typedef of EntityPtr as IceInternal::Handle<Entity> for convenience.
Definition Entity.h:45
std::shared_ptr< GridFileManager > GridFileManagerPtr
ArmarX headers.