如何将openCV视频流式传输到HTML网页?

时间:2013-11-25 23:08:17

标签: c++ python html opencv

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

总结一下: Python和/或C ++中的openCV2是否能够仅使用openCV直播视频? 如果没有,你会建议我尝试使用CV捕获对象或Mat对象并将其写入我可以放在网页上的流中的库? 在HTML中,使用?

流式传输视频是一个好主意

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

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

4 个答案:

答案 0 :(得分:3)

以下主题解决了OpenCV和Python之外的流帧问题: Pipe raw OpenCV images to FFmpeg

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

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

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

答案 1 :(得分:2)

我可能有点晚了,但由于我没有在 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,并在系统中安装make。

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,端口 = 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

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

答案 2 :(得分:1)

尝试阅读thisthis

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

答案 3 :(得分:0)

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

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