Ubuntu 24.04 + ROS 2 C++ 实现人脸识别

 

核心框架为 ROS 2(Iron/Humble)+ C++ + OpenCV(Haar级联检测器),通过C++节点完成图像采集、人脸检测与结果显示,步骤如下:

 

一、环境确认与依赖安装

 

1. 确认ROS 2环境:确保已安装ROS 2(推荐Iron,对Ubuntu 24.04兼容性更好),且已配置环境变量( source /opt/ros/iron/setup.bash )。

2. 安装C++依赖库:终端执行命令,安装OpenCV开发库与ROS 2图像相关功能包:

bash

sudo apt update && sudo apt install -y libopencv-dev ros-iron-sensor-msgs ros-iron-image-transport ros-iron-cv-bridge

 

 

二、创建ROS 2 C++功能包

 

1. 新建工作空间并创建功能包(依赖 rclcpp 、 sensor_msgs 等核心库):

bash

mkdir -p ~/ros2_cpp_ws/src && cd ~/ros2_cpp_ws/src

ros2 pkg create face_recognition_cpp --build-type ament_cmake --dependencies rclcpp sensor_msgs image_transport cv_bridge opencv2

cd ~/ros2_cpp_ws # 返回工作空间根目录

 

 

三、编写C++核心节点(2个关键节点)

 

在 src/face_recognition_cpp/src 目录下,创建2个 .cpp 文件,分别实现图像发布(摄像头采集) 和人脸识别(订阅+检测)。

 

1. 图像发布节点(camera_publisher.cpp):采集摄像头图像并发布

 

cpp

#include "rclcpp/rclcpp.hpp"

#include "sensor_msgs/msg/image.hpp"

#include "cv_bridge/cv_bridge.h"

#include <opencv2/opencv.hpp>

 

class CameraPublisher : public rclcpp::Node

{

public:

    CameraPublisher() : Node("camera_publisher")

    {

        // 创建图像发布者,话题为"camera/image_raw",队列大小10

        publisher_ = this->create_publisher<sensor_msgs::msg::Image>("camera/image_raw", 10);

        

        // 创建定时器,每30ms触发一次(约30fps)

        timer_ = this->create_wall_timer(

            std::chrono::milliseconds(30),

            std::bind(&CameraPublisher::timer_callback, this)

        );

        

        // 打开默认摄像头(设备号0)

        cap_.open(0);

        if (!cap_.isOpened())

        {

            RCLCPP_ERROR(this->get_logger(), "Failed to open camera!");

            rclcpp::shutdown();

        }

    }

 

private:

    void timer_callback()

    {

        cv::Mat frame;

        cap_ >> frame; // 读取一帧图像

        if (frame.empty()) return; // 若图像为空,跳过

        

        // 将OpenCV图像(BGR格式)转换为ROS 2图像消息

        auto msg = cv_bridge::CvImage(std_msgs::msg::Header(), "bgr8", frame).toImageMsg();

        msg->header.stamp = this->now(); // 设置时间戳

        publisher_->publish(*msg); // 发布图像消息

    }

 

    rclcpp::Publisher<sensor_msgs::msg::Image>::SharedPtr publisher_;

    rclcpp::TimerBase::SharedPtr timer_;

    cv::VideoCapture cap_; // 摄像头捕获对象

};

 

int main(int argc, char *argv[])

{

    rclcpp::init(argc, argv);

    rclcpp::spin(std::make_shared<CameraPublisher>()); // 启动节点

    rclcpp::shutdown();

    return 0;

}

 

 

2. 人脸识别节点(face_detector.cpp):订阅图像并检测人脸

 

cpp

#include "rclcpp/rclcpp.hpp"

#include "sensor_msgs/msg/image.hpp"

#include "cv_bridge/cv_bridge.h"

#include <opencv2/opencv.hpp>

#include <opencv2/objdetect.hpp>

 

class FaceDetector : public rclcpp::Node

{

public:

