python - 如何在 C++ 中使用 ZeroMQ 通信多个图像?
问题描述
我想实现可以通过 ZeroMQ 通信多个图像的程序。我可以使用 OpenCV 在 C++ 上显示多个图像,但我无法以某种方式在 Python 上显示,尽管编译器没有输出错误。
如何将多个图像从 C++ 传递到 Python?
C++ 代码:
Mat img0;
Mat img1;
Mat img2;
img0 = imread("images.jpeg");
img1 = imread("images1.jpeg");
img2 = imread("image2.jpg");
if(img0.empty()) return -1;
if(img1.empty()) return -1;
if(img2.empty()) return -1;
ShowManyImages("IMAGE",3,img0,img1,img2);
// Let structure for zeroMQ
int32_t info[3];
info[0] = (int32_t)img0.rows;
info[1] = (int32_t)img0.cols;
info[2] = (int32_t)img0.type();
info[3] = (int32_t)img1.rows;
info[4] = (int32_t)img1.cols;
info[5] = (int32_t)img1.type();
info[6] = (int32_t)img2.rows;
info[7] = (int32_t)img2.cols;
info[8] = (int32_t)img2.type();
zmq::context_t context (1);
zmq::socket_t socket (context, ZMQ_REQ);
socket.connect ("tcp://localhost:5555");
for(i=0; i<9; i++ )
{
zmq::message_t msg0 ( (void*)&info[i], sizeof(int32_t), NULL );
socket.send(msg0, ZMQ_SNDMORE);
}
void* data0 = malloc(img0.total() * img0.elemSize());
memcpy(data0, img0.data, img0.total() * img0.elemSize());
zmq::message_t msg00(data0, img0.total() * img0.elemSize(), my_free, NULL);
socket.send(msg00);
void* data1 = malloc(img1.total() * img1.elemSize());
memcpy(data1, img1.data, img1.total() * img1.elemSize());
zmq::message_t msg11(data1, img1.total() * img1.elemSize(), my_free, NULL);
socket.send(msg11);
void* data2 = malloc(img2.total() * img2.elemSize());
memcpy(data2, img2.data, img2.total() * img2.elemSize());
zmq::message_t msg22(data2, img2.total() * img2.elemSize(), my_free, NULL);
socket.send(msg22);
蟒蛇代码:
import zmq
import cv2
import struct
import numpy as np
# Connection String
conn_str = "tcp://*:5555"
# Open ZMQ Connection
ctx = zmq.Context()
sock = ctx.socket(zmq.REP)
sock.bind(conn_str)
while(True):
# Receve Data from C++ Program
byte_rows, byte_cols, byte_mat_type, data= sock.recv_multipart()
# Convert byte to integer
rows = struct.unpack('i', byte_rows)
cols = struct.unpack('i', byte_cols)
mat_type = struct.unpack('i', byte_mat_type)
if mat_type[0] == 0:
# Gray Scale
image = np.frombuffer(data, dtype=np.uint8).reshape((rows[0],cols[0]))
else:
# BGR Color
image = np.frombuffer(data, dtype=np.uint8).reshape((rows[0],cols[0],3))
cv2.imshow('Python',image)
cv2.waitKey()
真挚地,
解决方案
问:如何将多个图像从 C++ 传递到 Python?
上面的代码使用REQ/REP
Scalable Formal Communication Pattern Archetype,但它不会尝试发送和REP
-ly 到任何已经交付的REQ
-est。
如果不尝试-ly,-side 将永远无法发送任何下一条消息.send()
。REP
REQ
如果这是您使用ZeroMQ的第一次体验,
您可以在这里先看看“ ZeroMQ原则在不到5 秒内”,然后再深入了解更多细节。
解决方案 ?
尝试使用PUSH/PULL
不需要响应的 Archetype。
接下来,尝试确定仅使用第一张图像发送所有元数据是否是一个合理稳健的假设(我宁愿编写,最好使用struct.pack()/struct.unpack()
兼容的 BLOB 和byte_rows, byte_cols, byte_mat_type, data
所有人,单帧,微不足道的消息有效负载映射)。
Python 端只需一步读取单帧 BLOB,可能会测试签名,如果需要,.unpack()
前导几个字节来学习图像大小,.unpack()
图像数据的“其余部分”,你就完成了。这不是很可爱吗?
另请注意,并非所有平台都共享相同类型的 Endian-ness(因此最好将您的 c 端代码设计为具有显式字节顺序的“网络”-Endian 顺序 :o)只是为了在托管时安全起见设备/平台进一步发展,下一次可能会变得具有不同的字节序。显式排序是相同的显式排序,因为您的代码自第 1 天以来一直坚持使用)
我懂了。所以你说我必须使用 PUSH/PULL 对吗?但我将我的程序从 C++ 中的 ZMQ_REQ 修改为 ZMQ_XREQ 并在 python 中从 zmq.REP 修改为 zmq.XREQ。然后,我可以在 python 中观看三个窗口,但只显示 img0。我知道这是因为 sock.recv_multipart() 而发生的。但我不知道如何修改它。我还应该使用 PUSH/PULL 来实现吗?– user36327 7 小时前
不,我没有告诉任何人必须使用PUSH/PULL
,这是一个人的建议,他从 v2.1+ 开始使用 ZeroMQ
XREQ/XREP
已经有效地短路了理论上无限链的 dFSA 步进 REQ.send()s-REP.recv()s-REP.send()s-REQ.recv()s-REQ...-REP... -REP...-REQ...-REQ...-...-
[... ad-infinitum-or-deadlock,以先到者为准 :o) ]
问题在于期望事情一定会发生,而这实际上不需要像预期的那样发生:
MASK = 'Python: The Image#{0:} was decoded to be {1:}'
order_ORDER = 0
while( True ): # THIS WILL RUN FOREVER, WON'T IT?
#####################################################################################
order_ORDER += 1
#####################################################################################
( byte_rows, # EXPECTS ALL THIS TO .recv() EACH TIME
byte_cols, # EXPECTS ALL THIS TO .recv() EACH TIME
byte_mat_type, # EXPECTS ALL THIS TO .recv() EACH TIME
data # EXPECTS ALL THIS TO .recv() EACH TIME
) = sock.recv_multipart() # in Data from C++ Program
#####################################################################################
rows = struct.unpack( 'i', byte_rows) # EXPECTS THIS TO BE CORRECT EACH TIME
cols = struct.unpack( 'i', byte_cols) # EXPECTS THIS TO BE CORRECT EACH TIME
mat_type = struct.unpack( 'i', byte_mat_type) # EXPECTS THIS TO BE CORRECT EACH TIME
#####################################################################################
if mat_type[0] == 0: # IF mat_type[0] WAS == 0 ?in 2nd, 3rd?
# # # # # # # # # # # # # # # Gray Scale: # IF mat_type[0] WAS == 0 ?in 2nd, 3rd?
image = np.frombuffer( data,
dtype = np.uint8
).reshape( ( rows[0],
cols[0]
)
)
print "IMAGE WAS of TYPE == ZERO, HAVING SHAPE OF: ", image.shape, image.dtype
imgType = 'Grayscale'
else: # IF mat_type[0] WAS != 0 ?in 2nd, 3rd?
# # # # # # # # # # # # # # # # BGR Color # IF mat_type[0] WAS != 0 ?in 2nd, 3rd?
image = np.frombuffer( data,
dtype = np.uint8
).reshape( ( rows[0],
cols[0],
3
)
)
print "IMAGE WAS of TYPE != ZERO, HAVING SHAPE OF: ", image.shape, image.dtype
imgType = 'Blue-Green-Red'
###################################################################################
cv2.imshow( MASK.format( imgType, order_ORDER ), image )
cv2.waitKey()
###################################################################################
# LOOP AGAIN
###################################################################################
推荐阅读
- token - 我不能使用 WebJS 对 ERC20 令牌使用 Openzeppelin transferFrom 方法
- mysql - 创建一个组合两个表的视图,从一个表中优先考虑行
- django - /admin/password_change/ 和 /accounts/password_change/ 使用相同的模板,除非我手动指定一些 urlpatterns
- ios - AWS 放大 | iOS Swift 用户身份验证
- docker - 将 docker 镜像迁移到自定义注册表
- java - Fortify Eclipse 与 Fortify Audit Workbench 不匹配
- java - 是否可以修改 @WithMockUser 以获取和 Id?
- reactjs - 如何通过 React 钩子中的道具传递信息来显示引导模式?
- java - 从 webm 和其他文件中获取幻数
- python - xhtml2pdf 使用边框半径 css