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()。それらはすべてオリジナルで機能しますが、コンストラクターでは機能しません。ご覧のとおり、2 つのデータポインター間のアドレス空間は小さいです。少なくともframeSizeであるべきではありませんか?
//ジョン