27 #include <openpose/pose/poseParameters.hpp>
28 #include <openpose/pose/poseParametersRender.hpp>
31 #include <Image/ImageProcessor.h>
32 #include <Image/IplImageAdaptor.h>
33 #include <Image/PrimitivesDrawer.h>
52 positiveIntRound(
const T a)
58 OpenPoseAdapter::OpenPoseAdapter(
const OpenPoseSettings& settings) : settings(settings)
60 setupOpenPoseEnvironment();
65 OpenPoseAdapter::setupOpenPoseEnvironment()
73 poseModel = op::flagsToPoseModel(op_model_pose_conv);
78 const op::Point<int> netInputSize = op::flagsToPoint(op_net_resolution_conv,
"-1x368");
79 const op::Point<int> outputSize = op::flagsToPoint(op_output_resolution_conv,
"-1x-1");
81 #if (OPENPOSE_VERSION_MAJOR > 1) || (OPENPOSE_VERSION_MAJOR == 1 && OPENPOSE_VERSION_MINOR > 7) || \
82 (OPENPOSE_VERSION_MAJOR == 1 && OPENPOSE_VERSION_MINOR == 7 && OPENPOSE_VERSION_PATCH > 0)
101 {
"/usr/share/OpenPose/",
"/usr/local/share/OpenPose/", OPENPOSE_MODELS});
104 ARMARX_ERROR <<
"Could not find model folder at " << modelFolder;
107 if (!modelFolder.empty() && *modelFolder.rbegin() !=
'/')
111 ARMARX_INFO <<
"Found model path at: " << modelFolder;
126 IplImage* iplImage = IplImageAdaptor::Adapt(inputImage);
127 cv::Mat opInputImage = cv::cvarrToMat(iplImage);
128 const op::Point<int> imageSize{opInputImage.cols, opInputImage.rows};
131 std::vector<double> scaleInputToNetInputs;
132 std::vector<op::Point<int>> netInputSizes;
133 double scaleInputToOutput;
134 op::Point<int> outputResolution;
135 std::tie(scaleInputToNetInputs, netInputSizes, scaleInputToOutput, outputResolution) =
140 const auto netInputArray =
141 cvMatToOpInput->createArray(inputImage_conv, scaleInputToNetInputs, netInputSizes);
147 return poseKeypoints;
153 const CByteImage* rgbImage)
const
157 HumanPose2DMap ice_entities;
158 const std::map<unsigned int, std::string> poseBodyPartMapping =
161 if (op_keypoints.getSize().empty())
166 int entities = op_keypoints.getSize().at(0);
167 int points = op_keypoints.getSize().at(1);
172 for (
int i = 0; i < entities; i++)
176 ice_entities[entity_id] = HumanPose2D();
177 Keypoint2DMap ice_keypoint_map;
178 for (
int id = 0;
id < points;
id++)
181 float x = op_keypoints.at({i, id, 0});
182 float y = op_keypoints.at({i, id, 1});
183 float c = op_keypoints.at({i, id, 2});
184 if (x == 0.0f && y == 0.0f &&
c == 0.0f)
189 keypoint.label = poseBodyPartMapping.at(
id);
192 keypoint.confidence =
c;
193 keypoint.dominantColor =
195 ice_keypoint_map[keypoint.label] = keypoint;
200 ice_entities[entity_id].keypointMap = ice_keypoint_map;
207 armarx::DrawColor24Bit
210 int windowSize)
const
212 if (point.x < 0 || point.y < 0 || point.x >= image.width || point.y >= image.height)
213 return DrawColor24Bit{0, 0, 0};
214 int divisor = 256 / 3;
215 typedef std::tuple<Ice::Byte, Ice::Byte, Ice::Byte> RGBTuple;
216 std::map<RGBTuple, int> histogram;
217 int halfWindowSize =
static_cast<int>(windowSize * 0.5);
218 int left = std::max<int>(0,
static_cast<int>(point.x) - halfWindowSize);
219 int top = std::max<int>(0,
static_cast<int>(point.y) - halfWindowSize);
220 int right = std::min<int>(image.width,
static_cast<int>(point.x) + halfWindowSize);
221 int bottom = std::min<int>(image.height,
static_cast<int>(point.y) + halfWindowSize);
223 for (
int x = left; x < right; x++)
225 for (
int y = top; y < bottom; y++)
227 int pixelPos = (y * image.width + x) * 3;
228 auto tuple = std::make_tuple<Ice::Byte, Ice::Byte, Ice::Byte>(
229 static_cast<Ice::Byte
>(image.pixels[pixelPos] / divisor),
230 static_cast<Ice::Byte
>(image.pixels[pixelPos + 1] / divisor),
231 static_cast<Ice::Byte
>(image.pixels[pixelPos + 2] / divisor));
232 if (histogram.count(tuple))
234 histogram.at(tuple)++;
238 histogram[tuple] = 1;
243 float maxHistogramValue = 0;
244 RGBTuple dominantColor;
245 for (
auto& pair : histogram)
247 if (pair.second > maxHistogramValue)
249 dominantColor = pair.first;
250 maxHistogramValue = pair.second;
253 auto rgb = DrawColor24Bit{
static_cast<Ice::Byte
>(std::get<0>(dominantColor) * divisor),
254 static_cast<Ice::Byte
>(std::get<1>(dominantColor) * divisor),
255 static_cast<Ice::Byte
>(std::get<2>(dominantColor) * divisor)};
261 const op::Array<float>& keypoints,
262 CByteImage& resultImage,
263 float renderThreshold)
267 resultImage.Set(inputImage.width, inputImage.height, inputImage.type);
268 ::ImageProcessor::CopyImage(&inputImage, &resultImage);
270 if (keypoints.getSize().empty())
275 const std::vector<unsigned int>& posePartPairs = op::getPoseBodyPartPairsRender(
poseModel);
278 std::vector<float> keypointColors = op::getPoseColors(
poseModel);
280 const auto thicknessCircleRatio = 1.f / 75.f;
281 const auto thicknessLineRatioWRTCircle = 0.75f;
282 const auto area = inputImage.width * inputImage.height;
283 const int numberKeypoints = keypoints.getSize(1);
285 for (
int person = 0; person < keypoints.getSize(0); person++)
287 const auto personRectangle = op::getKeypointsRectangle(keypoints, person, 0.1f);
288 if (personRectangle.area() > 0)
291 const auto ratioAreas = op::fastMin(
293 op::fastMax(personRectangle.width /
static_cast<float>(inputImage.width),
294 personRectangle.height /
static_cast<float>(inputImage.height)));
295 const auto thicknessRatio =
296 op::fastMax(positiveIntRound<float>(
static_cast<float>(
std::sqrt(area)) *
297 thicknessCircleRatio * ratioAreas),
300 const auto thicknessCircle = op::fastMax(1, (ratioAreas > 0.05f ? thicknessRatio : -1));
301 const auto thicknessLine =
302 op::fastMax(1, positiveIntRound(thicknessRatio * thicknessLineRatioWRTCircle));
303 const auto radius = thicknessRatio / 2;
306 for (
unsigned int i = 0; i < posePartPairs.size(); i = i + 2)
308 const int index1 = (person * numberKeypoints +
static_cast<int>(posePartPairs[i])) *
309 keypoints.getSize(2);
311 (person * numberKeypoints +
static_cast<int>(posePartPairs[i + 1])) *
312 keypoints.getSize(2);
314 float x1 = keypoints[index1 + 0];
315 float y1 = keypoints[index1 + 1];
316 float x2 = keypoints[index2 + 0];
317 float y2 = keypoints[index2 + 1];
319 if (!(x1 == 0.0f && y1 == 0.0f) && !(x2 == 0.0f && y2 == 0.0f))
321 if (keypoints[index1 + 2] > renderThreshold &&
322 keypoints[index2 + 2] > renderThreshold)
324 unsigned int colorIndex = posePartPairs[i + 1] * 3;
325 ::PrimitivesDrawer::DrawLine(
329 static_cast<int>(keypointColors[colorIndex + 2]),
330 static_cast<int>(keypointColors[colorIndex + 1]),
331 static_cast<int>(keypointColors[colorIndex + 0]),
338 for (
int i = 0; i < numberKeypoints; i++)
340 const int index = (person * numberKeypoints + i) * keypoints.getSize(2);
341 float x = keypoints[
index + 0];
342 float y = keypoints[
index + 1];
344 if (!(x == 0.0f && y == 0.0f) && keypoints[
index + 2] > renderThreshold)
346 unsigned int colorIndex =
static_cast<unsigned int>(i * 3);
348 ::PrimitivesDrawer::DrawCircle(&resultImage,
352 static_cast<int>(keypointColors[colorIndex + 2]),
353 static_cast<int>(keypointColors[colorIndex + 1]),
354 static_cast<int>(keypointColors[colorIndex + 0]),