【问题标题】:Bad address in cv::Matcv::Mat 中的错误地址
【发布时间】:2012-05-28 09:34:17
【问题描述】:

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

这是更新后的代码示例:

#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)

为什么 clone() 会弄乱指针,我该如何解决?

感谢任何帮助。

编辑 2012-05-25: 更新了代码示例。 我可以通过向消息构造函数提供以下指针之一来发送原始帧:frame.ptr()、frame.data、frame.datastart、frame.at()。它们都适用于原始版本,但没有适用于构造函数。 如您所见,两个数据指针之间的地址空间很小。不应该是至少 frameSize 吗?

//约翰

【问题讨论】:

  • 我不确定,但我认为当你做 cv::Mat clonedFrame = frame.clone();您正在创建一个指向框架的指针。你为什么不尝试做 frame.copyTo(clonedFrame); .这样,图像肯定会被复制。试试看,以防万一。
  • 我也试过了。但它给出了相同的结果。 cv::Mat 参考说 clone() 创建了矩阵的完整副本,而 copyto() 将所有数据复制到目标。不完全了解其中的区别...
  • 是的,你是对的。有点奇怪。尝试调试并检查每个步骤的每个 Mat 属性:数据、数据开始、大小、步骤。也许您对这两个矩阵之间的差异以及它失败的原因有所了解。
  • 并尝试初始化矩阵,例如: cv::Mat frame = Mat::zeros(480,649,CV_8UC3);以防万一。有时,如果您没有正确初始化矩阵,程序会崩溃。

标签: c++ linux opencv zeromq


【解决方案1】:

好的...所以我最终制作了自己的复制功能

看起来像这样:

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

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

//约翰

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-12
    • 2014-06-21
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多