加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 如何在MJPEG中使用boost.Asio?

发布时间:2020-12-16 06:50:45 所属栏目:百科 来源:网络整理
导读:我想将OpenCV图像(来自相机)实时广播到远程计算机,它必须通过以太网完成.在标准的OpenCV Mat对象中连续接收图像.最终代码必须集成到C(Qt)应用程序中. 我发现this Python script能够很好地完成这项工作. 现在我试图获得相当于该代码的C,我设法使用Boost Asio
我想将OpenCV图像(来自相机)实时广播到远程计算机,它必须通过以太网完成.在标准的OpenCV Mat对象中连续接收图像.最终代码必须集成到C(Qt)应用程序中.

我发现this Python script能够很好地完成这项工作.

现在我试图获得相当于该代码的C,我设法使用Boost Asio和Simple-Web-Server项目创建一个HTTP服务器.我能够显示static blue image /网络摄像头相机图像(未刷新).

我写了一段代码,但它没有用.我的猜测是数据仅在函数返回时发送(永不返回).
如何在while循环的每次迭代后强制发送数据?

#include "server_http.hpp"

#include <thread>
#include <boost/chrono.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <opencv2/opencv.hpp>
//#include <opencv/cv.h>

using namespace boost::posix_time;
typedef SimpleWeb::Server<SimpleWeb::HTTP> HttpServer;

cv::Mat image;
cv::VideoCapture cap;

int main()
{
  cap.open(0);
  if (!cap.isOpened ())
  {
    std::cerr << "Could not initialize capturing" << std::endl;
    return (-1);
  }
  cap >> image;

  HttpServer server(8080,2);

  // Image resource is requested
  server.resource["^/cam.mjpg"]["GET"] =
      [=](HttpServer::Response& response,std::shared_ptr<HttpServer::Request> request)
      {
        time_facet *facet = new time_facet("%d-%b-%Y %H:%M:%S");
        std::cout.imbue(std::locale(std::cout.getloc(),facet));
        std::cout << second_clock::local_time() << " | " << "Camera image requested!" << std::endl;

        response <<
        "HTTP/1.1 200 OKrn"
        "Content-type: multipart/x-mixed-replace; boundary=--jpgboundary";
        //TODO: Send header

        while (1) // TODO: Allow exiting this
        {
          std::cout << "Send image" << std::endl;
          cap >> image;
          // Encode mat to jpg and copy it to content
          std::vector<uchar> buf;
          cv::imencode(".jpg",image,buf,std::vector<int>());
          std::string img_content(buf.begin(),buf.end());

          response << "--jpgboundaryrn" << // Signal we start a new image
              "Content-type: image/jpeg" <<
              "Content-Length: " << img_content.length() << "rn" <<
              "rn" << img_content << "rn";
          std::this_thread::sleep_for(std::chrono::milliseconds(400));
        }
      };

  // Anything else is requested
  server.default_resource["GET"] = [](HttpServer::Response& response,std::shared_ptr<HttpServer::Request> request)
  {
    time_facet *facet = new time_facet("%d-%b-%Y %H:%M:%S");
    std::cout.imbue(std::locale(std::cout.getloc(),facet));
    std::cout << second_clock::local_time() << " | " << request->path << std::endl;

    std::string content =
    "<html><head></head><body>"
    "<img src="cam.mjpg"/>"
    "</body></html>";
    response <<
    "HTTP/1.1 200 OKrn"
    "Content-Length: " << content.length() << "rn"
    "rn" << content;
  };

  std::thread server_thread([&server]()
  {
    server.start();
  });

  std::this_thread::sleep_for(std::chrono::seconds(1));
  server_thread.join();
  return 0;
}

编辑1

根据Technik Empire的评论,我回到了boost examples;
在HTTP服务器示例中,当回调返回时发送的响应因此我修改了回调以允许套接字上的do_write()操作.

HTML页面正确显示但图像未显示(显示损坏的图像图标),我试着看看Wireshark会发生什么,但我不知道出了什么问题.

这是我的handle_request函数:(request_handler.cpp):

