【问题标题】:Sending numpy arrays via Socket通过 Socket 发送 numpy 数组
【发布时间】:2016-10-30 16:45:46
【问题描述】:

首先,我想做什么: 使用 Socket 将照片从我的 Raspberry Pi 发送到我的笔记本电脑。

客户:

#!/usr/bin/python

import socket
import cv2
import numpy as np
import pickle

#Upload image
img = cv2.imread('/path/to/image', 0)

#Turn image into numpy-array
arr = np.asarray(img)

#Receiver ip
ip = "XXX.XXX.X.XXX"

#Set up socket and stuff 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

#Loop through each array (5 for test)
for each in range(5):

    #Encode each array
    msg = pickle.dumps(arr[each][0])

    #Send msg to ip with port
    s.sendto(msg, (ip, 50000))

s.close()

这里发生了什么: 我上传了一张图片,然后把它变成了一个 Numpy 数组。然后我取出数组的每一行(每个列表)并用pickle“编码”它,然后通过Socket发送它。到目前为止一切正常。

服务器:

#!/usr/bin/python

import socket
import numpy as np
import cPickle as pickle

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

s.bind(("", 50000)) 

while True:
    data, addr = s.recvfrom(4096)
    conv = pickle.loads(data)
    print conv
    #print np.fromstring(conv,dtype=int)
s.close()

服务器接收编码数据并将其解码回一个 Numpy 数组(这就是我想要实现的)。

最后,它应该将数组重新转换为图像,但由于我目前遇到的问题,我什至没有到达那部分。

我还尝试先将数组转换为字符串,用 pickle 对其进行编码,然后发送它,这样当它被解码时,它就是一个 numpy 数组。但这并没有奏效。

ValueError: 字符串大小必须是元素大小的倍数

我将不胜感激任何形式的帮助,无论是链接还是指出我的错误。 几天来一直在研究这个问题,但没有找到任何可以帮助我解决这个问题的东西。

提前致谢。

【问题讨论】:

  • 我不知道你为什么不直接将图像作为字节发送 - fh = open(... "rb"), sendto(fh.read())
  • 您能再解释一下吗? sendto() 函数是如何工作的?我实际上对套接字和所有这些东西都很陌生,这就是为什么^^
  • 没关系,我现在明白你的意思了,但是消息太长了,所以它不起作用。有没有办法将数据拆分成包,所以我像这样发送它们? socket.error: [Errno 90] Message too long
  • 您不必将文件中的字节转换为字符串(或任何其他东西)来发送它。 pickle 将 Python 对象转换为字节。 sendto() 总是发送字节。
  • 顺便说一句。如果客户端发送数据的时间超过 4096,那么服务器必须在循环中使用recvfrom(4096) 来接收所有数据。问题是服务器不知道使用recvfrom(4096) 的次数,所以首先你应该发送size - 这样你就可以像其他协议一样创建自己的“协议”,即。 HTTP、FTP。因此使用 HTTP 更容易。

标签: python arrays sockets numpy pickle


【解决方案1】:

您不需要 OpenCV 和 NumPy。相反,只需直接发送文件的字节。如果你有 Python 3.5,你甚至可以使用socket.sendfile()

更多详情请见:Sending a file over TCP sockets in Python

【讨论】:

  • 谢谢,不过我已经按照 furas 告诉我的方式解决了。
【解决方案2】:

我不知道你需要多少个小数位,但你可以用 UTF16 BE 编码你的 numpy 数组值,然后在套接字发送后解码

def retrieve_and_decode_data():
    try:
        data,addr = s.recvfrom(4096)                                                                                                                                                                                
        list_of_converted_utf16chars = (repr(data.decode('utf-16')).split("\\")[1:])

    except (ValueError, IndexError) as e:
        **perform some conversion-error exception...**

“repr”函数为您提供 utf16 字符的表示,您可以在 utf 表中查找

然后您可以将此表示形式转换为 int 或 float

integer_value = int(list_of_converted_utf16chars[index], 16)

【讨论】:

  • 谢谢,但我已经按照 furas 告诉我的方式解决了
猜你喜欢
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 2012-08-27
  • 2012-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多