Advertisement
Guest User

Untitled

a guest
Apr 6th, 2017
233
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.37 KB | None | 0 0
  1. #include <ros/ros.h>
  2.  
  3. #include <opencv2/objdetect/objdetect.hpp>
  4. #include <opencv2/highgui/highgui.hpp>
  5. #include <opencv2/imgproc/imgproc.hpp>
  6.  
  7. #include <image_transport/image_transport.h>
  8. #include <cv_bridge/cv_bridge.h>
  9. #include <sensor_msgs/image_encodings.h>
  10.  
  11. #include <stdint.h>
  12. #include <unistd.h>
  13.  
  14. #include <std_msgs/Bool.h>
  15. #include <std_msgs/Empty.h>
  16. #include <std_msgs/MultiArrayLayout.h>
  17. #include <std_msgs/MultiArrayDimension.h>
  18. #include <std_msgs/Int8MultiArray.h>
  19. #include <meccanoid_tx1/meccanoid_face_location.h>
  20.  
  21. using meccanoid_tx1::meccanoid_face_location;
  22.  
  23. /*
  24. / Face detector class
  25. */
  26. class MeccanoidFaceDetector{
  27.   public:
  28.     /*
  29.     / Constructor
  30.     */
  31.     MeccanoidFaceDetector(ros::Publisher pub, ros::Publisher pub2, ros::Publisher pub3, bool showIm){
  32.             faceLocationPublisher = pub;
  33.             arduinoPositionPublisher = pub2;
  34.             arduinoArmPublisher = pub3;
  35.     everyOther = true;
  36.     readyForAFace = true;
  37.     pos.push_back(0x77);
  38.     pos.push_back(0x87);
  39.         showImages = showIm;
  40.     FOV_WIDTH = 640;
  41.     FOV_HEIGHT = 480;
  42.         if (!faceLocationClassifier.load("/home/ubuntu/code/meccanoid_ws/res/haarcascades/haarcascade_frontalface_alt.xml")){
  43.             ROS_INFO("failed to load classifier xml,"
  44.              " make sure the correct path is specified in meccanoid_face_detection.cpp");
  45.         }
  46.     };
  47.  
  48.     /*
  49.     / Callback which publishes face locations is faces are detected
  50.     */
  51.     void faceDetectorCallback(const sensor_msgs::ImageConstPtr &msg){
  52.         if(!isNavigating){
  53.             try{
  54.                 image = cv_bridge::toCvCopy(msg,sensor_msgs::image_encodings::BGR8)->image;
  55.                 if (detectFaces()){
  56.                     publishFaceLocations();
  57.                     ROS_INFO("detected a face!");
  58.                     callWave();
  59.                     readyForAFace = false;
  60.                 }else{
  61.             publishNoFaceLocations();
  62.         }
  63.                 cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image);
  64.                 //cv::imshow("image_window", image);
  65.                 cv::waitKey(30);
  66.             }catch (cv_bridge::Exception &e){
  67.                 ROS_ERROR("could not convert image");
  68.             }
  69.         }
  70.     }
  71.  
  72.     /*
  73.     / Callback assigning 'is navigating' mode
  74.     */
  75.     void isNavigatingCallback(const std_msgs::Bool::ConstPtr &msg){
  76.         isNavigating = msg->data;
  77.     }
  78.  
  79.     /*
  80.     / Callback assigning 'readyForAFace'
  81.     */
  82.     void waveDoneCallback(const std_msgs::Empty& cmd_msg) {
  83.         readyForAFace = true;
  84.         ROS_INFO("Set readyForFace to true!");
  85.     }
  86.  
  87.     void callWave() {
  88.         std_msgs::Empty waveMsg;
  89.         arduinoArmPublisher.publish(waveMsg);
  90.         ROS_INFO("Called wave!");
  91.     }
  92.  
  93.   private:
  94.     ros::Publisher faceLocationPublisher;
  95.     ros::Publisher arduinoPositionPublisher;
  96.     ros::Publisher arduinoArmPublisher;
  97.     std::vector<cv::Rect> faceLocations;
  98.     cv::CascadeClassifier faceLocationClassifier;
  99.     cv::Mat image;
  100.     std::vector<uint8_t> pos;
  101.     bool isNavigating;
  102.     bool showImages;
  103.     bool everyOther;
  104.     bool readyForAFace;
  105.     int FOV_WIDTH;
  106.     int FOV_HEIGHT;
  107.  
  108.     /*
  109.     / Stores face locations in 'faceLocations' as cv::Rect objects.
  110.     */
  111.     bool detectFaces(){
  112.  
  113.         if (readyForAFace) {
  114.                 faceLocationClassifier.detectMultiScale(image, faceLocations, 1.09, 3, 0 | CV_HAAR_SCALE_IMAGE, cv::Size(40, 40));
  115.                 if (faceLocations.size() > 0) {
  116.                     if(showImages){
  117.                         for (size_t i = 0; i < faceLocations.size(); i++){
  118.                             cv::rectangle(image, faceLocations[i], cv::Scalar(0, 0, 255), 2);
  119.                         }
  120.                     }
  121.                     return true;
  122.                 }
  123.                 return false;
  124.             }
  125.         }
  126.  
  127.     void resetPos(){
  128.         pos.clear();
  129.         pos.push_back(0x77);
  130.         pos.push_back(0x87);
  131.     }
  132.  
  133.    
  134.     std::vector<uint8_t> mapPixelToPosition(std::vector<int> centerPoint){
  135.     int dx,dy;
  136.     //float range_per_pixel = 0.15; //0.36;
  137.  
  138.     float range_per_x = (0xA0-0x4E)/640.0;
  139.     float range_per_y = (0xA5-0x87)/(480.0/2); // di-vision by 2 to increase range of motion up/down   
  140.     dx = (centerPoint[0] - FOV_WIDTH/2)*range_per_x;
  141.     dy = (centerPoint[1] - FOV_HEIGHT/2)*range_per_y;
  142.     resetPos();
  143.  
  144.     pos[0] = ((pos[0]-dx) < 0x00 || (pos[0]-dx) > 0xEF) ? 0x77 : pos[0]-dx;
  145.     pos[1] = ((pos[1]-dy) < 0x00 || (pos[1]-dy) > 0xEF) ? 0x77 : pos[1]-dy;
  146.  
  147.     //pos[0] -= dx*range_per_x;
  148.     //pos[1] -= dy*range_per_y;
  149.  
  150.     return pos;
  151.     }
  152.  
  153.     std::vector<int> getCenterPoint(cv::Rect face){
  154.     int x,y;
  155.     std::vector<int> centerPoint;
  156.     centerPoint.push_back(face.x + (face.width / 2));
  157.     centerPoint.push_back(face.y + (face.height / 2));
  158.     return centerPoint;
  159.     }
  160.  
  161.     cv::Rect getLargestFace(){
  162.     int idx = 0,w,h,largest = -1;
  163.     for (size_t i = 0; i < faceLocations.size(); i++){
  164.             w = faceLocations[i].width;
  165.             h = faceLocations[i].height;
  166.            
  167.         if(w*h > largest){
  168.         idx = i;
  169.         largest = w*h;
  170.         }
  171.     }
  172.     return faceLocations[idx];
  173.     }
  174.  
  175.  
  176.     /*
  177.     / Publishes face locations as meccanoid_face_location messages
  178.     */
  179.     void publishFaceLocations(){
  180.     cv::Rect largestFace = getLargestFace();
  181.     std::vector<int> centerPoint = getCenterPoint(largestFace);
  182.     std::vector<uint8_t> positions = mapPixelToPosition(centerPoint);
  183.  
  184.     std_msgs::Int8MultiArray position_msg;
  185.     position_msg.data.clear();
  186.     position_msg.data.push_back(positions[0]);
  187.     position_msg.data.push_back(positions[1]);
  188.  
  189.     arduinoPositionPublisher.publish(position_msg);
  190.     }
  191.  
  192.     void publishNoFaceLocations(){
  193.     resetPos();
  194.     std_msgs::Int8MultiArray position_msg;
  195.     position_msg.data.clear();
  196.     position_msg.data.push_back(pos[0]);
  197.     position_msg.data.push_back(pos[1]);
  198.     arduinoPositionPublisher.publish(position_msg);
  199.     }
  200.  
  201. };
  202.  
  203.  
  204. /*
  205. / Meccanoid face detection node main
  206. */
  207. int main(int argc, char **argv)
  208. {
  209.     // init ros and set showImage param
  210.     bool showImages = true;
  211.     ros::init(argc, argv, "meccanoid_face_detection");
  212.     ros::NodeHandle nodeHandle;
  213.  
  214.     // set up face location publisher
  215.     ros::Publisher faceLocationPublisher = nodeHandle.advertise<meccanoid_face_location>("face_location", 10);
  216.  
  217.     ros::Publisher arduinoPositionPublisher = nodeHandle.advertise<std_msgs::Int8MultiArray>("face_location_pos", 10000);
  218.  
  219.     ros::Publisher arduinoArmPublisher = nodeHandle.advertise<std_msgs::Empty>("servo", 10);
  220.  
  221.     // set up face detector
  222.     MeccanoidFaceDetector faceDetector(faceLocationPublisher,arduinoPositionPublisher, arduinoArmPublisher, showImages);
  223.    
  224.  
  225.     // set up image subscriber
  226.     image_transport::ImageTransport it(nodeHandle);
  227.    
  228.     image_transport::Subscriber faceLocationSubscriber = it.subscribe("/rgb/image_raw", 1,
  229.     &MeccanoidFaceDetector::faceDetectorCallback, &faceDetector);  
  230.    
  231.     //image_transport::Subscriber faceLocationSubscriber = it.subscribe("/zed/rgb/image_raw_color", 1,
  232.     //                                    &MeccanoidFaceDetector::faceDetectorCallback, &faceDetector);
  233.  
  234.     ros::Subscriber isNavigatingSubscriber = nodeHandle.subscribe("/is_navigating", 1,
  235.                                         &MeccanoidFaceDetector::isNavigatingCallback, &faceDetector);
  236.  
  237.     //Subscriber for readyForAFace
  238.     ros::Subscriber waveDoneSubscriber = nodeHandle.subscribe("/wave_done", 1,
  239.                                         &MeccanoidFaceDetector::waveDoneCallback, &faceDetector);
  240.  
  241.     // set up image view
  242.     if(showImages){
  243.         cv::namedWindow("image_window");
  244.         cv::startWindowThread();
  245.     }
  246.    
  247.     // start ros blocking spin()
  248.     ros::spin();
  249.    
  250.     // kill image view
  251.     if(showImages){
  252.         cv::destroyWindow("image_window");
  253.     }
  254. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement