在numpy中,我有一系列bools。从图像中检索出数组;它是二维的,包含1024列和768行。我想通过以太网电缆推送这些数据。有多种方法可以做到这一点,但就我的目的而言,速度非常关键,因此记忆也非常重要。
由于每个数组中有1024 x 768 = 786432
个元素(像素),并且每个元素都是True
或False
,理论上可以将数组打包成98,304个未压缩的字节或96千字节。
786432 bits / 8 bits per byte = 98304 bytes
98304 bytes / 1024 bytes per kilobyte = 96 kilobytes
这需要展平数组
[ [True, False, True, ..., True]
[False, True, True, ..., True]
...
[True, True, False, ..., False] ]
# flatten the array
[True, False, True, ..., False]
理论上可以将其表示为字节位,因为786,432位均匀地适合98,304字节;每个数组应该能够用98,304个八位字符表示。
如何通过以太网快速发送1024×768 bool
个numpy阵列?我正在查看bitstring
python库,但我不确定如何快速将numpy数组管道化为bitstring
类。
具体来说,我将这些数组从Raspberry Pi 2发送到常规的Raspberry Pi。
socket
和SOCK_STREAM
是最快的解决方法吗?bitstring
内容,但是pickle对象太大而无法通过SOCK_STREAM
发送。我对socket
的东西做错了吗?import socket
from scipy.misc import imread
import numpy
IP = '127.0.0.1'
PORT = 7071
ADDRESS = (IP, PORT)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
image = imread('input.png')[:,:,[2]]
image[image < 170] = 0
image[image != 0] = 1
image = numpy.reshape(image, (-1, 1))
image = numpy.packbits(image)
data = image.tostring()
sock.connect(ADDRESS)
for i in range(0, 93804, 1024):
sock.send(data[i:i+1024])
sock.shutdown(socket.SHUT_WR)
sock.close()
import socket
from scipy.misc import imsave
import numpy
IP = '127.0.0.1'
PORT = 7071
ADDRESS = (IP, PORT)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(ADDRESS)
sock.listen(1)
while True:
c, addr = sock.accept()
data = ''
package = c.recv(1024)
while package:
data += package
package = c.recv(1024)
image = numpy.fromstring(data, dtype=numpy.uint8)
image = numpy.unpackbits(image)
image = numpy.reshape(image, (-1, 768))
imsave('output.png', image)
c.close()
sock.close()
正如您所看到的,我通过一系列1024字节的数据包通过TCP / SOCK_STREAM结束了每个数组。
答案 0 :(得分:6)
您可以使用np.packbits
将np.bool
数组的内容打包到np.uint8
数组的1/8大小的数组中,这样每个数组都可以打包#{1}}数组。布尔元素仅使用一个位。可以使用np.unpackbits
恢复原始数组。
import numpy as np
x = array([0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1], dtype=np.bool)
print(x.itemsize, x.nbytes)
# (1, 16)
xp = np.packbits(x)
print(xp)
# [ 24 139]
print(xp.itemsize, xp.nbytes)
# (1, 2)
print(np.unpackbits(xp))
# [0 0 0 1 1 0 0 0 1 0 0 0 1 0 1 1]
从这里开始最明显的方法是将打包的数组序列化为原始字符串pipe it through a UDP socket,然后反序列化并在另一侧解压缩。 numpy的本机序列化(.tostring()
和np.fromstring()
)可能比使用pickle
或cPickle
快得多。
如果你想玩压缩,一个选择是使用本机zlib
模块压缩字节串然后再通过管道,然后在另一侧解压缩。您是否从中看到任何好处将在很大程度上取决于输入阵列的可压缩程度,以及执行压缩/解压缩的硬件。