[英]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.