【问题标题】:How do I stream an openCV video to an HTML webpage?如何将 openCV 视频流式传输到 HTML 网页?
【发布时间】:2013-12-10 21:42:14
【问题描述】:

我正在制作一个机器人,上面有一个网络摄像头,可以提供一些简单的物体检测。现在,我想简单地将视频流式传输到机器人上托管的网页,并能够从另一台设备上查看它。我用 Python 编写了一个简单的测试脚本(我最终将转向 C++,我选择的语言),它可以从我的网络摄像头获取一个流,然后从那里做我需要的任何事情。那么问题是我无法在应用程序运行时将视频写入文件,它只会在我退出脚本后写入文件。我已经有一个网络服务器正在运行,我可以用 HTML 编写基本代码来托管来自文件的视频,所有这些都可以工作。

总结一下: Python 和/或 C++ 中的 openCV2 是否能够仅使用 openCV 直播视频? 如果不是,你会推荐哪个库让我尝试获取一个 CV 捕获对象或 Mat 对象并将其写入一个流,然后我可以将其放在网页上? 在 HTML 中,标签是用来流式传输视频的好主意吗?

非常感谢您的建议,我可以使用所有我能得到的指针*!

如果您需要比我给出的更进一步的澄清/发布的代码/解释,请询问,我会这样做!

【问题讨论】:

  • 您是否查看过 github 上提供的任何 JavaScript 图像/视频工具? CamanJS、Clmtrackr、JS Feat .. 可以将矩阵从 opencv 移植到 JS 吗?机器人上的处理器是什么——Rasberry pi、Beaglebone、Intel Edison 还是更高级的?也许是一个带有全功能显卡的主板(为了真正快速的处理帧速率......)?
  • 您好,先生!你是怎么解决这个问题的,我也有同样的问题。谢谢!
  • @BahramdunAdil,技术发生了变化……我相信我们现在使用的是 OpenCV3,HTTP 流和相关协议已经取得了长足的进步。我没有一定适合您的解决方案,但我建议尝试现有的流式视频框架,例如 rtmp 流媒体。祝你好运!
  • @PyroAVR 嘿,刚刚偶然发现你的问题。我正在尝试做同样的事情。 RTMP Streamer 并没有真正奏效。你有什么办法吗?

标签: c++ python html opencv


【解决方案1】:

从 OpenCV 和 Python 流式传输帧的问题已在以下线程中得到解决: Pipe raw OpenCV images to FFmpeg

这对我不起作用,但他们声称对他们有用。

在我的情况下它不起作用的原因似乎是对于某些输出帧,在 capture.py 中的 stdout 输出和 FFMPEG 输入之间的某个位置添加或丢失了额外的字节。因此,字节数与帧数不对应。我不确定为什么会这样。我使用的是 Windows 7。

如果您尝试一下,我很想知道您的体验。我还尝试了使用 cv2 修改后的 capture.py 版本,但由于同样的原因失败了。

