BlobRecognition.cpp
Go to the documentation of this file.
1/*
2* This file is part of ArmarX.
3*
4* ArmarX is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License version 2 as
6* published by the Free Software Foundation.
7*
8* ArmarX is distributed in the hope that it will be useful, but
9* WITHOUT ANY WARRANTY; without even the implied warranty of
10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11* GNU General Public License for more details.
12*
13* You should have received a copy of the GNU General Public License
14* along with this program. If not, see <http://www.gnu.org/licenses/>.
15*
16* @package VisionX::Component
17* @author Kai Welke <welke at kit dot edu>
18* @copyright 2013 Humanoids Group, HIS, KIT
19* @license http://www.gnu.org/licenses/gpl-2.0.txt
20* GNU General Public License
21*/
22
23#include "BlobRecognition.h"
24
27
28#include <RobotAPI/interface/core/RobotStateObserverInterface.h>
31
32#include <Image/ByteImage.h>
33#include <Image/ImageProcessor.h>
36#include <ObjectFinder/CompactRegionFilter.h>
37#include <ObjectFinder/ObjectFinderStereo.h>
38#include <SegmentableRecognition/SegmentableDatabase.h>
39
40// This file must be included after all Ice-related headers when Ice 3.5.x is used (e.g. with Ubuntu 14.04 or Debian 7.0)!
41// GLContext.h indirectly includes X.h which does "#define None", colliding with IceUtil::None.
42#include <gui/GLContext.h>
43
44using namespace armarx;
45using namespace visionx;
46using namespace memoryx::EntityWrappers;
47
51
55
56void
60
61bool
63{
64
65
66 Eigen::Vector3f minPoint = getProperty<Eigen::Vector3f>("MinPoint").getValue();
67 Eigen::Vector3f maxPoint = getProperty<Eigen::Vector3f>("MaxPoint").getValue();
68
69 Math3d::SetVec(validResultBoundingBoxMin, minPoint(0), minPoint(1), minPoint(2));
70 Math3d::SetVec(validResultBoundingBoxMax, maxPoint(0), maxPoint(1), maxPoint(2));
71
72 minPixelsPerRegion = getProperty<float>("MinPixelsPerRegion").getValue();
73 maxEpipolarDistance = getProperty<float>("MaxEpipolarDistance").getValue();
74 std::string colorParameterFilename = getProperty<std::string>("ColorParameterFile").getValue();
75
76 if (!ArmarXDataPath::getAbsolutePath(colorParameterFilename, colorParameterFilename))
77 {
78 ARMARX_ERROR << "Could not find color parameter file in ArmarXDataPath: "
79 << colorParameterFilename;
80 }
81
82 if (!objectFinderStereo)
83 {
84 colorParameters.reset(new CColorParameterSet());
85
86 if (!colorParameters->LoadFromFile(colorParameterFilename.c_str()))
87 {
88 throw armarx::LocalException("Could not read color parameter file.");
89 }
90
91 objectFinderStereo.reset(new CObjectFinderStereo());
92
93 ImageFormatInfo imageFormat = getImageFormat();
94 contextGL.reset(new CGLContext());
95 contextGL->CreateContext(imageFormat.dimension.width, imageFormat.dimension.height);
96 contextGL->MakeCurrent();
97
98 m_pOpenGLVisualizer.reset(new COpenGLVisualizer());
99 m_pOpenGLVisualizer->InitByCalibration(getStereoCalibration()->GetRightCalibration());
100
101 objectFinderStereo->SetColorParameterSet(colorParameters.get());
102 objectFinderStereo->SetRegionFilter(new CCompactRegionFilter());
103
104
105 ARMARX_VERBOSE << "BlobRecognition is initialized";
106 }
107
108
109 objectFinderStereo->Init(getStereoCalibration());
110
111
112 return true;
113}
114
115bool
117 const memoryx::GridFileManagerPtr& fileManager)
118{
119 ARMARX_VERBOSE << "Adding object class " << objectClassEntity->getName() << armarx::flush;
120
121 SegmentableRecognitionWrapperPtr recognitionWrapper =
122 objectClassEntity->addWrapper(new SegmentableRecognitionWrapper(fileManager));
123 std::string dataPath = recognitionWrapper->getDataFiles();
124 ObjectColor color = recognitionWrapper->getObjectColor();
125
126 std::string colorString;
127 CColorParameterSet::Translate(color, colorString);
128 ARMARX_VERBOSE << "Color: " << (int)color << " (" << colorString << ")";
129
130 if (dataPath != "")
131 {
132 // remember colors
133 std::string className = objectClassEntity->getName();
134 objectColors.insert(std::make_pair(className, color));
135 colorToObjectClass.insert(std::make_pair(color, className));
136
137 return true;
138 }
139 else
140 {
142 << "Datapath is empty for " << objectClassEntity->getName()
143 << " object class - make sure you set the correct model file in PriorKnowledge!";
144 }
145
146 return false;
147}
148
149memoryx::ObjectLocalizationResultList
150BlobRecognition::localizeObjectClasses(const std::vector<std::string>& objectClassNames,
151 CByteImage** cameraImages,
152 armarx::MetaInfoSizeBasePtr imageMetaInfo,
153 CByteImage** resultImages)
154{
155
157 localRobot, robotStateComponent, imageMetaInfo->timeProvided / 1000.0);
158
159 objectFinderStereo->PrepareImages(cameraImages);
160 objectFinderStereo->ClearObjectList();
161
162 if (objectClassNames.size() < 1)
163 {
164 ARMARX_WARNING << "objectClassNames.size() = " << objectClassNames.size()
165 << ", something is wrong here! ";
166
167 memoryx::ObjectLocalizationResultList resultList;
168 return resultList;
169 }
170
171 std::string allObjectNames;
172 for (size_t i = 0; i < objectClassNames.size(); i++)
173 {
174 allObjectNames.append(" ");
175 allObjectNames.append(objectClassNames.at(i));
176 }
177
178 contextGL->MakeCurrent();
179
180
181 std::string color;
182
183 for (size_t i = 0; i < objectClassNames.size(); i++)
184 {
185 CColorParameterSet::Translate(objectColors[objectClassNames.at(i)], color);
186 ARMARX_VERBOSE << "Localizing " << objectClassNames.at(i) << ", color: " << color << flush;
187
188 ObjectColor color = objectColors[objectClassNames.at(i)];
189
190 objectFinderStereo->FindObjects(
191 cameraImages, resultImages, color, minPixelsPerRegion, true);
192 }
193
194 objectFinderStereo->Finalize(validResultBoundingBoxMin.z,
195 validResultBoundingBoxMax.z,
196 true,
197 eNone,
198 maxEpipolarDistance,
200 Object3DList objectList = objectFinderStereo->m_objectList;
201
202 ARMARX_INFO << "Found " << objectList.size() << " objects";
203
204
205 // help for problem analysis
206 if (objectList.size() == 0)
207 {
208 ARMARX_INFO << "Looked unsuccessfully for:";
209 std::string color;
210
211 for (size_t i = 0; i < objectClassNames.size(); i++)
212 {
213 CColorParameterSet::Translate(objectColors[objectClassNames.at(i)], color);
214 ARMARX_INFO << objectClassNames.at(i) << " color: " << color << flush;
215 }
216 }
217
218 const auto agentName = getProperty<std::string>("AgentName").getValue();
219 memoryx::ObjectLocalizationResultList resultList;
220
221 for (Object3DEntry const& entry : objectList)
222 {
223 bool queriedClass = false;
224
225 if (colorToObjectClass.count(entry.color))
226 {
227 queriedClass = (std::find(objectClassNames.begin(),
228 objectClassNames.end(),
229 colorToObjectClass[entry.color]) != objectClassNames.end());
230 }
231
232 if (queriedClass)
233 {
234
235 std::string objectName = colorToObjectClass[entry.color];
236 float x = entry.pose.translation.x;
237 float y = entry.pose.translation.y;
238 float z = entry.pose.translation.z;
239
240 if (seq.count(objectName))
241 {
242 seq[objectName]++;
243 }
244 else
245 {
246 seq[objectName] = 0;
247 }
248
249
250 StringVariantBaseMap mapValues;
251 mapValues["x"] = new Variant(x);
252 mapValues["y"] = new Variant(y);
253 mapValues["z"] = new Variant(z);
254 mapValues["name"] = new Variant(objectName);
255 mapValues["sequence"] = new Variant(seq[objectName]);
256 mapValues["timestamp"] = new Variant(imageMetaInfo->timeProvided / 1000.0 / 1000.0);
257 debugObserver->setDebugChannel("ObjectRecognition", mapValues);
258
259 // only accept realistic positions
260 if (x > validResultBoundingBoxMin.x && y > validResultBoundingBoxMin.y &&
261 z > validResultBoundingBoxMin.z && x < validResultBoundingBoxMax.x &&
262 y < validResultBoundingBoxMax.y && z < validResultBoundingBoxMax.z)
263 {
264 // assemble result
265 memoryx::ObjectLocalizationResult result;
266
267 // position and orientation
268 Eigen::Vector3f positionVec(
269 entry.pose.translation.x, entry.pose.translation.y, entry.pose.translation.z);
270
271 FramedPositionPtr position =
272 new FramedPosition(positionVec, referenceFrameName, agentName);
273 position->changeToGlobal(localRobot);
274 float expectedHeight = 1020.0;
275 if (std::fabs(position->z - expectedHeight) < 50.0)
276 {
277 // manually update height
278 position->z = expectedHeight;
279 position->changeFrame(localRobot, referenceFrameName);
280
281 Eigen::Matrix3f m = Eigen::Matrix3f::Identity();
282 FramedOrientationPtr orientation =
283 new FramedOrientation(m, armarx::GlobalFrame, agentName);
284 orientation->changeFrame(localRobot, referenceFrameName);
285
286 result.position = position;
287 result.orientation = orientation;
288
289 // calculate noise
290 result.positionNoise = calculateLocalizationUncertainty(
291 entry.region_left.centroid, entry.region_right.centroid);
292
293 // calculate recognition certainty
294 result.recognitionCertainty =
295 0.5f + 0.5f * calculateRecognitionCertainty(objectName, entry);
296 result.objectClassName = objectName;
297 result.timeStamp = new TimestampVariant(imageMetaInfo->timeProvided);
298
299 resultList.push_back(result);
300 }
301 else
302 {
304 << "Ignoring object localization result with height "
305 << position->z;
306 }
307 }
308 else
309 {
310 ARMARX_VERBOSE_S << "Refused unrealistic localization at position: " << x << " "
311 << y << " " << z;
312 }
313 }
314 }
315
316 ARMARX_VERBOSE << "Finished localizing " << objectClassNames.at(0);
317
318 return resultList;
319}
320
321float
322BlobRecognition::calculateRecognitionCertainty(const std::string& objectClassName,
323 const Object3DEntry& entry)
324{
325 float foundProb = entry.quality * entry.quality2;
326 float notFoundProb = (1 - entry.quality) * (1 - entry.quality2);
327
328 if (foundProb <= 0)
329 {
330 return 0.0f;
331 }
332
333 return foundProb / (foundProb + notFoundProb);
334}
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
static bool getAbsolutePath(const std::string &relativeFilename, std::string &storeAbsoluteFilename, const std::vector< std::string > &additionalSearchPaths={}, bool verbose=true)
Property< PropertyType > getProperty(const std::string &name)
The FramedOrientation class.
Definition FramedPose.h:216
The FramedPosition class.
Definition FramedPose.h:158
static bool synchronizeLocalCloneToTimestamp(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx, Ice::Long timestamp)
Synchronizes a local robot to a robot state at timestamp.
Implements a Variant type for timestamps.
The Variant class is described here: Variants.
Definition Variant.h:224
SegmentableRecognitionWrapper offers a simplified access to the data of an object class or instance r...
bool initRecognizer() override
Initializes segmentable recognition.
void onExitObjectLocalizerProcessor() override
memoryx::ObjectLocalizationResultList localizeObjectClasses(const std::vector< std::string > &objectClassNames, CByteImage **cameraImages, armarx::MetaInfoSizeBasePtr imageMetaInfo, CByteImage **resultImages) override
localizes segmentable object instances
bool addObjectClass(const memoryx::EntityPtr &objectClassEntity, const memoryx::GridFileManagerPtr &fileManager) override
Add object class to segmentable object recognition.
ImageFormatInfo getImageFormat() const
Retrieve format of input images.
bool getImagesAreUndistorted() const
Retrieve whether images are undistorted.
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.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_VERBOSE_S
Definition Logging.h:207
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::string const GlobalFrame
Variable of the global coordinate system.
Definition FramedPose.h:65
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::map< std::string, VariantBasePtr > StringVariantBaseMap
IceInternal::Handle< FramedPosition > FramedPositionPtr
Definition FramedPose.h:149
IceInternal::Handle< FramedOrientation > FramedOrientationPtr
Definition FramedPose.h:207
const LogSender::manipulator flush
Definition LogSender.h:251
IceInternal::Handle< SegmentableRecognitionWrapper > SegmentableRecognitionWrapperPtr
IceInternal::Handle< Entity > EntityPtr
Typedef of EntityPtr as IceInternal::Handle<Entity> for convenience.
Definition Entity.h:45
std::shared_ptr< GridFileManager > GridFileManagerPtr
ArmarX headers.