void request_handler::handle_request(const request& req,reply& rep,connection &con)
{
  // Decode url to path.
  std::string request_path;
  if (!url_decode(req.uri,request_path))
  {
    rep = reply::stock_reply(reply::bad_request);
    return;
  }

  // Request path must be absolute and not contain "..".
  if (request_path.empty() || request_path[0] != '/'
      || request_path.find("..") != std::string::npos)
  {
    rep = reply::stock_reply(reply::bad_request);
    return;
  }

  // Determine the file extension.
  std::size_t last_slash_pos = request_path.find_last_of("/");
  std::string filename;
  if (last_slash_pos != std::string::npos)
    filename = request_path.substr(last_slash_pos + 1);

  if (filename == "cam.mjpg") // Image is requested
  {
    rep.status = reply::ok;
    rep.headers.resize(1);
    rep.headers[0].name = "Content-Type";
    rep.headers[0].value = "multipart/x-mixed-replace; boundary=--jpgboundary";
    rep.content.empty();
    con.do_write();
    rep.status = reply::none;

    while (true) // FIXME: How do I handle disconnection from the client?
    {
      cv::Mat image(200,300,CV_8UC3);
      int random = rand() % 255 + 1;
      image = cv::Scalar(random,0); // Fill image with blue
      std::vector<uchar> buf;
      cv::imencode(".jpg",std::vector<int>());
      std::string img_content(buf.begin(),buf.end());

      rep.headers.clear();
      rep.content.clear();

      rep.content.append("--jpgboundaryrn");
      con.do_write();

      rep.content.clear();
      rep.headers.resize(2);
      rep.headers[0].name = "Content-Type";
      rep.headers[0].value = mime_types::extension_to_type("jpg");
      rep.headers[1].name = "Content-length";
      rep.headers[1].value = img_content.size();
      rep.content.append(img_content);
      rep.content.append("rn");
      con.do_write();

      boost::this_thread::sleep(boost::posix_time::milliseconds(500));
    }
  }
  else // Anything but the image is requested
  {
    std::string content =
    "<html><head></head><body>"
    "Hello :)<br>"
    "<img src="cam.mjpg"/>"
    "</body></html>";

    rep.status = reply::ok;
    rep.headers.resize(2);
    rep.headers[0].name = "Content-Length";
    rep.headers[0].value = content.length();
    rep.headers[1].name = "Content-Type";
    rep.headers[1].value = mime_types::extension_to_type("html");
    rep.content.append(content);
    con.do_write();
    return;
  }
}

解决方法

感谢Firefox网络分析器,我通过分析数据包得到了它,我复制了Python标题/内容答案,它运行正常:

我添加了一个reply :: none回复类型,并确保如果提供了此回复,则不会发送任何HTTP状态.所以在reply :: to_buffers()函数中我添加了这个:

if (status != none) // Don't add status to buffer if status is "none"
    buffers.push_back(status_strings::to_buffer(status));

request_handler.cpp代码如下所示:

if (filename == "cam.mjpg") // Image is requested
  {
    rep.status = reply::ok;
    rep.headers.resize(1);
    rep.headers[0].name = "Content-Type";
    rep.headers[0].value = "multipart/x-mixed-replace; boundary=--jpgboundaryrn";
    con.do_write();

    while (true) // FIXME: How do I handle disconnection from the client?
    {
      cv::Mat image(200,buf.end());

      rep.status = reply::none;
      rep.headers.resize(0);
      rep.content.clear();
      rep.content.append("--jpgboundary");
      rep.content.append("rn");
      rep.content.append("Content-Type: image/jpeg");
      rep.content.append("rn");
      rep.content.append("Content-length: "+boost::lexical_cast<std::string>(img_content.length()));
      rep.content.append("rn");
      rep.content.append("rn");
      rep.content.append(img_content);
      rep.content.append("rn");
      con.do_write();
      boost::this_thread::sleep(boost::posix_time::milliseconds(100));
    }
  }
  else // Anything but the image is requested
  {
    std::string content =
    "<html><head></head><body>"
    "<img src="cam.mjpg"/>"
    "</body></html>";

    rep.status = reply::ok;
    rep.headers.resize(2);
    rep.headers[0].name = "Content-Length";
    rep.headers[0].value = content.length();
    rep.headers[1].name = "Content-Type";
    rep.headers[1].value = mime_types::extension_to_type("html");
    rep.content.append(content);
    con.do_write();
    return;
  }

评论中欢迎改进建议.我不知道如何处理从客户端断开连接(退出while循环),所以目前服务器只能处理1个请求;之后,它被困在了while循环中.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读