【讨论】:

    【解决方案2】:

    在实验室条件下,您发送完整图像

    您似乎处于实验室条件下,因此有一个简单但可用的解决方案,只需使用 Websockets 在 Base64 中流式传输 PNG。在客户端(网络浏览器)上,您只需接收 base64 图像并将它们直接加载到 <img>src 中。它非常适用于实验室场景,尽管速度很慢。

    【讨论】:

    • 我们可以在网页中添加snapshotrecord按钮到同一个端口上的websockets吗?
    • 是的,我的情况是我每隔几毫秒发送一个 json。 { b64:“...”,时间:“”}。 Websockets 是双向的,因此您可以请求快照或实现您想要的任何命令。我什至实现了一个开始/停止按钮来停止所有的交通。
    • 谢谢。这正是我想要做的。图像在Base64 中作为jpg 作为套接字发送,并作为<img>src 读取。但很高兴知道我们可以在网页上添加按钮,以在相同的 IP 和端口上向服务器发送请求。
    • lab 条件下它工作得很好,我通过 LAN 获得 >20fps,非常适用于这种情况。真正的视频流大量代码开销,真的不值得。
    【解决方案3】:

    尝试阅读thisthis

    所以基本上你必须使用 OpenCV 捕获帧并将它们打包成适合流协议的特定格式,然后从你的服务器使用 HTML5 将其放在页面上。您可能需要使用 VLC 或 FFMepg 来打包您的 cv::Mat。希望这会有所帮助。

    【讨论】:

    • 谢谢,我试试看。我在嵌入式平台(beaglebone)上运行,所以我们将看看它是如何进行的。我会及时通知你的!
    【解决方案4】:

    我可能有点晚了,但由于我没有在 StackOverflow 中找到完全更新的 C++ 和 mjpeg 解决方案,所以考虑写一个新答案。

    现在有一些用于 C++ 任务的简单易用的库(c++ mjpg 流式传输到 html)

    https://github.com/nadjieb/cpp-mjpeg-streamer

    https://github.com/jacksonliam/mjpg-streamer

    https://github.com/codewithpassion/mjpg-streamer/tree/master/mjpg-streamer

    我发现第一个非常简单。您需要 CMake,并在系统中安装。

    git clone https://github.com/nadjieb/cpp-mjpeg-streamer.git;
    cd cpp-mjpeg-streamer;
    mkdir build && cd build;
    cmake ../;
    make;
    sudo make install;
    
    • 确保您安装了正确版本的 OpenCV。

    现在,写流光:

    mjpeg_server.cc

    #include <opencv2/opencv.hpp>
    
    #include <nadjieb/mjpeg_streamer.hpp>
    
    // for convenience
    using MJPEGStreamer = nadjieb::MJPEGStreamer;
    
    int main()
    {
        cv::VideoCapture cap;
        cap.open("demo.mp4"); 
        if (!cap.isOpened())
        {
            std::cerr << "VideoCapture not opened\n";
            exit(EXIT_FAILURE);
        }
    
        std::vector<int> params = {cv::IMWRITE_JPEG_QUALITY, 90};
    
        MJPEGStreamer streamer;
    
        // By default 1 worker is used for streaming
        // if you want to use 4 workers:
        //      streamer.start(8080, 4);
        streamer.start(8000);
    
        // Visit /shutdown or another defined target to stop the loop and graceful shutdown
        while (streamer.isAlive())
        {
            cv::Mat frame;
            cap >> frame;
            if (frame.empty())
            {
                std::cerr << "frame not grabbed\n";
                //continue;
                exit(EXIT_FAILURE);
            }
    
            // http://localhost:8080/bgr
            std::vector<uchar> buff_bgr;
            cv::imencode(".jpg", frame, buff_bgr, params);
            streamer.publish("/bgr", std::string(buff_bgr.begin(), buff_bgr.end()));
    
            cv::Mat hsv;
            cv::cvtColor(frame, hsv, cv::COLOR_BGR2HSV);
    
            // http://localhost:8080/hsv
            std::vector<uchar> buff_hsv;
            cv::imencode(".jpg", hsv, buff_hsv, params);
            streamer.publish("/hsv", std::string(buff_hsv.begin(), buff_hsv.end()));
    
            // std::cout<< "published" << std::endl;
        }
    
        streamer.stop();
    }
    

    CMakeLists.txt

    cmake_minimum_required(VERSION 3.1)
    
    project(mjpeg_streamer CXX)
    
    find_package(OpenCV 4.2 REQUIRED)
    find_package(nadjieb_mjpeg_streamer REQUIRED)
    
    include_directories(${OpenCV_INCLUDE_DIRS})
    
    add_executable(stream_test
      "mjpeg_server.cc")
    target_compile_features(stream_test PRIVATE cxx_std_11)
    target_link_libraries(stream_test PRIVATE nadjieb_mjpeg_streamer::nadjieb_mjpeg_streamer
                         ${OpenCV_LIBS})
    
    
    
    | --- mjpeg_server.cc
    | --- CMakeLists.txt
    | --- ...
    | --- build  
          | --- demo.mp4
          | --- ...
    
    

    现在,我们可以构建流媒体了。

    mkdir build && cd build;
    cmake ../;
    make;
    ./stream_test
    

    现在,如果您转到"http://ip_address:port/bgr""http://ip_address:port/hsv",您应该能够看到流。在我的例子中,ip = 192.168.1.7 / localhost, port = 8000。

    如果你想用另一个服务器抓取流,

    index.html

    <html>
      <body>
        <img src="http://localhost:8000/bgr">
        <img src="http://localhost:8000/hsv">
      </body>
    </html>
    

    serve.py

    import http.server
    import socketserver
    
    class MyHttpRequestHandler(http.server.SimpleHTTPRequestHandler):
        def do_GET(self):
            if self.path == '/':
                self.path = 'index.html'
            return http.server.SimpleHTTPRequestHandler.do_GET(self)
    
    # Create an object of the above class
    handler_object = MyHttpRequestHandler
    
    PORT = 8080
    my_server = socketserver.TCPServer(("", PORT), handler_object)
    
    # Star the server
    my_server.serve_forever()
    

    python3 serve.py

    最后,尽管它非常简单,但并不安全。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-28
      • 2019-10-16
      • 2016-05-30
      • 2012-11-26
      • 2013-09-03
      相关资源
      最近更新 更多