2

boost asio ライブラリを使用して、OpenCV IplImage をサーバー (Ubuntu x64) からクライアント (Win7 x64) に送信しようとしています。

次のコードは、両方 (クライアントとサーバー) が同じオペレーティング システム上にある場合に正常に機能します。ただし、サーバーが Ubuntu 上にあり、クライアントが Win7 上にある場合は機能しません。画像ヘッダーは正しいですが、画像データに何か問題があります。

これは、2 つの OS のビット順序が異なるためだと思います。それは...ですか?この問題を解決するにはどうすればよいですか?

次に、このコードの送信は非常に遅いです。どうすれば速度を改善できますか?

クライアント:

#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

また、コピーしたイメージ ヘッダー パラメータの値を使用して宛先に新しいイメージを作成し、イメージ データを新しいイメージにコピーする必要があります (理想的には一度に 1 行ずつ)。

openCV が画像データを同じ方法でレイアウトするという保証はありません。パディングや行ストライドが異なる場合があります。

于 2011-02-26T15:57:59.703 に答える