在使用ROS 2的 GStreamer和 OpenCV时,出现了“context is already initialized”错误

编程语言 2026-07-09

我正在尝试创建一个节点,用OpenCV读取一个GStreamer管道并对其进行处理。

这三者似乎并不太和谐。奇怪的是,同样的代码在ROS2之外就能正常工作。我尝试了C++和 Python的代码,使用OpenCV读取同一个GStreamer管道,能工作,但在ROS2中却不行。

错误信息如下:

[ WARN:[email protected]] global ./modules/videoio/src/cap_gstreamer.cpp (862) isPipelinePlaying OpenCV | GStreamer warning: GStreamer: pipeline have not been created
[ERROR:[email protected]] global ./modules/videoio/src/cap.cpp (174) open VIDEOIO(GSTREAMER): raised C++ exception:
context is already initialized
Error: Could not open GStreamer pipeline.
^C[INFO] [1780242562.998072183] [rclcpp]: signal_handler(SIGINT/SIGTERM)

同样的代码在ROS2环境之外同样能正常工作。显然,这与管道无关,因为它在Python和 C++测试代码中都能工作。只有在把这段代码放在ROS2中时才会出错。代码可以正常构建并运行,没有链接问题,只有上面的错误信息。我已经确认两段测试代码中的OpenCV版本相同。此外,OpenCV的构建也带有正确的GStreamer标志。

以下是我的代码:

#include "rclcpp/rclcpp.hpp"
#include <opencv2/opencv.hpp>


class gstTester : public rclcpp::Node
{
public:
    gstTester() : Node("my_gsttester_node")
    {
        RCLCPP_INFO(this->get_logger(), "Node started!");
        // testing gstreamer // this part works outside of ROS2
    std::string gstreamPipe;
    gstreamPipe = "ros2src ros-topic=/veh/fwd_cam/stream ! h264parse ! avdec_h264 ! videoconvert ! video/x-raw, format=BGR ! queue ! appsink async=false"; 
    cv::VideoCapture m_inCap;
    m_inCap = cv::VideoCapture(gstreamPipe, cv::CAP_GSTREAMER); 
    if (!m_inCap.isOpened()) 
    {
        std::cerr << "Error: Could not open GStreamer pipeline." << std::endl;
        return;
    }

    cv::Mat frame;
    while (m_inCap.read(frame))
    {
       cv::imshow("GStreamer Capture", frame);
       if (cv::waitKey(1) == 27)
          break; // Exit on ESC
    }

     m_inCap.release();
     cv::destroyAllWindows();
    }
};


int main(int argc, char **argv)
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<gstTester>());
    //rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

解决方案

对于遇到类似问题的各位,终于找到了原因。如果你在ROS2中使用GStreamer,请确保在调用之前解析你的GStreamer管道。

 rclcpp::init(argc, argv);

事实上,为了让我的代码工作,我必须把那一行注释掉。显然,在使用 ros2src 管道通过GStreamer调用之后,你不需要再调用它,因为它会已经初始化ROS2客户端,这也是最初导致错误信息的原因。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章