【问题标题】:OpenCV MJPG Streamer not workingOpenCV MJPG Streamer 不工作
【发布时间】:2018-05-02 07:49:49
【问题描述】:

我正在尝试在 OpenCV 版本 3.1、Windows x64 中使用 OpenCV VideoCapture 类打开视频流。在我的树莓派上,我正在运行 mjpg_streamer,我可以通过 http://192.168.1.245:8080/?action=stream 看到输出,但是当我尝试在 OpenCV 中打开视频流时,它无法打开流。

这是我用来调试的代码,显然也适用于遇到连接问题的其他人。

#include <opencv2\core.hpp>
#include <opencv2\videoio.hpp>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    cv::VideoCapture vcap;
    cv::Mat raw_image;

    const string videoStreamAddress = "http://192.168.1.245:8080/?action=stream";

    if (!vcap.open(videoStreamAddress))
    {

        cout << "Error opening video stream" << endl;
        system("pause");
        return -1;
    }

    cout << "Stream opened" << endl;
    system("pause");
    return 0;
}

网上,有人说OpenCV必须在链接中有视频扩展。我曾尝试使用其他人正在使用的扩展技巧,例如 http://192.168.1.245:8080/?action=stream?dummy=param.mjpghttp://192.168.1.245:8080/?action=stream&type=.mjpg、&channel=0&.mjpg 和 &type=.mjpeg,但这不起作用。另外,我在 cmake 中启用了 ffmpeg 并用它构建。似乎在这一点上它适用于其他人,并且似乎没有关于该主题的任何其他内容。有什么办法解决这个问题?

【问题讨论】:

  • “等等!”是我投反对票的原因 - 不是因为有现有的工作。所以,您说您正在调试这段代码,但到目前为止,您实际上并没有展示调试研究所显示的大部分内容。
  • @MarcusMüller 知道了,我会尝试添加更多。
  • 你能用 VLC 播放流吗?
  • @Micka 是的,我可以使用 VLC 播放流,使用 192.168.1.245:8080/?action=stream
  • 这可能意味着流不满足 mjpg 流标准,而是流完整的 jpg 标头。不确定这是否是opencv的问题。您是否尝试输入 jpg 而不是 mjpg?有图片链接吗?即使第一次捕获尝试失败,您能否尝试继续捕获?

标签: c++ opencv mjpeg


【解决方案1】:

感谢@api55 的建议,我能够获取流,然后将原始 jpg 数据传递给 opencv 并首先做我想做的事情。

这是提供的链接@api55 (link to python solution) 中解决方案的c++ 代码。

    try
    {

        boost::asio::io_service io_service;

        tcp::resolver resolver(io_service);
        tcp::resolver::query query("192.168.1.245", "8080");
        tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);

        tcp::socket socket(io_service);
        boost::asio::connect(socket, endpoint_iterator);

        std::string jpgimg = "";

        std::stringstream request_;

        request_ << "GET /?action=stream HTTP/1.1\r\n";
        request_ << "Host: 192.168.1.245\r\n";
        request_ << "Accept-Encoding: *\r\n";
        request_ << "\r\n";

        boost::system::error_code ignored_error;
        boost::asio::write(socket, boost::asio::buffer(request_.str()), ignored_error);

        for (;;)
        {
            char buf[1025];
            buf[1024] = '\0';
            boost::system::error_code error;

            size_t len = socket.read_some(boost::asio::buffer(buf,1024), error);

            if (error == boost::asio::error::eof)
                break; // Connection closed cleanly by peer.
            else if (error)
                throw boost::system::system_error(error); // Some other error.

            jpgimg.append(buf,buf+len);

            int a = jpgimg.find("\xff\xd8");
            int b = jpgimg.find("\xff\xd9");

            if (a != -1 && b != -1)
            {
                Mat rawData(1, b-a+2, CV_8UC1, (void*)(&jpgimg[a]));

                Mat i = cv::imdecode(rawData, CV_LOAD_IMAGE_COLOR);
                cv::imshow("i", i);
                if (cv::waitKey(1) == 27)
                break;

                jpgimg = jpgimg.substr(b+2);
            }

        }
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

它绝不是优化的,纯粹是其他地方实现的基础。它与 Boost ASIO 1.65.1 一起工作,方法是在我的树莓派(端口 8080)上打开一个到 mjpg_streamer 的流,向原始链接的 /?action=stream 部分发送一个 HTTP GET 请求,寻找 jpg 数据开头和结束标志(“\xff\xd8”和“\xff\xd9”),然后通过 imdecode 将此数据发送到 OpenCV。

资源:

Boost ASIO 客户端代码: http://www.boost.org/doc/libs/1_65_1/doc/html/boost_asio/tutorial/tutdaytime1.html

有关 jpg 如何工作的信息: How to parse MJPEG HTTP Stream within C++?

在 OpenCV 中使用原始 jpg 数据: opencv read jpeg image from buffer

希望 OpenCV 将来能有更好的 mjpg 支持。

【讨论】:

    猜你喜欢
    • 2014-01-22
    • 2017-11-30
    • 2018-12-05
    • 2016-12-04
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-07
    相关资源
    最近更新 更多