2012-05-21 9 views
5

Ich mache eine C++ - Anwendung, die opencv und zeromq verwendet. Und ich habe einige Probleme, wenn ich versuche, ein cv :: Mat-Objekt (CV_8UC3) über einen zmq tcp-Socket zu senden. HierSchlechte Adresse in cv :: Mat

ist die aktualisierte Codebeispiel:

#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; 
} 

Letztere send() macht ZMQ eine Behauptung fehlschlagen. Ausgabe:

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) 

Warum clone() mess up der Zeiger, und wie kann ich dieses Problem lösen?

Jede Hilfe wird geschätzt.

Bearbeiten 2012-05-25: Das Codebeispiel wurde aktualisiert. Ich kann den ursprünglichen Rahmen senden, indem ich einen der folgenden Zeiger auf den Nachrichtenkonstruktor gebe: frame.ptr(), frame.data, frame.datastart, frame.at(). Sie alle arbeiten für das Original, aber nichts für den Konstrukteur. Wie Sie sehen können, ist der Adressraum zwischen den beiden Datapointern klein. Sollte es nicht mindestens frameSize sein?

// John

+0

Ich bin nicht sicher, aber ich glaube, dass, wenn Sie cv tun :: Mat clonedFrame = frame.clone(); Sie erstellen einen Zeiger auf den Rahmen. Warum versuchst du nicht, frame.copyTo zu machen (clonedFrame); . Auf diese Weise wird das Bild sicher kopiert. Probieren Sie das aus, nur für den Fall. –

+0

Ich habe das auch versucht. Aber es gibt das gleiche Ergebnis. cv :: Mat Referenz besagt, dass clone() eine vollständige Kopie der Matrix erstellt und dass copyto() alle Daten an das Ziel kopiert. Verstehe den Unterschied nicht vollständig ... – John

+0

Ja, du hast Recht. Es ist komisch. Versuchen Sie, jede Mat-Eigenschaft in jedem Schritt zu debuggen und zu überprüfen: data, datastart, size, step. Vielleicht haben Sie einen Hinweis auf den Unterschied zwischen den 2 Matrizen und warum es scheitert. –

Antwort

0

Ok ... So landete ich meine eigene Kopierfunktion

Es sieht aus wie diese bilden:

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; 
} 

und ich verwende es wie folgt aus:

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

Wenn jemand einen besseren Weg kennt, lass es mich wissen.

// John

Verwandte Themen