DeepFaceRecognition.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::ArmarXObjects::DeepFaceRecognition
17  * @author Mirko Waechter (waechter at kit dot edu)
18  * @date 2017
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #include "DeepFaceRecognition.h"
24 #include <Image/PrimitivesDrawerCV.h>
25 #include <Image/PrimitivesDrawer.h>
27 
32 
34 
37 
38 #include <SimoxUtility/algorithm/string/string_tools.h>
39 
40 #include <Image/ImageProcessor.h>
41 #include <Image/IplImageAdaptor.h>
42 
43 #include <Eigen/Geometry>
44 #include <Calibration/Calibration.h>
45 
46 using namespace armarx;
47 using namespace visionx;
48 
49 //void visionx::DeepFaceRecognition::onInitObjectLocalizerProcessor()
51 {
52  usingProxy("FaceRecognition");
53  usingProxy("LongtermMemory");
54  usingProxy(getProperty<std::string>("ImageProviderName").getValue());
55 
56 
57  offeringTopic("TextToSpeech");
58 }
59 
60 //void visionx::DeepFaceRecognition::onConnectObjectLocalizerProcessor()
62 {
63  getProxy(faceReg, "FaceRecognition");
64  getProxy(ltm, "LongtermMemory");
65  getProxy(imageProvider, getProperty<std::string>("ImageProviderName").getValue());
66  // auto calibration = imageProvider->getMonocularCalibration();
67 
68  // this->calibration.reset(visionx::tools::convert(imageProvider->getMonocularCalibration()));
69  this->calibration.reset(new CCalibration());
70  calibration->SetCameraParameters(987.99, 956.82, 639.32, 415.64,
71  0, 0, 0, 0,
72  Math3d::unit_mat, Math3d::zero_vec, 1280, 720);
73 
74  tts = getTopic<armarx::TextListenerInterfacePrx>("TextToSpeech");
75  if (!ltm->hasSegment(faceSegmentName))
76  {
77  faceSegmentPrx = memoryx::EntityMemorySegmentInterfacePrx::checkedCast(ltm->addGenericSegment(faceSegmentName));
78  }
79  else
80  {
81  faceSegmentPrx = memoryx::EntityMemorySegmentInterfacePrx::checkedCast(ltm->getSegment(faceSegmentName));
82  }
83 }
84 
85 
86 
87 
88 
89 armarx::PropertyDefinitionsPtr DeepFaceRecognition::createPropertyDefinitions()
90 {
92  getConfigIdentifier()));
93 }
94 
95 
96 
97 memoryx::ObjectLocalizationResultList visionx::DeepFaceRecognition::localizeObjectClasses(const memoryx::ObjectClassNameList& classes, const Ice::Current&)
98 {
99  ARMARX_VERBOSE << deactivateSpam(10) << "Localizing: " << classes;
100  memoryx::ObjectLocalizationResultList result;
101  ARMARX_CHECK_EXPRESSION(faceReg);
102  ARMARX_CHECK_EXPRESSION(faceSegmentPrx);
103 
104  auto faceLocations = faceReg->calculateFaceLocations();
105  ARMARX_VERBOSE << deactivateSpam(10, std::to_string(faceLocations.size())) << "Found " << faceLocations.size() << " faces";
106  auto agentName = getProperty<std::string>("AgentName").getValue();
107  auto cameraFrame = getProperty<std::string>("CameraFrameName").getValue();
108  for (visionx::FaceLocation faceLocation : faceLocations)
109  {
110  memoryx::EntityPtr oldFace = memoryx::EntityPtr::dynamicCast(faceSegmentPrx->getEntityByName(faceLocation.label));
111  bool updateFaceMemory = true;
112  ARMARX_DEBUG << deactivateSpam(1) << "Rect: " << faceLocation.topLeft.e0 << ", " << faceLocation.topLeft.e1 << ", " << faceLocation.bottomRight.e0 << ", " << faceLocation.bottomRight.e1 ;
113  float centerX = (faceLocation.bottomRight.e0 + faceLocation.topLeft.e0) * 0.5f;
114  float centerY = (faceLocation.bottomRight.e1 + faceLocation.topLeft.e1) * 0.5f;
115  memoryx::ObjectLocalizationResult r;
116  r.objectClassName = "face";
117  r.instanceName = faceLocation.label;
119  r.orientation = new FramedOrientation(ori, cameraFrame, agentName);
120  Vec3d cameraCoords;
121  float faceHeightPixel = faceLocation.bottomRight.e1 - faceLocation.topLeft.e1;
122  float distance = calibration->GetCameraParameters().focalLength.y * 160.f / (faceHeightPixel);
123  this->calibration->ImageToCameraCoordinates(Vec2d {centerX, centerY}, cameraCoords, distance, false);
124  ARMARX_VERBOSE << deactivateSpam(1) << "Camera coordinates for " << faceLocation.label << ": " << cameraCoords.x << ", " << cameraCoords.y << " distance: " << distance
125  << ", " << VAROUT(faceHeightPixel) << VAROUT(centerX) << VAROUT(centerY);
126  r.position = new FramedPosition(Eigen::Vector3f(cameraCoords.x, cameraCoords.y, distance), cameraFrame, agentName);
128  r.orientation = new FramedOrientation(id, cameraFrame, agentName);
129  r.recognitionCertainty = 0.7f;
130  Eigen::Vector3f cov(10, 10, 10000);
131  r.positionNoise = new memoryx::MultivariateNormalDistribution(Eigen::Vector3f::Zero(), cov.asDiagonal());
132 
133  r.timeStamp = new armarx::TimestampVariant(faceLocation.timestamp);
134  result.push_back(r);
135  if (faceLocation.label == "Unknown")
136  {
137  continue;
138  }
139  if (oldFace && oldFace->hasAttribute("LastGreetingTime"))
140  {
141  VariantPtr updateTimeVariant = VariantPtr::dynamicCast(oldFace->getAttribute("LastGreetingTime")->getValue());
142  ARMARX_CHECK_EXPRESSION(updateTimeVariant);
143  ARMARX_CHECK_EXPRESSION(updateTimeVariant->get<TimestampVariant>());
144  updateFaceMemory &= updateTimeVariant->get<TimestampVariant>()->toTime() + IceUtil::Time::secondsDouble(getProperty<float>("GreetAgainDelay").getValue()) < TimeUtil::GetTime();
145  }
146  auto face = oldFace ? oldFace : memoryx::Entity::CreateGenericEntity();
148  // int matchCounter = 0;
149  if (updateFaceMemory)
150  {
151  // if (oldFace && oldFace->hasAttribute("MatchCounter"))
152  // {
153  // bool lastLocalizationTooOld = false;
154  // if (oldFace->hasAttribute("UpdateTime"))
155  // {
156  // VariantPtr updateTimeVariant = VariantPtr::dynamicCast(oldFace->getAttribute("UpdateTime")->getValue());
157  // lastLocalizationTooOld &= updateTimeVariant->get<TimestampVariant>()->toTime() + IceUtil::Time::secondsDouble(10) > TimeUtil::GetTime();
158 
159  // }
160  // if (!lastLocalizationTooOld)
161  // {
162  // matchCounter = oldFace->getAttribute("MatchCounter")->getValue()->getInt();
163  // }
164  // }
165  // matchCounter++;
166  face->setName(faceLocation.label);
167 
168  face->putAttribute("ImagePosition", new armarx::Vector2(centerX, centerY));
169  face->putAttribute("UpdateTime", TimestampVariant::nowPtr());
170  // if (matchCounter >= getProperty<int>("FaceMatchCounter").getValue())
171  float prob = updateAndCheckFaceExistenceProbability(faceLocation);
172  ARMARX_INFO << deactivateSpam(1) << VAROUT(prob);
173  if (prob > getProperty<float>("GreetThreshold").getValue())
174 
175  {
176  auto tts_label = simox::alg::replace_all(faceLocation.label, "mirko", "mir ko");
177  face->putAttribute("LastGreetingTime", TimestampVariant::nowPtr());
178  tts->reportTextWithParams("Hello %1%.", {tts_label});
179  ARMARX_IMPORTANT << "Hello " << faceLocation.label;
180  // matchCounter = 0; // reset back to 0 so
181  }
182  }
183  // face->putAttribute("MatchCounter", matchCounter); //always update matchCounter, though matchCounter is only increased if LastGreetingTime is old (see GreetAgainDelay)
184  faceSegmentPrx->upsertEntityByName(faceLocation.label, face);
185 
186  }
187  return result;
188 }
189 
190 
191 
192 float visionx::DeepFaceRecognition::updateAndCheckFaceExistenceProbability(const visionx::FaceLocation& faceLocation)
193 {
194  auto& timeConfList = faceConfidenceHistory[faceLocation.label];
195 
196  double filterRadius = getProperty<float>("FilterRadius").getValue(); // kind of seconds
197  double sigma = filterRadius / 2.5;
198  double sigmaSquare = sigma * sigma;
199  auto gaussianBellCurve = [&](double x)
200  {
201  return exp(-double((x) * (x)) / (sigmaSquare));
202  };
203 
204  auto now = IceUtil::Time::now();
205  // remove old entries
206  for (auto it = timeConfList.begin(); it != timeConfList.end();)
207  {
208  IceUtil::Time t = it->first;
209  // double confidence = it->second;
210  double tDiff = (t - now).toMilliSecondsDouble() * 0.001;
211  double weight = gaussianBellCurve(tDiff);
212  // ARMARX_INFO << VAROUT(tDiff) << VAROUT(weight) << t.toDateTime() + " " << now.toDateTime();
213  if (weight < 0.001)
214  {
215  it = timeConfList.erase(it);
216  }
217  else
218  {
219  it++;
220  }
221  }
222 
223  timeConfList.push_back(std::make_pair(now, faceLocation.confidence));
224  float sum = 0;
225  for (auto& timeConfPair : timeConfList)
226  {
227  IceUtil::Time t = timeConfPair.first;
228  double confidence = timeConfPair.second;
229  double tDiff = (t - now).toMilliSecondsDouble() * 0.001;
230  double weight = gaussianBellCurve(tDiff);
231  // ARMARX_INFO << VAROUT(confidence) << VAROUT(weight) << VAROUT(tDiff);
232  sum += confidence * weight;
233  }
234  ARMARX_INFO << VAROUT(sum);
235  return sum;
236 }
visionx::DeepFaceRecognition::localizeObjectClasses
memoryx::ObjectLocalizationResultList localizeObjectClasses(const memoryx::ObjectClassNameList &classes, const Ice::Current &) override
Definition: DeepFaceRecognition.cpp:97
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
visionx
ArmarX headers.
Definition: OpenPoseStressTest.h:38
visionx::DeepFaceRecognition::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: DeepFaceRecognition.cpp:61
visionx::DeepFaceRecognition::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: DeepFaceRecognition.cpp:50
visionx::DeepFaceRecognitionPropertyDefinitions
Definition: DeepFaceRecognition.h:41
armarx::TimestampVariant
Definition: TimestampVariant.h:54
GfxTL::Vec2d
VectorXD< 2, double > Vec2d
Definition: VectorXD.h:694
PersistentEntitySegment.h
memoryx::Entity::CreateGenericEntity
static EntityPtr CreateGenericEntity()
Creates an entity without any convenience getter/setter functions.
Definition: Entity.cpp:42
armarx::Vector2
The Vector2 class.
Definition: Pose.h:52
armarx::TimestampVariant::nowPtr
static TimestampVariantPtr nowPtr()
Definition: TimestampVariant.h:111
IceInternal::Handle
Definition: forward_declarations.h:8
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:72
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:523
FramedPose.h
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
GfxTL::Vec3d
VectorXD< 3, double > Vec3d
Definition: VectorXD.h:695
TimestampVariant.h
MemoryXCoreObjectFactories.h
DeepFaceRecognition.h
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:40
armarx::TimeUtil::GetTime
static IceUtil::Time GetTime(TimeMode timeMode=TimeMode::VirtualTime)
Get the current time.
Definition: TimeUtil.cpp:42
CMakePackageFinder.h
GfxTL::Matrix3f
MatrixXX< 3, 3, float > Matrix3f
Definition: MatrixXX.h:600
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
armarx::VariantType::FramedOrientation
const VariantTypeId FramedOrientation
Definition: FramedPose.h:40
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
IceUtil::Handle< class PropertyDefinitionContainer >
MemoryXTypesObjectFactories.h
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:88
TypeMapping.h
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:39
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:34
ArmarXDataPath.h
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::VariantType::MultivariateNormalDistribution
const armarx::VariantTypeId MultivariateNormalDistribution
Definition: ProbabilityMeasures.h:36