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 
44 using namespace armarx;
45 using namespace visionx;
46 using namespace memoryx::EntityWrappers;
47 
48 BlobRecognition::BlobRecognition()
49 {
50 }
51 
52 BlobRecognition::~BlobRecognition()
53 {
54 }
55 
56 void
57 BlobRecognition::onExitObjectLocalizerProcessor()
58 {
59 }
60 
61 bool
62 BlobRecognition::initRecognizer()
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 
115 bool
116 BlobRecognition::addObjectClass(const memoryx::EntityPtr& objectClassEntity,
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 
149 memoryx::ObjectLocalizationResultList
150 BlobRecognition::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,
199  getImagesAreUndistorted());
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 
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 
321 float
322 BlobRecognition::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 }
armarx::Variant
The Variant class is described here: Variants.
Definition: Variant.h:223
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::StringVariantBaseMap
std::map< std::string, VariantBasePtr > StringVariantBaseMap
Definition: ManagedIceObject.h:110
visionx
ArmarX headers.
Definition: OpenPoseStressTest.h:38
Pose.h
armarx::GlobalFrame
const std::string GlobalFrame
Definition: FramedPose.h:65
armarx::TimestampVariant
Definition: TimestampVariant.h:54
ObjectRecognitionWrapper.h
memoryx::EntityWrappers::SegmentableRecognitionWrapper
SegmentableRecognitionWrapper offers a simplified access to the data of an object class or instance r...
Definition: ObjectRecognitionWrapper.h:85
IceInternal::Handle
Definition: forward_declarations.h:8
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:75
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:570
FramedPose.h
armarx::flush
const LogSender::manipulator flush
Definition: LogSender.h:251
TimestampVariant.h
MemoryXCoreObjectFactories.h
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
memoryx::EntityWrappers
Definition: AbstractEntityWrapper.cpp:30
armarx::VariantType::FramedOrientation
const VariantTypeId FramedOrientation
Definition: FramedPose.h:39
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
memoryx::GridFileManagerPtr
std::shared_ptr< GridFileManager > GridFileManagerPtr
Definition: AbstractEntityWrapper.h:33
magic_enum::detail::find
constexpr std::size_t find(string_view str, char_type c) noexcept
Definition: magic_enum.hpp:309
armarx::RemoteRobot::synchronizeLocalCloneToTimestamp
static bool synchronizeLocalCloneToTimestamp(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx, Ice::Long timestamp)
Synchronizes a local robot to a robot state at timestamp.
Definition: RemoteRobot.cpp:566
ARMARX_VERBOSE_S
#define ARMARX_VERBOSE_S
Definition: Logging.h:207
armarx::ArmarXDataPath::getAbsolutePath
static bool getAbsolutePath(const std::string &relativeFilename, std::string &storeAbsoluteFilename, const std::vector< std::string > &additionalSearchPaths={}, bool verbose=true)
Definition: ArmarXDataPath.cpp:109
GfxTL::Matrix3f
MatrixXX< 3, 3, float > Matrix3f
Definition: MatrixXX.h:649
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:38
armarx::view_selection::skills::localRobot
VirtualRobot::RobotPtr localRobot
Definition: LookForObjectsWithKinematicUnit.cpp:25
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
BlobRecognition.h
ArmarXDataPath.h
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27