27 #include <VisionX/interface/components/RGBDImageProvider.h>
30 #include <SimoxUtility/algorithm/string.h>
40 def->topic(
listener3DPrx,
"OpenPoseEstimation3D",
"OpenPoseEstimation3DTopicName");
43 def->optional(
useDistortionParameters,
"UseDistortionParameters",
"Whether to use distortion parameters when transforming image coordinates into world coordinates");
45 def->optional(
radius,
"DepthMedianRadius",
"Depth Median Radius");
48 def->optional(
cameraNodeName,
"CameraNodeName",
"The robot node name of the camera");
50 def->optional(
brightnessIncrease,
"BrightnessIncrease",
"Increase brightness of masked pixels");
61 visionx::StereoCalibrationInterfacePrx calib = visionx::StereoCalibrationInterfacePrx::checkedCast(
imageProviderInfo.
proxy);
71 calibration = stereoCalibration->GetLeftCalibration();
121 maskOutputImageBasedOnDepth();
129 if (entity.keypointMap.size() == 0)
134 std::map<std::string, int> depthStorage;
135 std::vector<int> depthsCopy;
138 for (
const auto& [kp_name, point] : entity.keypointMap)
140 int depth = getMedianDepthFromImage(
static_cast<int>(point.x),
static_cast<int>(point.y),
radius);
141 depthStorage[kp_name] = depth;
142 depthsCopy.push_back(depth);
146 std::sort(depthsCopy.begin(), depthsCopy.end());
147 const int medianDepth = depthsCopy.at(depthsCopy.size() / 2);
148 for (
auto& [storage_name, depth] : depthStorage)
150 if (depth > medianDepth + depthThreshold || depth < medianDepth - depthThreshold)
159 for (
const auto& [kp_name, point] : entity.keypointMap)
162 imagePoint.x = point.x;
163 imagePoint.y = point.y;
180 openposeResult3D[name].keypointMap[kp_name].dominantColor = point.dominantColor;
194 int RGBDOpenPoseEstimationComponentPluginUser::getMedianDepthFromImage(
int x,
int y,
int radius)
const
196 std::vector<int> depths;
197 for (
int xoffset = -
radius; xoffset <
radius; xoffset++)
199 int xo = x + xoffset;
204 for (
int yoffset = -
radius; yoffset <
radius; yoffset++)
206 int yo = y + yoffset;
213 if (xoffset * xoffset + yoffset * yoffset <=
radius *
radius)
215 unsigned int pixelPos =
static_cast<unsigned int>(3 * (yo *
depthImageBuffer->width + xo));
221 depths.push_back(z_value);
226 std::sort(depths.begin(), depths.end());
228 return depths.empty() ? 0 : depths[depths.size() / 2];
231 void RGBDOpenPoseEstimationComponentPluginUser::maskOutputImageBasedOnDepth()
247 ::ImageProcessor::Zero(&depthMaskImage);
248 ::ImageProcessor::Zero(&brightenMaskImage);
250 for (
int i = 0; i < pixelCount; i += 1)
253 depthMaskImage.pixels[i] = z_value > depthThresholdmm || z_value == 0 ? 0 : 255;
256 ::ImageProcessor::Erode(&depthMaskImage, &depthMaskImage, 5);
257 ::ImageProcessor::Dilate(&depthMaskImage, &depthMaskImage, 20);
259 for (
int i = 0; i < pixelCount; i += 1)
261 if (depthMaskImage.pixels[i] == 0)
269 brightenMaskImage.pixels[i] = 255;
276 CByteImage smoothedImageMask(&brightenMaskImage);
277 ::ImageProcessor::GaussianSmooth5x5(&brightenMaskImage, &smoothedImageMask);
279 for (
int i = 0; i < pixelCount; i += 1)
281 if (depthMaskImage.pixels[i] == 0)
283 float perc =
static_cast<float>(smoothedImageMask.pixels[i]) / 255.f;
307 ARMARX_INFO <<
"Starting OpenposeEstimation -- 3D";
317 ARMARX_INFO <<
"Stopping OpenposeEstimation -- 3D";
373 void RGBDOpenPoseEstimationComponentPluginUser::filterToNearest()
380 std::vector<std::pair<std::string, HumanPose3D>> poses;
383 poses.push_back({key, humanPose});
386 std::sort(poses.begin(), poses.end(), [](std::pair<std::string, HumanPose3D> o1, std::pair<std::string, HumanPose3D> o2)
388 auto humanPose1 = o1.second;
389 auto humanPose2 = o2.second;
390 float humanPose1AverageDepth = std::numeric_limits<float>::quiet_NaN();
391 float humanPose2AverageDepth = std::numeric_limits<float>::quiet_NaN();
392 if (humanPose1.keypointMap.size() == 0)
395 int amountDepths = 0;
396 for (const auto& [k, point] : humanPose1.keypointMap)
401 humanPose1AverageDepth = result / static_cast<float>(amountDepths);
404 if (humanPose2.keypointMap.size() == 0)
407 int amountDepths = 0;
408 for (const auto& [k, point] : humanPose2.keypointMap)
413 humanPose2AverageDepth = result /
static_cast<float>(amountDepths);
416 return humanPose1AverageDepth < humanPose2AverageDepth;
420 openposeResult3D.clear();
421 for (
const auto& p : poses)
423 openposeResult3D[p.first] = p.second;
442 std::string objectName =
"human_" + name;