25#include <SimoxUtility/algorithm/string.h>
29#include <VisionX/interface/components/RGBDImageProvider.h>
42 def->topic(
listener3DPrx,
"OpenPoseEstimation3D",
"OpenPoseEstimation3DTopicName");
46 "UseDistortionParameters",
47 "Whether to use distortion parameters when transforming image coordinates into "
50 def->optional(
radius,
"DepthMedianRadius",
"Depth Median Radius");
54 "Pixels with a distance higher than this value are masked out. Only for depth camera mode.",
58 "Allowed difference of depth value for one keypoint to median of all keypoints.",
60 def->optional(
cameraNodeName,
"CameraNodeName",
"The robot node name of the camera");
62 def->optional(
brightnessIncrease,
"BrightnessIncrease",
"Increase brightness of masked pixels");
73 ARMARX_VERBOSE <<
"Trying to get StereoCalibrationInterface proxy: "
75 visionx::StereoCalibrationInterfacePrx calib =
79 ARMARX_ERROR <<
"Image provider does not provide a stereo calibration - 3D will not work - "
85 CStereoCalibration* stereoCalibration =
88 calibration = stereoCalibration->GetLeftCalibration();
138 <<
"Could not render output image for 3d pose estimation";
144 maskOutputImageBasedOnDepth();
153 if (entity.keypointMap.size() == 0)
158 std::map<std::string, int>
160 std::vector<int> depthsCopy;
163 for (
const auto& [kp_name, point] : entity.keypointMap)
165 int depth = getMedianDepthFromImage(
166 static_cast<int>(point.x),
static_cast<int>(point.y),
radius);
167 depthStorage[kp_name] = depth;
168 depthsCopy.push_back(depth);
172 std::sort(depthsCopy.begin(), depthsCopy.end());
173 const int medianDepth = depthsCopy.at(depthsCopy.size() / 2);
174 for (
auto& [storage_name, depth] : depthStorage)
176 if (depth > medianDepth + depthThreshold || depth < medianDepth - depthThreshold)
185 for (
const auto& [kp_name, point] : entity.keypointMap)
188 imagePoint.x = point.x;
189 imagePoint.y = point.y;
194 static_cast<float>(depthStorage.at(kp_name)),
211 openposeResult3D[name].keypointMap[kp_name].dominantColor = point.dominantColor;
228RGBDOpenPoseEstimationComponentPluginUser::getMedianDepthFromImage(
int x,
int y,
int radius)
const
230 std::vector<int> depths;
231 for (
int xoffset = -
radius; xoffset <
radius; xoffset++)
233 int xo =
x + xoffset;
238 for (
int yoffset = -
radius; yoffset <
radius; yoffset++)
240 int yo = y + yoffset;
247 if (xoffset * xoffset + yoffset * yoffset <=
radius *
radius)
249 unsigned int pixelPos =
256 depths.push_back(z_value);
261 std::sort(depths.begin(), depths.end());
263 return depths.empty() ? 0 : depths[depths.size() / 2];
267RGBDOpenPoseEstimationComponentPluginUser::maskOutputImageBasedOnDepth()
281 CByteImage depthMaskImage(
283 CByteImage brightenMaskImage(
285 ::ImageProcessor::Zero(&depthMaskImage);
286 ::ImageProcessor::Zero(&brightenMaskImage);
288 for (
int i = 0; i < pixelCount; i += 1)
293 depthMaskImage.pixels[i] = z_value > depthThresholdmm || z_value == 0 ? 0 : 255;
296 ::ImageProcessor::Erode(&depthMaskImage, &depthMaskImage, 5);
297 ::ImageProcessor::Dilate(&depthMaskImage, &depthMaskImage, 20);
299 for (
int i = 0; i < pixelCount; i += 1)
301 if (depthMaskImage.pixels[i] == 0)
309 brightenMaskImage.pixels[i] = 255;
316 CByteImage smoothedImageMask(&brightenMaskImage);
317 ::ImageProcessor::GaussianSmooth5x5(&brightenMaskImage, &smoothedImageMask);
319 for (
int i = 0; i < pixelCount; i += 1)
321 if (depthMaskImage.pixels[i] == 0)
323 float perc =
static_cast<float>(smoothedImageMask.pixels[i]) / 255.f;
352 ARMARX_INFO <<
"Starting OpenposeEstimation -- 3D";
363 ARMARX_INFO <<
"Stopping OpenposeEstimation -- 3D";
370 const EnableHumanPoseEstimationInput& input,
423RGBDOpenPoseEstimationComponentPluginUser::filterToNearest()
430 std::vector<std::pair<std::string, HumanPose3D>> poses;
433 poses.push_back({key, humanPose});
436 std::sort(poses.begin(),
438 [](std::pair<std::string, HumanPose3D> o1, std::pair<std::string, HumanPose3D> o2)
440 auto humanPose1 = o1.second;
441 auto humanPose2 = o2.second;
442 float humanPose1AverageDepth = std::numeric_limits<float>::quiet_NaN();
443 float humanPose2AverageDepth = std::numeric_limits<float>::quiet_NaN();
444 if (humanPose1.keypointMap.size() == 0)
447 int amountDepths = 0;
448 for (const auto& [k, point] : humanPose1.keypointMap)
453 humanPose1AverageDepth = result / static_cast<float>(amountDepths);
456 if (humanPose2.keypointMap.size() == 0)
459 int amountDepths = 0;
460 for (const auto& [k, point] : humanPose2.keypointMap)
465 humanPose2AverageDepth = result /
static_cast<float>(amountDepths);
468 return humanPose1AverageDepth < humanPose2AverageDepth;
472 openposeResult3D.clear();
473 for (
const auto& p : poses)
475 openposeResult3D[p.first] = p.second;
486 arviz.commit(openPoseArVizLayer);
494 std::string objectName =
"human_" + name;
499 arviz.commit(openPoseArVizLayer);
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
armarx::viz::Client arviz
The FramedPosition class.
Eigen::Vector3f toGlobalEigen(const SharedRobotInterfacePrx &referenceRobot) const
IceManagerPtr getIceManager() const
Returns the IceManager.
std::atomic_long timestamp_of_update
virtual void reportEntities()
virtual void preOnConnectImageProcessor()
void stop(const Ice::Current &=Ice::emptyCurrent) override
void start(const Ice::Current &=Ice::emptyCurrent) override
virtual void postOnConnectImageProcessor()
virtual void postCreatePropertyDefinitions(PropertyDefinitionsPtr &properties)
HumanPose2DMap openposeResult
void enableHumanPoseEstimation(const EnableHumanPoseEstimationInput &input, const Ice::Current &=Ice::emptyCurrent) override
virtual void preOnDisconnectImageProcessor()
CByteImage ** openposeResultImage
virtual void preOnInitImageProcessor()
visionx::ImageProviderInfo imageProviderInfo
virtual void postOnDisconnectImageProcessor()
virtual void renderOutputImage(const op::Array< float > &)
std::mutex depthImageBufferMutex
void start3DPoseEstimation(const Ice::Current &=Ice::emptyCurrent) override
std::string cameraNodeName
OpenPose3DListenerPrx listener3DPrx
VirtualRobot::RobotPtr localRobot
void stop(const Ice::Current &=Ice::emptyCurrent) override
void preOnInitImageProcessor() override
void stop3DPoseEstimation(const Ice::Current &=Ice::emptyCurrent) override
void renderOutputImage(const op::Array< float > &) override
const CCalibration * calibration
void postCreatePropertyDefinitions(PropertyDefinitionsPtr &properties) override
CByteImage * depthImageBuffer
void postOnDisconnectImageProcessor() override
void visualize() override
bool useDistortionParameters
armarx::RobotStateComponentInterfacePrx robotStateInterface
void preOnConnectImageProcessor() override
void postOnConnectImageProcessor() override
void enableHumanPoseEstimation(const EnableHumanPoseEstimationInput &input, const Ice::Current &) override
void preOnDisconnectImageProcessor() override
unsigned int maxDepthDifference
RGBDOpenPoseEstimationComponentPluginUser()
void reportEntities() override
std::atomic_bool running3D
HumanPose3DMap openposeResult3D
bool reportOnlyNearestPerson
CByteImage * maskedrgbImageBuffer
VirtualRobot::RobotPtr createLocalClone()
Clones the structure of this remote robot to a local instance.
static bool synchronizeLocalCloneToTimestamp(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx, Ice::Long timestamp)
Synchronizes a local robot to a robot state at timestamp.
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.