• ROS人脸检测 使用webcam实现


    github地址https://github.com/ngunauj/facedetection

    熟悉ros环境。ubuntu16.04 + ros kinetic版本。使用笔记本自带摄像头,完成人脸的实时检测。代码可能会更改,具体以github上的代码为主。

    camera_subscribe.cpp 订阅camera发出的图片信息,然后对Mat 类型的图片进行每一帧图片的人脸检测,人脸检测代码参考opencv的开源代码。
    /* ***********************************************
    Author        :guanjunace@foxmail.com
    Created Time  :2017年07月10日 星期一 10时43分26秒
    File Name     :camera_subscribe.cpp
    ************************************************ */
    #include <iostream>
    #include <ros/ros.h>
    #include <image_transport/image_transport.h>
    #include <cv_bridge/cv_bridge.h>
    #include <sensor_msgs/image_encodings.h>
    #include <opencv2/highgui/highgui.hpp>
    #include "opencv2/objdetect.hpp"
    #include "opencv2/imgproc.hpp"
    using namespace std;
    using namespace cv;
    const string cascadeName = "/usr/share/opencv/haarcascades/haarcascade_frontalface_alt.xml";
    const string nestedCascadeName = "/usr/share/opencv/haarcascades/haarcascade_eye.xml";
    const double scale = 1.3;
    void detectFace(Mat& img, CascadeClassifier& cascade,
            CascadeClassifier& nestedCascade) {
        double t = 0;
        vector<Rect> faces;
        const static Scalar colors[] = {
            Scalar(255,0,0),
            Scalar(255,128,0),
            Scalar(255,255,0),
            Scalar(0,255,0),
            Scalar(0,128,255),
            Scalar(0,255,255),
            Scalar(0,0,255),
            Scalar(255,0,255)
        };
        Mat gray, smallImg;
    
        cvtColor( img, gray, COLOR_BGR2GRAY );
        double fx = 1 / scale;
        resize(gray, smallImg, Size(), fx, fx, INTER_LINEAR);
        equalizeHist(smallImg, smallImg);
        t = (double)getTickCount();
        cascade.detectMultiScale(smallImg, faces, 1.1, 2, 0
                //|CASCADE_FIND_BIGGEST_OBJECT
                //|CASCADE_DO_ROUGH_SEARCH
                |CASCADE_SCALE_IMAGE,
                Size(30, 30));
        t = (double)getTickCount() - t;
        printf("detection time = %g ms
    ", t*1000/getTickFrequency());    
        for (size_t i = 0; i < faces.size(); ++i) {
            Rect r = faces[i];
            Mat smallImgROI;
            vector<Rect> nestedObjects;
            Point center;
            Scalar color = colors[i%8];
            int radius;
            double aspect_ratio = (double)r.width/r.height;
            if(0.75 < aspect_ratio && aspect_ratio < 1.3) {
                center.x = cvRound((r.x + r.width*0.5)*scale);
                center.y = cvRound((r.y + r.height*0.5)*scale);
                radius = cvRound((r.width + r.height)*0.25*scale);
                circle(img, center, radius, color, 3, 8, 0);
            } else {
                rectangle(img, cvPoint(cvRound(r.x*scale), cvRound(r.y*scale)),
                        cvPoint(cvRound((r.x + r.width-1)*scale), cvRound((r.y + r.height-1)*scale)),
                        color, 3, 8, 0);
            }
            smallImgROI = smallImg(r);
            nestedCascade.detectMultiScale(smallImgROI, nestedObjects,
                    1.1, 2, 0
                    |CASCADE_SCALE_IMAGE,
                    Size(30, 30) );
            for (size_t j = 0; j < nestedObjects.size(); ++j) {
                Rect nr = nestedObjects[j];
                center.x = cvRound((r.x + nr.x + nr.width*0.5)*scale);
                center.y = cvRound((r.y + nr.y + nr.height*0.5)*scale);
                radius = cvRound((nr.width + nr.height)*0.25*scale);
                circle(img, center, radius, color, 3, 8, 0);
            }
    
        }
        imshow("result", img);
        waitKey(1);
    
    }
    void img_Callback(const sensor_msgs::ImageConstPtr& msg) {
        Mat image ;
        CascadeClassifier cascade, nestedCascade;
        try {
            image = cv_bridge::toCvShare(msg, "bgr8")->image;
            //CascadeClassifier cascade, nestedCascade;
            nestedCascade.load(nestedCascadeName);
            cascade.load(cascadeName);
            detectFace(image, cascade, nestedCascade);
            //Convert an immutable sensor_msgs::Image message to an OpenCV-compatible CvImage, 
            //sharing the image data if possible. 
            //imshow("img", cv_bridge::toCvShare(msg, "bgr8")->image);//IplImage 类型的 mat
            //waitKey(1);
        } catch (cv_bridge::Exception &e) {
            ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
        }
        if (!image.empty()) detectFace(image, cascade, nestedCascade);
        else printf("no image!");
    }
    int main(int argc, char *argv[]) { 
        ros::init(argc, argv, "img_subscribe");
        ros::NodeHandle nh;
        namedWindow("webcamimg");
        startWindowThread();/*
        CascadeClassifier cascade, nestedCascade;
        if (!nestedCascade.load(nestedCascadeName))
            cerr << "WARNING: Could not load classifier cascade for nested objects" << endl;
        if (!cascade.load(cascadeName)) {
            cerr << "ERROR: Could not load classifier cascade" << endl;
            return -1;
           }
    */
        image_transport::ImageTransport it(nh);
        image_transport::Subscriber img_sub = it.subscribe("/webcam/img", 1, &(img_Callback));
    
        destroyWindow("webcamimg");
        ros::spin();
        return 0;
    }

    camera_driver代码

    /* ***********************************************
    Author        :guanjun  guanjunace@foxmail.com
    Created Time  :2017/7/8 10:40:13
    File Name     :camera_publisher.cpp
    ************************************************ */
    #include <bits/stdc++.h>
    #include <ros/ros.h>
    #include <image_transport/image_transport.h>
    #include <cv_bridge/cv_bridge.h>
    #include <sensor_msgs/image_encodings.h>
    #include <opencv2/highgui/highgui.hpp>
    
    using namespace std;
    using namespace cv;
    
    class WebCam {
     public:
        WebCam (ros::NodeHandle& nh, int video_source = 0)
        : it(nh), 
        cap(video_source) {
            if (!cap.isOpened()) {
                ROS_ERROR("Cannot open the camera!
    ");
            }
            /*设置主题名和缓冲区*/   
            imgPub = it.advertise("webcam/img", 1);
            /*初始化CvImage智能指针,CvImage为Mat与ROS图像之间转换的载体*/
            frame = boost::make_shared<cv_bridge::CvImage>();
            /*设置ROS图片为BGR且每个像素点用1个字节来表示类似于CV_8U*/
            frame->encoding = sensor_msgs::image_encodings::BGR8;
        }
        /*图像发布函数*/
        int publishImage(){
            /*将摄像头获取到的图像存放在frame中的image*/
            cap >> frame->image;
            /*判断是否获取到图像,若获取到图像,将其转化为ROS图片*/
            if (!(frame->image.empty())){
                frame->header.stamp = ros::Time::now();
                imgPub.publish(frame->toImageMsg());
            }
            return 0;       
        }
     private:    
        /*设置图片节点*/
        image_transport::ImageTransport it;
        /*设置图片的发布者*/
        image_transport::Publisher imgPub;
        /*设置存放摄像头图像的变量*/    
        VideoCapture cap;
        /*设置cvImage的智能指针*/
        cv_bridge::CvImagePtr frame;
    };
    
    int main(int argc, char *argv[]) {
        /*初始化节点,并设定节点名*/
        ros::init(argc, argv, "img_publiser");
        /*设置节点句柄*/
        ros::NodeHandle nh;
    
        /*判断输入参数是否完成*/
        if (argv[1] == NULL){
            ROS_WARN("Please choose the camera you want to use !");
            return 1;
        }
        /*获取打开摄像机的设备号*/
        int video_source = 0;
        int default_p = 0;
        istringstream default_param(argv[1]);
        default_param >> default_p;
        nh.param<int>("video_source", video_source, default_p);
    
        /*定义摄像机对象*/
        WebCam webcam(nh, video_source);
    
        /*设置主题的发布频率为10Hz*/
        ros::Rate loop_rate(10);
        /*图片节点进行主题的发布*/
        while (ros::ok()) {
            webcam.publishImage();
            ros::spinOnce();
            /*按照设定的频率来将程序挂起*/
            loop_rate.sleep();
        }
        return 0;
    }

     在人脸检测的过程中,随着人脸的移动,有个别帧并不能检测出人脸,考虑以后哦要加个跟踪

  • 相关阅读:
    代理模式
    组合模式
    策略模式
    状态模式
    js 未结束的字符串常量错误解决方法
    struts2+hibernate+poi导出Excel实例
    Java 实现导出excel表 POI
    ExtJS 4.2 中自定义事件
    dhtmlxGrid分页查询,条件查询实例
    '@P0' 附近有语法错误
  • 原文地址:https://www.cnblogs.com/pk28/p/7146172.html
Copyright © 2020-2023  润新知