Boost asio: отправьте OpenCV IplImage с Ubuntu-Server на Win7-Client - PullRequest
2 голосов
/ 26 февраля 2011

Я пытаюсь передать OpenCV IplImage с Сервера (Ubuntu x64) на Клиент (Win7 x64) с помощью библиотеки boost asio.

Следующий код работает нормально, если оба (Клиент и Сервер) находятся в одной операционной системе. Но когда сервер находится в 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;
}

Ответы [ 2 ]

0 голосов
/ 26 февраля 2011

Вы также должны создать новое изображение в месте назначения, со значениями параметров заголовка изображения, которые вы скопировали, затем скопировать данные изображения в новое изображение (в идеале - строку за раз)

Естьнет гарантии, что openCV выкладывает данные изображения одинаково, у него могут быть разные отступы или разные строки

0 голосов
/ 26 февраля 2011

Вы можете попробовать библиотеку наподобие Boost.Serialization вместо того, чтобы переходить на собственную версию, чтобы увидеть, если она имеет значение:

7) Переносимость данных - созданы потоки байтовна одной платформе должен быть читаемым на любой другой.

...