2012-05-21 38 views
5

我正在制作一个使用opencv和zeromq的C++应用程序。并且在尝试通过zmq tcp套接字发送cv :: Mat对象(CV_8UC3)时遇到了一些问题。cv中的坏地址:: Mat

这里是更新的代码示例:

#include <iostream> 
#include <zmq.hpp> 
#include <pthread.h> 
#include <opencv/cv.h> 
#include <opencv/highgui.h> 

using namespace std; 

int main() 
{ 
    zmq::context_t ctx(1); 
    zmq::socket_t mysocket(ctx, ZMQ_PUSH); 
    mysocket.bind("tcp://lo:4050"); 

    cv::VideoCapture capture(CV_CAP_ANY); 
    capture.set(CV_CAP_PROP_FRAME_WIDTH, 640); 
    capture.set(CV_CAP_PROP_FRAME_HEIGHT, 480); 

    cv::Mat3b frame; 

    capture >> frame; //First one is usually blank 
    capture >> frame; 
    capture >> frame; 

    cv::Mat3b clonedFrame(480, 640, CV_8UC3); 
    frame.copyTo(clonedFrame); 

    cout << "Original:" << endl 
     << "Address of data:\t" << &frame.data << endl 
     << "Size:\t\t\t" << frame.total() * frame.channels() << endl << endl; 

    cout << "Cloned:" << endl 
     << "Address of data:\t" << &clonedFrame.data << endl 
     << "Size:\t\t\t" << clonedFrame.total() * clonedFrame.channels() << endl << endl; 

    cout << "Gap between data:\t" << &clonedFrame.data - &frame.data << endl; 

    unsigned int frameSize = frame.total() * frame.channels(); 

    zmq::message_t frameMsg(frame.data, frameSize, NULL, NULL); 
    zmq::message_t clonedFrameMsg(clonedFrame.data, frameSize, NULL, NULL); 

    cv::imshow("original", frame); 
    cv::imshow("cloned", clonedFrame); 


    cvWaitKey(0); 

    if(frame.isContinuous()) 
    { 
     cout << "Sending original frame" << endl; 
     mysocket.send(frameMsg, 0); //This works 
     cout << "done..." << endl; 
    } 

    cvWaitKey(0); 

    if(clonedFrame.isContinuous()) 
    { 
     cout << "Sending cloned frame" << endl; 
     mysocket.send(clonedFrameMsg, 0); //This fails 
     cout << "done..." << endl; 
    } 

    return EXIT_SUCCESS; 
} 

后者的send()使得ZMQ失败一些断言。 输出:

Original: 
Address of data: 0xbfdca480 
Size:   921600 

Cloned: 
Address of data: 0xbfdca4b8 
Size:   921600 

Gap between data: 14 
Sending original frame 
done... 
Sending cloned frame 
Bad address 
done... 
nbytes != -1 (tcp_socket.cpp:203) 

为什么克隆()陷入困境的指针,我怎么能解决这个问题?

任何帮助表示赞赏。

编辑2012-05-25: 更新了代码示例。 我可以通过给消息构造函数指定以下指针之一来发送原始帧:frame.ptr(),frame.data,frame.datastart,frame.at()。他们都为原创而工作,但没有为构造者。如您所见,两个数据存储器之间的地址空间很小。它不应该蜜蜂至少frameSize?

//约翰

+0

我不确定,但我认为,当你做cv :: Mat clonedFrame = frame.clone();你正在创建一个指向帧的指针。你为什么不尝试去做frame.copyTo(clonedFrame); 。这样图像就被复制了。试试看,以防万一。 –

+0

我也试过。但它给出了相同的结果。 cv :: Mat引用说明clone()创建矩阵的完整副本,并且copyto()将所有数据复制到目标。不完全了解区别... – John

+0

是的,你说得对。有点奇怪。尝试调试并检查每个步骤中的每个Mat属性: data,datastart,size,step。也许你知道两个矩阵之间的区别以及它失败的原因。 –

回答

0

好吧...所以我最终使我自己的复制功能

它看起来像这样:

struct frameData_t 
{ 
    unsigned char *data; 
    size_t size; 
}; 

struct frameData_t *copyMatData(cv::Mat3b &indata) 
{ 
    struct frameData_t *ret = new struct frameData_t; 

    ret->size = indata.total() * indata.channels(); 
    ret->data = new unsigned char[ret->size]; 

    int datapos = 0; 
    for(int channel = 0; channel < indata.channels(); channel++) 
    { 
     for(int row = 0; row < indata.rows; row++) 
     { 
      const cv::Vec3b *srcrow = indata[row]; 
      for(int col = 0; col < indata.cols; col++, datapos++) 
      { 
       ret->data[datapos] = srcrow[col][channel]; 
      } 
     } 
    } 

    return ret; 
} 

我用这样的:

struct frameData_t *clonedFrame = copyMatData(frame); 
zmq::message_t frameMsg(frame.data, frameSize, NULL, NULL); 
mysocket.send(clonedFrameMsg, 0); 

如果有人知道更好的方法,请让我知道。

// John