OpenPoseEstimation.h
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::OpenPoseEstimation
17  * @author Stefan Reither ( stef dot reither at web dot de )
18  * @date 2018
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 #pragma once
23 
26 
27 #include <RobotAPI/interface/visualization/DebugDrawerInterface.h>
30 
31 #include <VirtualRobot/Robot.h>
32 
33 #include <Calibration/Calibration.h>
34 #include <Calibration/StereoCalibration.h>
35 
38 #include <VisionX/interface/components/OpenPoseEstimationInterface.h>
39 #include <VisionX/interface/components/PointCloudAndImageAndCalibrationProviderInterface.h>
40 #include <VisionX/components/image_processor/OpenPoseEstimation/Util.h>
41 #include <VisionX/components/image_processor/OpenPoseEstimation/KeypointManager.h>
42 #include <VisionX/components/image_processor/OpenPoseEstimation/ImageKeypointBuffer.h>
43 
44 // OpenPose
45 #include <openpose/core/headers.hpp>
46 #include <openpose/pose/headers.hpp>
47 #include <openpose/utilities/headers.hpp>
48 
49 
50 //#ifdef OPENPOSE_MODELS
51 //#define MODEL_FOLDER OPENPOSE_MODELS
52 //#else
53 //#define MODEL_FOLDER ""
54 //#endif
55 
56 
57 namespace armarx
58 {
60  {
64  };
65 
66  /**
67  * @class OpenPoseEstimationPropertyDefinitions
68  * @brief
69  */
72  {
73  public:
76  {
77  defineOptionalProperty<std::string>("OpenPoseEstimation2DTopicName", "OpenPoseEstimation2D");
78  defineOptionalProperty<std::string>("OpenPoseEstimation3DTopicName", "OpenPoseEstimation3D");
79  defineOptionalProperty<int>("DepthMedianRadius", 10, "Radius of the circle around a target pixel in the depth image, which is used to calculate the median around that pixel.");
80  defineOptionalProperty<bool>("UseDistortionParameters", false, "Whether to use distortion parameters when transforming image coordinates into world coordinates");
81 
82  defineRequiredProperty<std::string>("ImageProviderName", "Name of the ImageProviderComponent");
83  defineOptionalProperty<std::string>("DebugDrawerTopicName", "DebugDrawerUpdates", "Name of the debug drawer topic that should be used");
84 
85  defineOptionalProperty<OpenPoseEstimationMode>("Mode", FromDepthImage, "Sets the mode of this instance of OpenPoseEstiamtion. There are currently three support modes:"
86  "'FromDepthImage', which lets the image processor expect a rgb-image and a depth-image,"
87  "'FromStereoImage', which lets the image processor expect two images as a stereo input "
88  "which will be used for calculating the 3D-values and"
89  "'FromTopic', which lets the image processor listen on a topic which provides openpose-keypoints.")
90  .setMatchRegex("FromDepthImage|FromStereoImage|FromTopic")
91  .map("FromDepthImage", OpenPoseEstimationMode::FromDepthImage)
92  .map("FromStereoImage", OpenPoseEstimationMode::FromStereoImage)
93  .map("FromTopic", OpenPoseEstimationMode::FromTopic);
94 
95  defineOptionalProperty<std::string>("OP_net_resolution", "-1x368", "Multiples of 16. If it is increased, the accuracy potentially increases. If it is "
96  "decreased, the speed increases. For maximum speed-accuracy balance, it should keep the "
97  "closest aspect ratio possible to the images or videos to be processed.\n Using `-1` in "
98  "any of the dimensions, OP will choose the optimal aspect ratio depending on the user's "
99  "input value.\n E.g. the default `-1x368` is equivalent to `656x368` in 16:9 resolutions, "
100  "e.g. full HD (1980x1080) and HD (1280x720) resolutions.");
101  defineOptionalProperty<std::string>("OP_output_resolution", "-1x-1", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the"
102  " input image resolution.");
103  defineOptionalProperty<double>("OP_scale_gap", 0.3, "Scale gap between scales. No effect unless scale_number > 1. Initial scale is always 1. "
104  "If you want to change the initial calib->get scale, you actually want to multiply the "
105  "`net_resolution` by your desired initial scale.");
106  defineOptionalProperty<int>("OP_scale_number", 1, "Number of scales to average.");
107  defineOptionalProperty<std::string>("OP_model_pose", human::pose::model::openpose_body_25::ModelId, "Model to be used. E.g. `BODY_25` (25 keypoints, best model), `COCO` (18 keypoints), `MPI` (15 keypoints, ~10% faster), "
108  "MPI_4_layers` (15 keypoints, even faster but less accurate).");
109  defineOptionalProperty<std::string>("OP_model_folder", "models/", "Folder path (absolute or relative) where the models (pose, face, ...) are located.");
110  defineOptionalProperty<int>("OP_num_gpu_start", 0, "GPU device start number.");
111  defineOptionalProperty<float>("OP_render_threshold", 0.05f, "Only estimated keypoints whose score confidences are higher than this threshold will be"
112  " rendered.\n Generally, a high threshold (> 0.5) will only render very clear body parts;"
113  " while small thresholds (~0.1) will also output guessed and occluded keypoints, but also"
114  " more false positives (i.e. wrong detections).");
115  defineOptionalProperty<int>("MaxDepth", 3000, "Pixels with a distance higher than this value are masked out. Only for depth camera mode.", PropertyDefinitionBase::eModifiable);
116  defineOptionalProperty<int>("MaxDepthDifference", 700, "Allowed difference of depth value for one keypoint to median of all keypoints.", PropertyDefinitionBase::eModifiable);
117  defineOptionalProperty<int>("MaskBrightnessIncrease", 100, "All masked pixels will be increased by this brightness for visualization. If value is <0, the original mask is shown.", PropertyDefinitionBase::eModifiable);
118 
119  defineOptionalProperty<std::string>("RobotStateComponentName", "RobotStateComponent");
120  defineOptionalProperty<std::string>("CameraNodeName", "DepthCamera", "Name of the robot node for the input camera");
121  defineOptionalProperty<bool>("FilterWithWorkspacePolygonActive", true, "Whether to use the WorkspacePolygon for filtering keypoints.");
122  defineOptionalProperty<std::string>("WorkspacePolygon", "-5000,-5000;5000,-5000;5000,5000;-5000,5000;-5000,-5000",
123  "A string that describes a polygon which represents the workspace of the robot.\n"
124  "Every keypoint outside of this polygon will be masked out.\n"
125  "Every point is seperated by a ';' (semicolon) and every point is described as 'x-value, y-value' (comma-seperated).\n"
126  "The last point must be identical to the first point.");
127  defineOptionalProperty<int>("MinimalAmountKeypoints", 5, "Minimal amount of keypoints per person. Detected persons with less valid keypoints will be discarded.");
128  defineOptionalProperty<bool>("ReportOnlyNearestPerson", false, "If true, only one person is reported in the 3DTopic. The reported person is the nearest person to the robot.");
129  defineOptionalProperty<bool>("ActivateOnStartup", true, "If true, poseEstimation-tasks are started after starting the component. If false, the component idles.");
130 
131  defineOptionalProperty<std::string>("Topic_Dimensions", "480x360", "Only for: 'Mode'='FromTopic'!! The dimensions of the image whose keypoints are reported over the topic.");
132  }
133  };
134 
135 
136  /**
137  * @defgroup Component-OpenPoseEstimation OpenPoseEstimation
138  * @ingroup VisionX-Components
139  * A description of the component OpenPoseEstimation.
140  *
141  * @class OpenPoseEstimation
142  * @ingroup Component-OpenPoseEstimation
143  * @brief Brief description of class OpenPoseEstimation.
144  *
145  * Detailed description of class OpenPoseEstimation.
146  */
149  public OpenPoseEstimationInterface,
150  virtual public armarx::ArVizComponentPluginUser
151  {
152  public:
153  using PoseKeypoints = op::Array<float>;
154 
155  /**
156  * @see armarx::ManagedIceObject::getDefaultName()
157  */
158  std::string getDefaultName() const override
159  {
160  return "OpenPoseEstimation";
161  }
162 
163  void start(const Ice::Current& = Ice::emptyCurrent) override;
164  void stop(const Ice::Current& = Ice::emptyCurrent) override;
165  void start3DPoseEstimation(const Ice::Current& = Ice::emptyCurrent) override;
166  void stop3DPoseEstimation(const Ice::Current& = Ice::emptyCurrent) override;
167 
168  /**
169  * @see PropertyUser::createPropertyDefinitions()
170  */
172  static void Render2DResultImage(const CByteImage& inputImage, const CByteImage& maskedInputImage, KeypointManagerPtr keypointManager, CByteImage& resultImage, op::PoseModel poseModel, float renderThreshold, int brightnessIncrease = 100);
173  static void Render2DResultImage(const CByteImage& inputImage, const CByteImage& maskedInputImage, PoseKeypoints& keypoints, CByteImage& resultImage, op::PoseModel poseModel, float renderThreshold, int brightnessIncrease = 100);
174  static void VisualizeTransparentImageMask(CByteImage& resultImage, const CByteImage& maskedInputImage, int brightnessIncrease, const CByteImage& inputImage);
175 
176  protected:
177  // ImageProcessor interface
178  void onInitImageProcessor() override;
179  void onConnectImageProcessor() override;
180  void onDisconnectImageProcessor() override;
181  void onExitImageProcessor() override;
182  void process() override;
183 
184  KeypointManagerPtr generate2DKeypoints(PoseKeypoints& keypoints, const CByteImage& rgbImage) const;
186  void calculate2DFromTopic();
190  void filterToNearest();
191  void visualize3DKeypoints();
192 
193  int getMedianDepthFromImage(int x, int y, int radius) const;
194  void maskOutBasedOnDepth(CByteImage& image, int maxDepth);
195  DrawColor24Bit getDominantColorOfPatch(const CByteImage& image, const Vec2d& point, int windowSize = 10) const;
196 
197  //Texting interface
198  void onMessage(const Texting::TextMessage& text, const Ice::Current& = Ice::emptyCurrent) override;
199 
200  private:
201  // Meta (Properties)
203  std::string providerName;
204  int radius;
205  bool useDistortionParameters;
206  bool reportOnlyNearestPerson;
207  bool filterWithWorkspacePolygonActive;
208  std::string cameraNodeName;
209  Polygon2D workspacePolygon;
210  int minimalValidKeypoints;
211  float renderThreshold;
212 
213  // Robot
214  RobotStateComponentInterfacePrx robotStateInterface;
215  VirtualRobot::RobotPtr localRobot;
216 
217  // Keypoints
218  KeypointManagerPtr keypointManager;
219  std::mutex keypointManagerMutex;
220 
221  // ImageBuffer und ImageInformations
222  CByteImage** imageBuffer;
223  CByteImage* rgbImageBuffer, *maskedrgbImageBuffer;
224  std::mutex rgbImageBufferMutex;
225  CByteImage* depthImageBuffer;
226  std::mutex depthImageBufferMutex;
227  CByteImage** openPoseResultImage;
228  std::mutex resultImageBufferMutex;
229  visionx::ImageProviderInfo imageProviderInfo;
230  armarx::MetaInfoSizeBasePtr imageMetaInfo;
231  unsigned int numImages;
232 
233  // SecondHandsTopic
234  ImageKeypointBufferPtr imageKeypointBuffer;
235  visionx::ImageDimension incomingKeypointDimensions;
236 
237  // Calibrations (IVT-Objects)
238  const CCalibration* calibration = nullptr;
239  CStereoCalibration* stereoCalibration = nullptr;
240 
241  // Visualization
242  armarx::DebugDrawerInterfacePrx debugDrawerTopic;
243  std::string layerName;
244  int layerCounter = 0;
245 
246  // Topics
247  OpenPose2DListenerPrx listener2DPrx;
248  OpenPose3DListenerPrx listener3DPrx;
249 
250  // Threads and program flow information
253  bool running2D;
254  bool running3D;
255  void run();
256  bool imageUpdated; // Is true, if new images are available (when mode is 'FromTopic' this also means that corresponding keypoints are available)
257  long timeProvidedImage; // Contains the timestamp of the currently available images (when mode is 'FromTopic' this is also the timestamp of the corresponding keypoints)
258 
259  // OpenPose
260  std::shared_ptr<op::ScaleAndSizeExtractor> scaleAndSizeExtractor;
261  std::shared_ptr<op::CvMatToOpInput> cvMatToOpInput;
262  std::shared_ptr<op::CvMatToOpOutput> cvMatToOpOutput;
263  std::shared_ptr<op::PoseExtractorCaffe> poseExtractorCaffe;
264  std::shared_ptr<op::OpOutputToCvMat> opOutputToCvMat;
265  void setupOpenPoseEnvironment();
266  PoseKeypoints getPoseKeypoints(CByteImage* imageBuffer);
267  op::PoseModel poseModel;
268 
269  // ErrorCounters
270  std::uint64_t timeoutCounter2d{0};
271  std::uint64_t readErrorCounter2d{0};
272  std::uint64_t sucessCounter2d{0};
273  };
274 }
ArVizComponentPlugin.h
armarx::OpenPoseEstimation::Render2DResultImage
static void Render2DResultImage(const CByteImage &inputImage, const CByteImage &maskedInputImage, KeypointManagerPtr keypointManager, CByteImage &resultImage, op::PoseModel poseModel, float renderThreshold, int brightnessIncrease=100)
Definition: OpenPoseEstimation.cpp:464
armarx::OpenPoseEstimation::start3DPoseEstimation
void start3DPoseEstimation(const Ice::Current &=Ice::emptyCurrent) override
Definition: OpenPoseEstimation.cpp:675
visionx
ArmarX headers.
Definition: OpenPoseStressTest.h:38
armarx::FromStereoImage
@ FromStereoImage
Definition: OpenPoseEstimation.h:62
visionx::ImageProcessor
The ImageProcessor class provides an interface for access to ImageProviders via Ice and shared memory...
Definition: ImageProcessor.h:87
armarx::OpenPoseEstimation::stop
void stop(const Ice::Current &=Ice::emptyCurrent) override
Definition: OpenPoseEstimation.cpp:664
armarx::OpenPoseEstimation::PoseKeypoints
op::Array< float > PoseKeypoints
Definition: OpenPoseEstimation.h:153
armarx::OpenPoseEstimation::onInitImageProcessor
void onInitImageProcessor() override
Setup the vision component.
Definition: OpenPoseEstimation.cpp:75
armarx::KeypointManagerPtr
std::shared_ptr< KeypointManager > KeypointManagerPtr
Definition: KeypointManager.h:159
armarx::PropertyDefinitionContainer::prefix
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
Definition: PropertyDefinitionContainer.h:333
GfxTL::Vec2d
VectorXD< 2, double > Vec2d
Definition: VectorXD.h:694
armarx::KeypointObjectPtr
std::shared_ptr< KeypointObject > KeypointObjectPtr
Definition: KeypointManager.h:124
armarx::OpenPoseEstimation::process
void process() override
Process the vision component.
Definition: OpenPoseEstimation.cpp:250
armarx::OpenPoseEstimation::onExitImageProcessor
void onExitImageProcessor() override
Exit the ImapeProcessor component.
Definition: OpenPoseEstimation.cpp:246
armarx::ImageKeypointBufferPtr
std::shared_ptr< ImageKeypointBuffer > ImageKeypointBufferPtr
Definition: ImageKeypointBuffer.h:92
visionx::ImageProcessorPropertyDefinitions::ImageProcessorPropertyDefinitions
ImageProcessorPropertyDefinitions(std::string prefix)
Definition: ImageProcessor.h:65
RunningTask.h
armarx::OpenPoseEstimation::generate2DKeypoints
KeypointManagerPtr generate2DKeypoints(PoseKeypoints &keypoints, const CByteImage &rgbImage) const
Definition: OpenPoseEstimation.cpp:843
armarx::OpenPoseEstimationMode
OpenPoseEstimationMode
Definition: OpenPoseEstimation.h:59
armarx::OpenPoseEstimation::start
void start(const Ice::Current &=Ice::emptyCurrent) override
Definition: OpenPoseEstimation.cpp:649
armarx::OpenPoseEstimation
Brief description of class OpenPoseEstimation.
Definition: OpenPoseEstimation.h:147
armarx::OpenPoseEstimation::getDefaultName
std::string getDefaultName() const override
Definition: OpenPoseEstimation.h:158
visionx::ImageProviderInfo
Definition: ImageProcessor.h:466
armarx::OpenPoseEstimation::VisualizeTransparentImageMask
static void VisualizeTransparentImageMask(CByteImage &resultImage, const CByteImage &maskedInputImage, int brightnessIncrease, const CByteImage &inputImage)
Definition: OpenPoseEstimation.cpp:506
armarx::OpenPoseEstimation::onConnectImageProcessor
void onConnectImageProcessor() override
Implement this method in the ImageProcessor in order execute parts when the component is fully initia...
Definition: OpenPoseEstimation.cpp:134
armarx::ArVizComponentPluginUser
Provides a ready-to-use ArViz client arviz as member variable.
Definition: ArVizComponentPlugin.h:36
ImageProcessor.h
armarx::OpenPoseEstimation::filterKeypointsBasedOnWorkspacePolygon
void filterKeypointsBasedOnWorkspacePolygon(KeypointObjectPtr object)
Definition: OpenPoseEstimation.cpp:889
armarx::FromTopic
@ FromTopic
Definition: OpenPoseEstimation.h:63
armarx::Polygon2D
Definition: Util.h:48
armarx::OpenPoseEstimation::getDominantColorOfPatch
DrawColor24Bit getDominantColorOfPatch(const CByteImage &image, const Vec2d &point, int windowSize=10) const
Definition: OpenPoseEstimation.cpp:739
Component.h
armarx::OpenPoseEstimation::calculate2DFromOpenPose
void calculate2DFromOpenPose()
Definition: OpenPoseEstimation.cpp:916
openpose_body_25.h
armarx::OpenPoseEstimation::onDisconnectImageProcessor
void onDisconnectImageProcessor() override
Implement this method in the ImageProcessor in order execute parts when the component looses network ...
Definition: OpenPoseEstimation.cpp:230
armarx::OpenPoseEstimationPropertyDefinitions::OpenPoseEstimationPropertyDefinitions
OpenPoseEstimationPropertyDefinitions(std::string prefix)
Definition: OpenPoseEstimation.h:74
armarx::OpenPoseEstimation::calculate3DFromDepthImage
void calculate3DFromDepthImage(KeypointManagerPtr manager)
Definition: OpenPoseEstimation.cpp:975
armarx::OpenPoseEstimation::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: OpenPoseEstimation.cpp:69
armarx::human::pose::model::openpose_body_25::ModelId
const std::string ModelId
Definition: openpose_body_25.h:30
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::OpenPoseEstimation::visualize3DKeypoints
void visualize3DKeypoints()
Definition: OpenPoseEstimation.cpp:1064
visionx::ImageProcessorPropertyDefinitions
Definition: ImageProcessor.h:61
armarx::OpenPoseEstimation::onMessage
void onMessage(const Texting::TextMessage &text, const Ice::Current &=Ice::emptyCurrent) override
Definition: OpenPoseEstimation.cpp:788
IceInternal::ProxyHandle<::IceProxy::armarx::RobotStateComponentInterface >
armarx::OpenPoseEstimationPropertyDefinitions
Definition: OpenPoseEstimation.h:70
armarx::OpenPoseEstimation::calculate3DFromStereoImage
void calculate3DFromStereoImage(KeypointManagerPtr manager)
Definition: OpenPoseEstimation.cpp:1037
armarx::OpenPoseEstimation::getMedianDepthFromImage
int getMedianDepthFromImage(int x, int y, int radius) const
Definition: OpenPoseEstimation.cpp:1139
armarx::OpenPoseEstimation::filterToNearest
void filterToNearest()
Definition: OpenPoseEstimation.cpp:911
armarx::OpenPoseEstimation::maskOutBasedOnDepth
void maskOutBasedOnDepth(CByteImage &image, int maxDepth)
Definition: OpenPoseEstimation.cpp:706
armarx::PropertyDefinitionBase::eModifiable
@ eModifiable
Definition: PropertyDefinitionInterface.h:57
armarx::OpenPoseEstimation::stop3DPoseEstimation
void stop3DPoseEstimation(const Ice::Current &=Ice::emptyCurrent) override
Definition: OpenPoseEstimation.cpp:690
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:18
armarx::FromDepthImage
@ FromDepthImage
Definition: OpenPoseEstimation.h:61
armarx::OpenPoseEstimation::calculate2DFromTopic
void calculate2DFromTopic()
Definition: OpenPoseEstimation.cpp:957
RobotStateComponent.h