    FaceDetector() : Node("face_detector")

    {

        // 创建图像订阅者,订阅"camera/image_raw"话题

        subscription_ = this->create_subscription<sensor_msgs::msg::Image>(

            "camera/image_raw", 10,

            std::bind(&FaceDetector::image_callback, this, std::placeholders::_1)

        );

        

        // 加载OpenCV Haar人脸检测器(默认级联文件路径)

        if (!face_cascade_.load(cv::samples::findFile("haarcascade_frontalface_default.xml")))

        {

            RCLCPP_ERROR(this->get_logger(), "Failed to load face cascade!");

            rclcpp::shutdown();

        }

        

        cv::namedWindow("Face Detection (ROS 2 C++)", cv::WINDOW_NORMAL); // 创建显示窗口

    }

 

    ~FaceDetector()

    {

        cv::destroyAllWindows(); // 销毁窗口

    }

 

private:

    void image_callback(const sensor_msgs::msg::Image::SharedPtr msg)

    {

        try

        {

            // 将ROS 2图像消息转换为OpenCV图像(BGR格式)

            cv::Mat frame = cv_bridge::toCvShare(msg, "bgr8")->image;

            cv::Mat gray;

            cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY); // 转为灰度图(加速检测)

            

            // 检测人脸:返回人脸矩形列表

            std::vector<cv::Rect> faces;

            face_cascade_.detectMultiScale(gray, faces, 1.1, 2, 0|cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));

            

            // 在图像上绘制绿色人脸框(线宽2)

            for (const auto& face : faces)

            {

                cv::rectangle(frame, face, cv::Scalar(0, 255, 0), 2);

            }

            

            // 显示检测结果

            cv::imshow("Face Detection (ROS 2 C++)", frame);

            if (cv::waitKey(1) == 'q') // 按"q"退出

            {

                rclcpp::shutdown();

            }

        }

        catch (const cv_bridge::Exception& e)

        {

            RCLCPP_ERROR(this->get_logger(), "cv_bridge exception: %s", e.what());

        }

    }

 

    rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr subscription_;

    cv::CascadeClassifier face_cascade_; // Haar级联检测器对象

};

 

int main(int argc, char *argv[])

{

    rclcpp::init(argc, argv);

    rclcpp::spin(std::make_shared<FaceDetector>()); // 启动节点

    rclcpp::shutdown();

    return 0;

}

 

 

四、配置编译文件(CMakeLists.txt)

 

打开 src/face_recognition_cpp/CMakeLists.txt ,在文件末尾添加以下内容,指定编译规则:

 

cmake

# 编译摄像头发布节点

add_executable(camera_publisher src/camera_publisher.cpp)

ament_target_dependencies(camera_publisher rclcpp sensor_msgs cv_bridge opencv2)

 

# 编译人脸检测节点

add_executable(face_detector src/face_detector.cpp)

ament_target_dependencies(face_detector rclcpp sensor_msgs cv_bridge opencv2)

 

# 安装可执行文件到ROS 2路径

install(TARGETS

  camera_publisher

  face_detector

  DESTINATION lib/${PROJECT_NAME}

)

 

 

五、编译与运行

 

1. 编译工作空间:在 ros2_cpp_ws 目录下执行:

bash

colcon build --packages-select face_recognition_cpp

 

2. 加载环境变量:编译完成后,加载工作空间环境:

bash

source install/setup.bash

 

3. 启动节点:

- 打开第1个终端,启动图像发布节点:

bash

ros2 run face_recognition_cpp camera_publisher

 

- 打开第2个终端,启动人脸检测节点(先加载环境: source install/setup.bash ):

bash

ros2 run face_recognition_cpp face_detector

 

- 效果:将显示摄像头画面,检测到的人脸会被绿色矩形框标注,按 q 可退出。

 

我可以帮你排查编译或运行中的常见问题(如依赖缺失、摄像头权限错误),需要的话可以告诉我具体报错信息。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