pose_recognition.cpp
Go to the documentation of this file.
1 
22 #include <ros/console.h>
23 #include <ros/ros.h>
24 #include <pcl/filters/filter.h>
25 #include <pcl/filters/passthrough.h>
27 #include <asr_halcon_bridge/halcon_pointcloud.h>
28 
29 #include <pcl/common/common.h>
30 #include <ros/package.h>
31 
32 #include "pose_recognition.h"
33 #include "util.h"
34 
35 
37 
38 PoseRecognition::PoseRecognition(HalconCpp::HImage &scene_image, HalconCpp::HImage &scene_image_mono, pcl::PointCloud<pcl::PointXYZ>::Ptr &point_cloud_with_guppy, ObjectDescriptor *obj_desc, int median_points_offset, double samplingDistance, double keypointFraction, bool eval, int max_instances)
39  : scene_image_(scene_image), scene_image_mono_(scene_image_mono),
40  point_cloud_with_guppy_(point_cloud_with_guppy), obj_desc_(obj_desc), max_instances_(max_instances), median_points_offset_(median_points_offset),
41  sampling_distance_(samplingDistance), keypoint_fraction_(keypointFraction), eval_(eval) { }
42 
43 
45 {
46  for (unsigned int i = 0; i < results_.size(); i++) {
47  delete results_.at(i);
48  }
49 }
50 
52  std::ofstream object_ofstream;
53  std::string path = PACKAGE_PATH + "/" + OUTPUT_EVALUATION_DIR + "/" + obj_desc_->getName() + "_times.txt";
54  if (eval_) {
55  object_ofstream.open (path.c_str(), std::ofstream::out | std::ofstream::app);
56  }
57  ros::Time find_poses_start = ros::Time::now();
58 
59  //find object in 2D
60  findTexture();
61 
62  ros::Time textures_found = ros::Time::now();
63  if (eval_) {
64  object_ofstream << textures_found - find_poses_start;
65  }
66  for (unsigned int i = 0; i < results_.size(); i++) {
67  if (eval_) {
68  object_ofstream << "#";
69  }
70  ros::Time loop_entry = ros::Time::now();
71 
72  //reduce cloud
73  if (reducePointCloud(i)) {
74  ros::Time cloud_reduced = ros::Time::now();
75  if (eval_) {
76  object_ofstream << cloud_reduced - loop_entry << ";";
77  }
78 
79  //find object
80  if (findModelInCloud(i)) {
81  ros::Time model_found = ros::Time::now();
82  if (eval_) {
83  object_ofstream << model_found - cloud_reduced << ";";
84  }
85 
86  if (sqrt(pow(results_.at(i)->getPose()[0] - results_.at(i)->getTexPoint3D()[0], 2.0) + pow(results_.at(i)->getPose()[1] - results_.at(i)->getTexPoint3D()[1], 2.0) + pow(results_.at(i)->getPose()[2] - results_.at(i)->getTexPoint3D()[2], 2.0)) < (obj_desc_->getDiameter() * 0.5)) {
87  results_.at(i)->setModelFound();
88  //find rotation
89  adjustRotation(i);
90  if (eval_) {
91  object_ofstream << ros::Time::now() - model_found;
92  }
93 
94  }
95  }
96  }
97  }
98  if (eval_) {
99  object_ofstream << std::endl;
100  object_ofstream.close();
101  }
102 }
103 
104 
106 {
107  for (unsigned int i = 0; i < obj_desc_->getModelViewDescriptors().size(); i++) {
108  HalconCpp::HTuple score;
109  if (obj_desc_->getModelViewDescriptors().at(i).getUseColor()) {
110  scene_image_.FindUncalibDescriptorModel(obj_desc_->getModelViewDescriptors().at(i).getDescModel(), HalconCpp::HTuple(), HalconCpp::HTuple(), HalconCpp::HTuple(), HalconCpp::HTuple(), obj_desc_->getModelViewDescriptors().at(i).getScore2D(), max_instances_, "inlier_ratio", &score);
111  } else {
112  scene_image_mono_.FindUncalibDescriptorModel(obj_desc_->getModelViewDescriptors().at(i).getDescModel(), HalconCpp::HTuple(), HalconCpp::HTuple(), HalconCpp::HTuple(), HalconCpp::HTuple(), obj_desc_->getModelViewDescriptors().at(i).getScore2D(), max_instances_, "inlier_ratio", &score);
113  }
114  if (score.Length() > 0) {
115  for (int j = 0; j < score.Length(); j++) {
116  HalconCpp::HTuple matrix_tuple = obj_desc_->getModelViewDescriptors().at(i).getDescModel().GetDescriptorModelResults(j, "homography");
117  HalconCpp::HHomMat2D matrix;
118  matrix.SetFromTuple(matrix_tuple);
119 
120  double trans_x, trans_y, trans_w;
121  trans_x = matrix.ProjectiveTransPoint2d(obj_desc_->getModelViewDescriptors().at(i).getVerticalTexOffset(), obj_desc_->getModelViewDescriptors().at(i).getHorizontalTexOffset(), 1, &trans_y, &trans_w);
122 
123  int row = (int) (trans_x / trans_w);
124  int column = (int) (trans_y / trans_w);
125 
126  results_.push_back(new RecognitionResult(i, (double)score[j], matrix, Eigen::Vector2i(row, column)));
127  ROS_DEBUG_STREAM("Texture of " << obj_desc_->getName() << " (instance " << j << ") found at (" << row << ", " << column << ")");
128  if ((int)(results_.size()) >= max_instances_) {
129  return;
130  }
131  }
132  }
133  }
134 }
135 
136 bool PoseRecognition::reducePointCloud(int result_index)
137 {
138  double radius = obj_desc_->getDiameter() / 2;
139  int image_height = scene_image_.Height();
140  int image_width = scene_image_.Width();
141 
142  pcl::PointXYZ min;
143  pcl::PointXYZ max;
144  pcl::getMinMax3D(*point_cloud_with_guppy_, min, max);
145 
146  int row = results_.at(result_index)->getTexPoint()[0];
147  int column = results_.at(result_index)->getTexPoint()[1];
148 
149  std::vector<pcl::PointXYZ> points;
150  int offsets[10] = {0, 0, median_points_offset_, 0, 0, -1 * median_points_offset_, -1 * median_points_offset_, 0, 0, median_points_offset_ };
151 
152  for (int i = 0; i < 5; i++) {
153  if (row - median_points_offset_ < 0 || column - median_points_offset_ < 0 || row + median_points_offset_ >= image_height || column + median_points_offset_ >= image_width) {
154  return false;
155  }
156  pcl::PointXYZ current_point = findPoint3D(point_cloud_with_guppy_, (*point_cloud_with_guppy_)(column + offsets[i * 2], row + offsets[i * 2 + 1]), row + offsets[i * 2 + 1], column + offsets[i * 2], image_height, image_width);
157  if (pcl::isFinite(current_point)) {
158  points.push_back(current_point);
159  }
160  }
161 
162  if (points.size() > 0) {
163  pcl::PointXYZ median_point = computeMedian(points);
164 
165  if (pcl::isFinite(median_point)) {
166  if (median_point.x - radius > min.x) { min.x = median_point.x - radius; }
167  if (median_point.x + radius < max.x) { max.x = median_point.x + radius; }
168  if (median_point.y - radius > min.y) { min.y = median_point.y - radius; }
169  if (median_point.y + radius < max.y) { max.y = median_point.y + radius; }
170  if (median_point.z - radius > min.z) { min.z = median_point.z - radius; }
171  if (median_point.z + radius < max.z) { max.z = median_point.z + radius; }
172 
173  } else {
174  return false;
175  }
176 
177 
178  pcl::PointCloud<pcl::PointXYZ>::Ptr reduced_cloud(new pcl::PointCloud<pcl::PointXYZ>);
179 
180  pcl::PassThrough<pcl::PointXYZ> pass;
181  pass.setInputCloud (point_cloud_with_guppy_);
182  pass.setFilterFieldName ("x");
183  pass.setFilterLimits (min.x, max.x);
184  pass.filter (*reduced_cloud);
185 
186  pass.setInputCloud (reduced_cloud);
187  pass.setFilterFieldName ("y");
188  pass.setFilterLimits (min.y, max.y);
189  pass.filter (*reduced_cloud);
190 
191  results_.at(result_index)->setTexPoint3D(median_point);
192  results_.at(result_index)->setSearchCloud(reduced_cloud);
193 
194  return true;
195  }
196  return false;
197 
198 }
199 
200 bool PoseRecognition::findModelInCloud(int result_index)
201 {
202 
203  if ((results_.at(result_index)->getSearchCloud()->width * results_.at(result_index)->getSearchCloud()->height > 0)) {
204 
205  std::vector< int > index;
206  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud = results_.at(result_index)->getSearchCloud();
207  pcl::removeNaNFromPointCloud(*cloud, *cloud, index);
208 
209  results_.at(result_index)->setSearchCloud(cloud);
210  sensor_msgs::PointCloud2 p_n_cloud;
211  pcl::toROSMsg(*cloud, p_n_cloud);
212  halcon_bridge::HalconPointcloudPtr ptr = halcon_bridge::toHalconCopy(p_n_cloud);
213  HalconCpp::HObjectModel3D scene = *ptr->model;
214 
215  HalconCpp::HSurfaceMatchingResultArray result;
216  HalconCpp::HTuple *score = new HalconCpp::HTuple();
217  HalconCpp::HTuple genParamName("num_matches");
218  genParamName.Append("pose_ref_use_scene_normals");
219  HalconCpp::HTuple genParamValue(1);
220  genParamValue.Append("false");
221  HalconCpp::HPoseArray poses = scene.FindSurfaceModel(obj_desc_->getSurfaceModel(), sampling_distance_, keypoint_fraction_, obj_desc_->getScore3D(), "false", genParamName, genParamValue, score, &result);
222 
223  if ((score->Length() > 0) && ((*score)[0] >= obj_desc_->getScore3D())) {
224  bool pose_already_found = false;
225  for (int i = 0; i < result_index; i++) {
226  if ((results_.at(i)->checkModelFound()) && (sqrt(pow(results_.at(i)->getPose()[0] - poses.ConvertToTuple()[0], 2.0) + pow(results_.at(i)->getPose()[1] - poses.ConvertToTuple()[1], 2.0) + pow(results_.at(i)->getPose()[2] - poses.ConvertToTuple()[2], 2.0)) < (obj_desc_->getDiameter() * 0.5))) {
227  pose_already_found = true;
228  break;
229  }
230  }
231  if (!pose_already_found) {
232  ROS_DEBUG_STREAM("Found object " << obj_desc_->getName() << " (instance " << result_index << ") in the point cloud");
233  results_.at(result_index)->setPose(poses.ConvertToTuple());
234  results_.at(result_index)->setScore3D((*score)[0]);
235  return true;
236  } else {
237  ROS_DEBUG_STREAM("Found pose of object " << obj_desc_->getName() << " (instance " << result_index << ") was found for another instance already");
238  }
239  }
240  } else {
241  ROS_DEBUG_STREAM("Reduced point cloud of object " << obj_desc_->getName() << " (instance " << result_index << ") is empty");
242  }
243  return false;
244 }
245 
246 void PoseRecognition::adjustRotation(int result_index)
247 {
248  HalconCpp::HPose pose;
249  pose.SetFromTuple(results_.at(result_index)->getPose());
250 
251  HalconCpp::HQuaternion rotation;
252  rotation.PoseToQuat(pose);
253  rotation = rotation.QuatNormalize();
254 
255  Eigen::Vector3d location(results_.at(result_index)->getPose()[0], results_.at(result_index)->getPose()[1], results_.at(result_index)->getPose()[2]);
256 
257  //case: model is rotated around given axes
258  switch(obj_desc_->getRotationModelType()) {
260  {
261  //not implemented
262  }
264  {
265  Eigen::Vector3d texFromObjOrigin;
266  texFromObjOrigin = results_.at(result_index)->getTexPoint3D() - location;
267  texFromObjOrigin.normalize();
268 
269  double x, y, z;
270  x = rotation.QuatRotatePoint3d(obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getViewOrientation()[0], obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getViewOrientation()[1], obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getViewOrientation()[2], &y, &z);
271  Eigen::Vector3d viewOrientationFromObjOrigin(x, y, z);
272  viewOrientationFromObjOrigin.normalize();
273 
274  double dot = texFromObjOrigin.dot(viewOrientationFromObjOrigin);
275  double maxDot = dot;
276  double bestAngle = 0.0;
277  double currentAngle = obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getAxes().at(0).getAngle();
278  while (currentAngle < 360) {
279  double radians = (currentAngle) * (PI / 180);
280  HalconCpp::HQuaternion current_rot(obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getAxes().at(0).getAxis()[0], obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getAxes().at(0).getAxis()[1], obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getAxes().at(0).getAxis()[2], radians);
281 
282  double x_curr, y_curr, z_curr;
283  x_curr = current_rot.QuatRotatePoint3d(obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getViewOrientation()[0], obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getViewOrientation()[1], obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getViewOrientation()[2], &y_curr, &z_curr);
284 
285  Eigen::Vector3d vec_curr_obj(x_curr, y_curr, z_curr);
286  vec_curr_obj.normalize();
287  x_curr = rotation.QuatRotatePoint3d(vec_curr_obj[0], vec_curr_obj[1], vec_curr_obj[2], &y_curr, &z_curr);
288 
289  Eigen::Vector3d vec_curr(x_curr, y_curr, z_curr);
290  vec_curr.normalize();
291 
292  if (texFromObjOrigin.dot(vec_curr) > maxDot) {
293  maxDot = texFromObjOrigin.dot(vec_curr);
294  bestAngle = currentAngle;
295  }
296  currentAngle += obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getAxes().at(0).getAngle();
297  }
298  HalconCpp::HQuaternion quat_result(obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getAxes().at(0).getAxis()[0], obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getAxes().at(0).getAxis()[1], obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getAxes().at(0).getAxis()[2], bestAngle * (PI / 180));
299  results_.at(result_index)->setAdjustedRotation(quat_result.QuatCompose(results_.at(result_index)->getAdjustedRotation()));
300  }
301  }
302 
303  //case: model is upside-down
304  if (obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getIsInvertible()) {
305 
306  double trans_x, trans_y, trans_w;
307  trans_x = results_.at(result_index)->getTransMatrix2D().ProjectiveTransPoint2d(0, 1, 1, &trans_y, &trans_w);
308  Eigen::Vector2d upperPoint(trans_x / trans_w, trans_y / trans_w);
309  trans_x = results_.at(result_index)->getTransMatrix2D().ProjectiveTransPoint2d(0, 0, 1, &trans_y, &trans_w);
310  Eigen::Vector2d centerPoint(trans_x / trans_w, trans_y / trans_w);
311  upperPoint = upperPoint - centerPoint;
312  upperPoint.normalize();
313 
314  double x_upper, y_upper, z_upper;
315  x_upper = rotation.QuatRotatePoint3d(0, -1, 0, &y_upper, &z_upper);
316  Eigen::Vector2d upperPoint3D(x_upper, -1 * y_upper);
317  upperPoint3D.normalize();
318 
319  if (upperPoint.dot(upperPoint3D) < 0) {
320  double axis_rot_x, axis_rot_y, axis_rot_z;
321  axis_rot_x = results_.at(result_index)->getAdjustedRotation().QuatRotatePoint3d(obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getViewOrientation()[0], obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getViewOrientation()[1], obj_desc_->getModelViewDescriptors().at(results_.at(result_index)->getViewIndex()).getViewOrientation()[2], &axis_rot_y, &axis_rot_z);
322  HalconCpp::HQuaternion quat_upside_down(axis_rot_x, axis_rot_y, axis_rot_z, PI);
323  results_.at(result_index)->setAdjustedRotation(quat_upside_down.QuatCompose(results_.at(result_index)->getAdjustedRotation()));
324  }
325  }
326 }
327 
328 std::vector<RecognitionResult*> PoseRecognition::getResults() const { return results_; }
329 
331 
332 HalconCpp::HRegion PoseRecognition::getInputImageDomain() const { return scene_image_mono_.GetDomain(); }
333 
334 }
std::vector< RecognitionResult * > getResults() const
static const std::string OUTPUT_EVALUATION_DIR("eval")
pcl::PointXYZ findPoint3D(pcl::PointCloud< pcl::PointXYZ >::Ptr cloud, pcl::PointXYZ current_point, int row, int column, int image_height, int image_width)
Finds the corresponding 3D point to the given 2D point.
Definition: util.cpp:104
PoseRecognition(HalconCpp::HImage &scene_image, HalconCpp::HImage &scene_image_mono, pcl::PointCloud< pcl::PointXYZ >::Ptr &point_cloud_with_guppy, ObjectDescriptor *obj_desc, int median_points_offset, double samplingDistance, double keypointFraction, bool eval, int max_instances=1)
The constructor of this class.
TFSIMD_FORCE_INLINE const tfScalar & y() const
pcl::PointCloud< pcl::PointXYZ >::Ptr point_cloud_with_guppy_
bool reducePointCloud(int result_index)
Prepares the 3D-recognition by reducing the point cloud depending on the 2D-recognition result...
void findPoses()
Recognizes the present object instances in the scene.
bool findModelInCloud(int result_index)
Recognizes the object in the reduced 3D-scene.
TFSIMD_FORCE_INLINE const tfScalar & x() const
std::vector< ObjectViewDescriptor > getModelViewDescriptors() const
#define ROS_DEBUG_STREAM(args)
TFSIMD_FORCE_INLINE const tfScalar & z() const
Eigen::Vector3d computeMedian(std::vector< Eigen::Vector3d > points)
Computes the median of the given points.
Definition: util.cpp:67
void findTexture()
Recognizes the object in the 2D-scene.
int min(int a, int b)
void toROSMsg(const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
static Time now()
virtual ~PoseRecognition()
The destructor of this class.
void adjustRotation(int result_index)
Adjusts the rotation of the found object instance depending on its rotation-type. ...


asr_descriptor_surface_based_recognition
Author(s): Allgeyer Tobias, Hutmacher Robin, Meißner Pascal
autogenerated on Mon Dec 16 2019 03:31:15