head_detector_node.cpp
Go to the documentation of this file.
00001 
00061 #ifdef __LINUX__
00062 #include "cob_people_detection/head_detector_node.h"
00063 #include "cob_vision_utils/GlobalDefines.h"
00064 #else
00065 #endif
00066 
00067 // OpenCV
00068 #include <opencv2/opencv.hpp>
00069 #include <cv_bridge/cv_bridge.h>
00070 #include <sensor_msgs/image_encodings.h>
00071 
00072 // point cloud
00073 #include <pcl/point_types.h>
00074 #include <pcl_ros/point_cloud.h>
00075 
00076 // timer
00077 #include <cob_people_detection/timer.h>
00078 
00079 using namespace ipa_PeopleDetector;
00080 
00081 HeadDetectorNode::HeadDetectorNode(ros::NodeHandle nh) :
00082         node_handle_(nh)
00083 {
00084         data_directory_ = ros::package::getPath("cob_people_detection") + "/common/files/";
00085 
00086         // Parameters
00087         double depth_increase_search_scale; // The factor by which the search window is scaled between the subsequent scans
00088         int depth_drop_groups; // Minimum number (minus 1) of neighbor rectangles that makes up an object.
00089         int depth_min_search_scale_x; // Minimum search scale x
00090         int depth_min_search_scale_y; // Minimum search scale y
00091         std::cout << "\n--------------------------\nHead Detector Parameters:\n--------------------------\n";
00092         node_handle_.param("data_directory", data_directory_, data_directory_);
00093         std::cout << "data_directory = " << data_directory_ << "\n";
00094         node_handle_.param("fill_unassigned_depth_values", fill_unassigned_depth_values_, true);
00095         std::cout << "fill_unassigned_depth_values = " << fill_unassigned_depth_values_ << "\n";
00096         node_handle_.param("depth_increase_search_scale", depth_increase_search_scale, 1.1);
00097         std::cout << "depth_increase_search_scale = " << depth_increase_search_scale << "\n";
00098         node_handle_.param("depth_drop_groups", depth_drop_groups, 68);
00099         std::cout << "depth_drop_groups = " << depth_drop_groups << "\n";
00100         node_handle_.param("depth_min_search_scale_x", depth_min_search_scale_x, 20);
00101         std::cout << "depth_min_search_scale_x = " << depth_min_search_scale_x << "\n";
00102         node_handle_.param("depth_min_search_scale_y", depth_min_search_scale_y, 20);
00103         std::cout << "depth_min_search_scale_y = " << depth_min_search_scale_y << "\n";
00104         node_handle_.param("display_timing", display_timing_, false);
00105         std::cout << "display_timing = " << display_timing_ << "\n";
00106 
00107         // initialize head detector
00108         head_detector_.init(data_directory_, depth_increase_search_scale, depth_drop_groups, depth_min_search_scale_x, depth_min_search_scale_y);
00109 
00110         // advertise topics
00111         head_position_publisher_ = node_handle_.advertise<cob_perception_msgs::ColorDepthImageArray>("head_positions", 1);
00112 
00113         // subscribe to sensor topic
00114         pointcloud_sub_ = nh.subscribe("pointcloud_rgb", 1, &HeadDetectorNode::pointcloud_callback, this);
00115 
00116         std::cout << "HeadDetectorNode initialized." << std::endl;
00117 }
00118 
00119 HeadDetectorNode::~HeadDetectorNode(void)
00120 {
00121 }
00122 
00123 void HeadDetectorNode::pointcloud_callback(const sensor_msgs::PointCloud2::ConstPtr& pointcloud)
00124 {
00125 
00126         //      Timer tim;
00127         //      tim.start();
00128 
00129         // convert incoming colored point cloud to cv::Mat images
00130         cv::Mat depth_image;
00131         cv::Mat color_image;
00132         convertPclMessageToMat(pointcloud, depth_image, color_image);
00133 
00134 //              cv::Mat gray_depth(depth_image.rows, depth_image.cols, CV_32FC1);
00135 //              for (int v=0; v<depth_image.rows; ++v)
00136 //                      for (int u=0; u<depth_image.cols; ++u)
00137 //                              gray_depth.at<float>(v,u) = depth_image.at<cv::Vec3f>(v,u).val[2];
00138 //              cv::normalize(gray_depth, gray_depth, 0.f, 1.f, cv::NORM_MINMAX);
00139 //              cv::imshow("depth image", gray_depth);
00140 //              char key = cv::waitKey(1000);
00141 //              if (key == 's')
00142 //              {
00143 //                      cv::normalize(gray_depth, gray_depth, 0.f, 255.f, cv::NORM_MINMAX);
00144 //                      cv::imwrite("depth_image.png", gray_depth);
00145 //              }
00146 
00147         // detect heads in the depth image
00148         std::vector<cv::Rect> head_bounding_boxes;
00149         head_detector_.detectRangeFace(depth_image, head_bounding_boxes, fill_unassigned_depth_values_);
00150 
00151         // publish image patches from head region
00152         cob_perception_msgs::ColorDepthImageArray image_array;
00153         image_array.header = pointcloud->header;
00154         image_array.head_detections.resize(head_bounding_boxes.size());
00155         for (unsigned int i = 0; i < head_bounding_boxes.size(); i++)
00156         {
00157                 cv_bridge::CvImage cv_ptr;
00158                 image_array.head_detections[i].head_detection.x = head_bounding_boxes[i].x;
00159                 image_array.head_detections[i].head_detection.y = head_bounding_boxes[i].y;
00160                 image_array.head_detections[i].head_detection.width = head_bounding_boxes[i].width;
00161                 image_array.head_detections[i].head_detection.height = head_bounding_boxes[i].height;
00162                 cv::Mat depth_patch = depth_image(head_bounding_boxes[i]);
00163                 cv_ptr.image = depth_patch;
00164                 cv_ptr.encoding = sensor_msgs::image_encodings::TYPE_32FC3; // CV32FC3
00165                 image_array.head_detections[i].depth_image = *(cv_ptr.toImageMsg());
00166                 image_array.head_detections[i].depth_image.header = pointcloud->header;
00167                 cv::Mat color_patch = color_image(head_bounding_boxes[i]);
00168                 cv_ptr.image = color_patch;
00169                 cv_ptr.encoding = sensor_msgs::image_encodings::BGR8;
00170                 image_array.head_detections[i].color_image = *(cv_ptr.toImageMsg());
00171                 image_array.head_detections[i].color_image.header = pointcloud->header;
00172         }
00173         head_position_publisher_.publish(image_array);
00174 
00175         if (display_timing_ == true)
00176                 ROS_INFO("%d HeadDetection: Time stamp of pointcloud message: %f. Delay: %f.", pointcloud->header.seq, pointcloud->header.stamp.toSec(),
00177                                 ros::Time::now().toSec() - pointcloud->header.stamp.toSec());
00178         //      ROS_INFO("Head Detection took %f ms.", tim.getElapsedTimeInMilliSec());
00179 }
00180 
00181 unsigned long HeadDetectorNode::convertPclMessageToMat(const sensor_msgs::PointCloud2::ConstPtr& pointcloud, cv::Mat& depth_image, cv::Mat& color_image)
00182 {
00183         pcl::PointCloud < pcl::PointXYZRGB > depth_cloud; // point cloud
00184         pcl::fromROSMsg(*pointcloud, depth_cloud);
00185         depth_image.create(depth_cloud.height, depth_cloud.width, CV_32FC3);
00186         color_image.create(depth_cloud.height, depth_cloud.width, CV_8UC3);
00187         uchar* depth_image_ptr = (uchar*)depth_image.data;
00188         uchar* color_image_ptr = (uchar*)color_image.data;
00189         for (int v = 0; v < (int)depth_cloud.height; v++)
00190         {
00191                 int depth_base_index = depth_image.step * v;
00192                 int color_base_index = color_image.step * v;
00193                 for (int u = 0; u < (int)depth_cloud.width; u++)
00194                 {
00195                         int depth_index = depth_base_index + 3 * u * sizeof(float);
00196                         float* depth_data_ptr = (float*)(depth_image_ptr + depth_index);
00197                         int color_index = color_base_index + 3 * u * sizeof(uchar);
00198                         uchar* color_data_ptr = (uchar*)(color_image_ptr + color_index);
00199                         pcl::PointXYZRGB point_xyz = depth_cloud(u, v);
00200                         depth_data_ptr[0] = point_xyz.x;
00201                         depth_data_ptr[1] = point_xyz.y;
00202                         depth_data_ptr[2] = (isnan(point_xyz.z)) ? 0.f : point_xyz.z;
00203                         color_data_ptr[0] = point_xyz.r;
00204                         color_data_ptr[1] = point_xyz.g;
00205                         color_data_ptr[2] = point_xyz.b;
00206                         //if (u%100 == 0) std::cout << "u" << u << " v" << v << " z" << data_ptr[2] << "\n";
00207                 }
00208         }
00209         return ipa_Utils::RET_OK;
00210 }
00211 
00212 //#######################
00213 //#### main programm ####
00214 int main(int argc, char** argv)
00215 {
00216         // Initialize ROS, specify name of node
00217         ros::init(argc, argv, "head_detector");
00218 
00219         // Create a handle for this node, initialize node
00220         ros::NodeHandle nh("~");
00221 
00222         // Create HeadDetectorNode class instance
00223         HeadDetectorNode head_detector_node(nh);
00224 
00225         // Create action nodes
00226         //DetectObjectsAction detect_action_node(object_detection_node, nh);
00227         //AcquireObjectImageAction acquire_image_node(object_detection_node, nh);
00228         //TrainObjectAction train_object_node(object_detection_node, nh);
00229 
00230         ros::spin();
00231 
00232         return 0;
00233 }


cob_people_detection
Author(s): Richard Bormann , Thomas Zwölfer
autogenerated on Mon May 6 2019 02:32:06