2011-02-26 101 views
2

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

如果两个(客户端和服务器)在同一个操作系统上,以下代码正常工作。但是,当服务器在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; 
} 

回答

0

你也应该在目的地创建一个新的形象,与您在随后的图像数据复制到新的图像复制的图像头参数的值(理想的是排在一个时间)

有没有保证openCV以相同的方式放置图像数据,它可能有不同的填充或不同的rowtrides

+0

你是对的!但我该怎么做?我尝试了以下: IplImage * img2 = cvCreateImage(atoi(parts [5] .c_str()),atoi(parts [4] .c_str())),atoi(parts [2] .c_str() ),的atoi(份[1] .c_str())); cvSetImageData(img2,imgdata,img2-> widthStep);但是这不起作用! – Dave 2011-02-26 17:37:50

+0

这是制作新图像标题的最佳方法。数据丢失可能来自使用char而不是unsigned char - 它可能会丢失opencv源代码中的最高位 – 2011-02-26 17:44:40

+0

imagedata是char *而不是unsigned char *。当我在初始文章的源代码中这样做时,如果客户端和服务器在同一个操作系统上运行,它就可以工作。所以我不认为这是问题。 – Dave 2011-02-26 18:00:34

0

您可以尝试像Boost.Serialization库,而不是滚动您自己的版本,看它是否有差别:

7 )数据可移植性 - 在任何其他平台上创建的字节流应为 。

相关问题