c++ - 提升 asio : Send OpenCV IplImage from Ubuntu-Server to Win7-Client

标签 c++ sockets opencv boost-asio iplimage

我尝试使用 boost asio 库将 OpenCV IplImage 从服务器 (Ubuntu x64) 传输到客户端 (Win7 x64)。

如果(客户端和服务器)都在同一操作系统上,则以下代码可以正常工作。但是当服务器在 Ubuntu 上,客户端在 Win7 上时,它不起作用。图像标题是正确的,但图像数据有问题。

我认为这是因为两个操作系统之间的位顺序不同。是吗?我该如何解决这个问题?

其次:此代码的传输非常慢。 如何提高速度?

客户:

#define _WIN32_WINNT 0x0601 

#include <iostream>
#include <sstream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>

using boost::asio::ip::tcp;

using namespace std;

char* splitImage(const string& str, const string& delim, vector<string>& parts) {
  size_t start, end = 0;
  int i = 0;
  while (end < str.size() && i < 8) {
    start = end;
    while (start < str.size() && (delim.find(str[start]) != string::npos)) {
      start++;  // skip initial whitespace
    }
    end = start;
    while (end < str.size() && (delim.find(str[end]) == string::npos)) {
      end++; // skip to end of word
    }
    if (end-start != 0) {  // just ignore zero-length strings.
      parts.push_back(string(str, start, end-start));
    }
    i++;
  }
  int size = atoi(parts[6].c_str());
  char *imgdata = new char[size];
  memcpy(imgdata, string(str, end+1, size).c_str(), size);
  return imgdata;

}

int main(int argc, char* argv[])
{

  string header;
  try
  {

    boost::asio::io_service io_service;

    tcp::resolver resolver(io_service);
    tcp::resolver::query query("localhost", "1234");
    tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
    tcp::resolver::iterator end;

    tcp::socket socket(io_service);
    boost::system::error_code error = boost::asio::error::host_not_found;
    while (error && endpoint_iterator != end)
    {
      socket.close();
      socket.connect(*endpoint_iterator++, error);
    }
    if (error)
      throw boost::system::system_error(error);

    stringstream ss;

    cout << "reading";
    for (;;)
    {
      boost::array<char, 1024> buf;
      boost::system::error_code error;

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

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

      ss.write(buf.data(), len);
      header = ss.str();
    }
    cout << "done: data size: "<< header.size() << endl;
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
    return 1;
  }

  vector<string> parts; 
  char* imgdata = splitImage(header,"#",parts); 

  IplImage img2;    
  img2.nSize = atoi(parts[0].c_str());  
  img2.ID = 0;  
  img2.nChannels = atoi(parts[1].c_str());  
  img2.depth = atoi(parts[2].c_str());  
  img2.dataOrder = atoi(parts[3].c_str());; 
  img2.height = atoi(parts[4].c_str()); 
  img2.width = atoi(parts[5].c_str());  
  img2.roi = NULL;  
  img2.maskROI = NULL;  
  img2.imageId = NULL;  
  img2.tileInfo = NULL; 
  img2.imageSize = atoi(parts[6].c_str());      
  img2.widthStep = atoi(parts[7].c_str());  
  img2.imageData = imgdata;

  cvNamedWindow("Image:",1);  
  cvShowImage("Image:",&img2);
  cvWaitKey();  
  cvDestroyWindow("Image:");

  delete[] imgdata;

  return 0;
}

服务器:

#define _WIN32_WINNT 0x0601 
#define WIN32_LEAN_AND_MEAN 
#include <string>
#include <iostream>

#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <boost/asio.hpp>

#define DELIMITER "#"

using boost::asio::ip::tcp;
using namespace std;

IplImage *img;

string serializeImageHeader(){
    stringstream ss;
    ss << img->nSize << DELIMITER;
    ss << img->nChannels << DELIMITER;
    ss << img->depth << DELIMITER;
    ss << img->dataOrder << DELIMITER;
    ss << img->height << DELIMITER;
    ss << img->width << DELIMITER;
    ss << img->imageSize << DELIMITER;
    ss << img->widthStep << DELIMITER;

    return ss.str();
}


int main()
{
  try
  {
    boost::asio::io_service io_service;

    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 1234));

    img = cvLoadImage("Test.bmp");
    cout << "Server is running" << endl;

    for (;;)
    {
      tcp::socket socket(io_service);
      acceptor.accept(socket);
      cout << "socket accepted" << endl;

      string message  = serializeImageHeader().append(img->imageData, img->imageSize);

      boost::system::error_code ignored_error;
      boost::asio::write(socket, boost::asio::buffer(message),
          boost::asio::transfer_all(), ignored_error);
      cout << "sent: size: "<< message.size() << endl;
    }
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  cvReleaseImage(&img);

  return 0;
}

最佳答案

您可以尝试像 Boost.Serialization 这样的库而不是滚动您自己的版本以查看它是否有所作为:

7) Data Portability - Streams of bytes created on one platform should be readable on any other.

关于c++ - 提升 asio : Send OpenCV IplImage from Ubuntu-Server to Win7-Client,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5126923/

相关文章:

c++ - QTreeWidget 子类,停止放置指示器显示给定的不需要的 dropIndicatorPosition

java - Java中使用TCP协议(protocol)的多客户端多实例集中式服务器游戏系统

C++ 运行时错误 : free(): invalid next size (fast)

c++ - 在c++中找到两个 vector 中第一个公共(public)条目的位置的最快方法是什么?

sockets - 在哪些情况下调用 bind() 是必要的?

android - 在 OpenCV/Android 上更改分辨率

c++ - 我可以以任何方式将数据分配给从 OpenCV 对象取消引用的双函数返回检索吗?

c++ - OpenCV 凸性缺陷

c++ - 将已经围绕另一个枢轴变换的 GL 对象的枢轴居中?

java - java读取大文件时做 Action