2011-02-26 102 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 )數據可移植性 - 在任何其他平臺上創建的字節流應爲 。

相關問題