2012-05-21 14 views
5

Estoy haciendo una aplicación C++ que usa opencv y zeromq. Y estoy experimentando algunos problemas al intentar enviar un objeto cv :: Mat (CV_8UC3) sobre un socket zmq tcp.Mala dirección en cv :: Mat

Aquí está el ejemplo de código actualizado:

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

Este último send() hace ZMQ fallar alguna afirmación. de salida:

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) 

¿Por qué clon de desastre() el puntero, y cómo puedo solucionar esto?

Cualquier ayuda es apreciada.

Editar 2012-05-25: Actualizado el código de muestra. Puedo enviar el cuadro original dando uno de los siguientes punteros al constructor del mensaje: frame.ptr(), frame.data, frame.datastart, frame.at(). Todos trabajan para el original, pero ninguno para el constructor. Como puede ver, el espacio de direcciones entre los dos datapointers es pequeño. ¿No debería ser al menos frameSize?

// John

+0

No estoy seguro, pero creo que cuando se hace cv :: Mat clonedFrame = frame.clone(); está creando un puntero a marco. ¿Por qué no intentas hacer frame.copyTo (clonedFrame); . De esa manera, la imagen se copia con seguridad. Pruébalo, por las dudas. –

+0

Lo intenté también. Pero da el mismo resultado. cv :: La referencia Mat dice que clone() crea una copia completa de la matriz y que copyto() copia todos los datos en el destino. No entiendo completamente la diferencia ... – John

+0

Sí, tienes razón. Es raro. Intente depurar y verificar cada propiedad de Mat en cada paso: data, datastart, size, step. Tal vez tengas una pista sobre la diferencia entre las 2 matrices y por qué está fallando. –

Respuesta

0

bien ... Así que terminé de hacer mi propia función de copia

Se ve así:

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

y lo uso como esto:

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

Si alguien conoce una mejor manera, por favor avíseme.

// John

Cuestiones relacionadas