簡體   English   中英

如何通過ZeroMQ將圖像(opencv矩陣/ numpy數組)從C ++發布者傳輸到python發送者?

[英]How to I transfer an image(opencv Matrix/numpy array) from c++ publisher to python sender via ZeroMQ?

我知道如何通過Zeromq從C ++向python發送字符串消息。

這是我知道的發送字符串消息的代碼:

C ++發送者代碼:

void *context = zmq_ctx_new();
void *publisher = zmq_socket(context, ZMQ_PUB);
int bind = zmq_bind(publisher, "tcp://localhost:5563");
std::string message = "Hello from sender";
const char *message_char = message.c_str();
zmq_send(publisher, message_char, strlen(message_char), ZMQ_NOBLOCK);

Python接收器代碼:

context = zmq.Context()
receiver = context.socket(zmq.SUB)
receiver.connect("tcp://*:5563")
receiver.setsockopt_string(zmq.SUBSCRIBE, "")
message = receiver.recv_string()

我想要的是將圖像從C ++ zeromq發布器發送到python接收器。

免責聲明: 回答我自己的問題,以便其他人不會卡在我所做的事情上。

因此,讓我們開始吧。

什么是零MQ?

ZeroMQ是一個高性能的異步消息傳遞庫,旨在用於分布式或並發應用程序中。 它提供了一個消息隊列,但是與面向消息的中間件不同,ZeroMQ系統可以在沒有專用消息代理的情況下運行。

之前,我們從這里開始:

使用的協議/庫:ZeroMQ

發布者:面向C ++

Subsciber:面向Python


通過ZeroMQ發送字符串/字符數組消息:

C ++發布者:-

// Setting up ZMQ context & socket variables
void *context = zmq_ctx_new();
void *publisher = zmq_socket(context, ZMQ_PUB); 
int bind = zmq_bind(publisher, "tcp://*:9000");
std::string message = "Hello from sender";
const char *message_char = message.c_str(); // Converting c++ string to char array
// Sending char array via ZMQ
zmq_send(publisher, message_char, strlen(message_char), ZMQ_NOBLOCK);

Python訂閱者:-

// Setting up ZMQ context & socket variables
context = zmq.Context()
receiver = context.socket(zmq.SUB)
receiver.connect("tcp://localhost:9000")
// Subscribing to start receiving messages
receiver.setsockopt_string(zmq.SUBSCRIBE, "")
message = receiver.recv_string()

通過ZeroMQ發送Image / ndarray數組消息:

對於處理圖像,opencv是一個很棒的庫。 簡單,易於編碼和快速閃電。

C ++發布者:-

void *context = zmq_ctx_new();
void *publisher = zmq_socket(context, ZMQ_PUB);
int bind = zmq_bind(publisher, "tcp://*:9000");

// Reading the image through opencv package
cv::Mat image = cv::imread("C:/Users/rohit/Desktop/sample.bmp", CV_LOAD_IMAGE_GRAYSCALE );
int height = image.rows;
int width = image.cols;
zmq_send(publisher, image.data, (height*width*sizeof(UINT8)), ZMQ_NOBLOCK);

在上面的代碼中,圖像被讀取為灰度圖像,通過在opencv的imread方法中傳遞適當的參數,您也可以讀取3通道(RGB)圖像。

還要記住相應地修改大小(zmq_send函數調用中的第三個參數)。

Python訂閱者:-

context = zmq.Context()
receiver = context.socket(zmq.SUB)
receiver.connect("tcp://localhost:9000")
receiver.setsockopt_string(zmq.SUBSCRIBE, "")
// Receiving image in bytes
image_bytes = receiver.recv()
int width = 4096; // My image width
int height = 4096; // My image height
// Converting bytes data to ndarray
image = numpy.frombuffer(image_byte, dtype=uint8).reshape((width, height))

要做/改進:您還可以傳遞來自c ++發布者的圖像大小以及圖像數據。 因此,可以在python端相應地重塑該圖像。

ZMQ_SNDMORE標志在這里很方便

只需在c ++端添加另一個zmq_send語句即可。

zmq_send(publisher, img_height, strlen(img_height), ZMQ_SNDMORE)
zmq_send(publisher, img_width, strlen(img_width), ZMQ_SNDMORE)
zmq_send(publisher, image.data, (height*width*sizeof(UINT8)), ZMQ_NOBLOCK);

同樣,在python末尾添加相應的接收語句。

height = receiver.recv_string(ZMQ_RCVMORE)
width = receiver.recv_string(ZMQ_RCVMORE)
image_bytes = receiver.recv()

另一個改進

感謝@Mark Setchell指出了一項改進。

直接通過網絡發送大型的opencv Matrix可能會很昂貴。 更好的方法是在通過網絡發送之前對圖像進行編碼。

C ++發布者:-

void *context = zmq_ctx_new();
void *publisher = zmq_socket(context, ZMQ_PUB);
int bind = zmq_bind(publisher, "tcp://*:9000");

// Reading the image through opencv package
cv::Mat image = cv::imread("C:/Users/rohit/Desktop/sample.bmp", CV_LOAD_IMAGE_GRAYSCALE );
int height = image.rows;
int width = image.cols;
cv::vector<uchar> buffer;
cv::imencode(".jpg", image, buffer);
zmq_send(publisher, buffer.data(), buffer.size(), ZMQ_NOBLOCK);

Python訂閱者:-

context = zmq.Context()
receiver = context.socket(zmq.SUB)
receiver.connect("tcp://localhost:9000")
receiver.setsockopt_string(zmq.SUBSCRIBE, "")
// Receiving image in bytes
image_bytes = receiver.recv()
// Decoding the image -- Python's PIL.Image library is used for decoding
image = numpy.array(Image.open(io.BytesIO(image_byte)))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM