2

我尝试使用 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;
}
4

2 回答 2

1

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

7) 数据可移植性——在一个平台上创建的字节流应该在任何其他平台上都是可读的。

于 2011-02-26T15:05:26.903 回答
0

您还应该在目标上创建一个新图像,使用您复制的图像标题参数的值,然后将图像数据复制到新图像中(最好是一次一行)

无法保证 openCV 以相同的方式布局图像数据,它可能具有不同的填充或不同的行跨度

于 2011-02-26T15:57:59.703 回答