所以这就是我要做的事情: 有这个图像服务器将在端口5003上发送数据 它将传输的数据格式如下 图像类型为1个字节(0 =原始,1 = JPEG) 然后是图像大小的下一个4字节 然后在那之后将有n个字节,具有以下顺序 宽度为2字节,高度为2字节,B为1字节,R为1字节,G
为1字节所以我要做的是获取数据并使用以下代码将其转换为图像:
#! /usr/bin/python
import socket
import sys
import binascii
from PIL import Image
from StringIO import StringIO
# Connect to the server image
serverHost = 'localhost'
serverPort = 5003
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((serverHost, serverPort))
print >>sys.stderr, 'Connecting to host: ' + str(serverHost)
print >>sys.stderr, 'and server Port: ' + str(serverPort)
s.settimeout(1)
#Receive the image type
imageType = s.recv(1)
print>>sys.stderr, 'received %r' %binascii.hexlify(imageType)
print>>sys.stderr, 'Unpacked: ', int(binascii.hexlify(imageType), 16)
received = imageType.__len__()
print>> sys.stderr, "Received: ", received
#Receive the image size
imageSize = s.recv(4)
print>>sys.stderr, 'received %r' %binascii.hexlify(imageSize)
print>>sys.stderr, 'Unpacked: ', int(binascii.hexlify(imageSize), 16)
received = imageSize.__len__()
print>> sys.stderr, "Received: ", received
#Receive the image Data
imageData = ''
received =0
while(received < int(binascii.hexlify(imageSize), 16)):
buffer = s.recv(4096)
imageData += buffer
received += buffer.__len__()
print>> sys.stderr, "Received: ", received
img = Image.fromstring('RGB', (1280, 720), imageData, 'raw')
#img = Image.open(StringIO(binascii.hexlify(imageData)))
img = img.convert('RGB')
img.save('out.png')
#file = open('test.png', 'w');
#file.write(imageData)
#file.close()
#When we receive the image, we send the acknowledgement
s.send('OK')
s.close()`enter code here`
但每次我运行代码时总是会出现这种错误
"Value error not enough Image Data"
如果改变
img = Image.fromstring('RGB', (1280, 720), imageData, 'raw')
到
img = Image.fromstring('BRG', (1280, 720), imageData, 'raw')
我收到此错误:
Value error: Unrecognized mode,
任何人都知道如何解决这类问题?
答案 0 :(得分:2)
最好在完全给出服务器和客户端的代码时调试这些问题(但只是简单地显示问题)。
因此,以下是基于您的初始代码和描述的非常基本的客户端。请注意,image_type
未使用,它就在那里,因为您提到要区分JPEG和RAW。我总是假设收到的数据是RGB数据,您可以根据实际问题进行调整。这里的主要区别是使用struct
,这是一种标准方式,以通用格式打包数据以通过网络发送,并避免与字节排序相关的问题。此代码还希望接收图像宽度和高度(代码中不存在),因此您可以在客户端重建图像。
import socket
import struct
from PIL import Image
def recv(sock, size):
data = ''
to_receive = size
while to_receive > 0:
data += sock.recv(size)
to_receive = size - len(data)
return data
serv_host = ''
serv_port = 5003
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((serv_host, serv_port))
s.settimeout(1)
image_type = struct.unpack('!b', recv(s, 1))[0]
print "Image type: %d" % image_type
image_size = struct.unpack('!i', recv(s, 4))[0]
print "Image size: %d" % image_size
image_width, image_height = struct.unpack('!hh', recv(s, 4))
print "Image dimensions: %d x %d" % (image_width, image_height)
# Receive image data
image_data = recv(s, image_size)
print len(image_data)
# When we receive the image, we send the acknowledgement.
s.send('OK')
s.close()
img = Image.fromstring('RGB', (image_width, image_height), image_data)
img.save('out.png')
由于未包含服务器,因此以下是一个尊重您所描述的协议的简单服务器。我没有费心检查服务器中完全接收的数据。另请注意,此服务器仅提供运行时在命令行中指定的单个映像。再次,适应您的问题。还要注意我没有发送图像模式,这可能是实际应用中的一个问题。
import sys
import socket
import struct
from PIL import Image
host = ''
port = 5003
backlog = 5
serv_img = Image.open(sys.argv[1])
simg_size = serv_img.size
serv_data = serv_img.tostring()
data_size = len(serv_data)
print "Serving data of size %d" % data_size
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(backlog)
while True:
client, address = s.accept()
client.sendall(struct.pack('!b', 1))
client.sendall(struct.pack('!i', data_size))
client.sendall(struct.pack('!hh', *simg_size))
client.sendall(serv_data)
data = client.recv(2)
if data == 'OK':
print "OK", address
client.close()
关于不使用__len__
的引发注释仅仅是因为它是Python中的一种特殊方法,由len
本身调用。如果你没有任何充分的理由使用特殊方法,那么就不要这样做。
答案 1 :(得分:0)
您提到过使用USARSim的图像服务器。这是我用于从USARSim(UT2004版本)接收图像的代码:
def get_image(sock):
image_type = struct.unpack('b', sock.recv(1))[0]
image_size = struct.unpack('>i', sock.recv(4))[0]
if image_size < 250000:
image_data = ""
received = 0
while (received < image_size):
data = sock.recv(image_size-received)
received += len(data)
image_data += data
filename = "image_%s.jpg" % str(now())
with open(filename, "wb") as f:
f.write(image_data)
def write_ack(sock):
sock.send("OK")
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
while True:
get_image(sock)
write_ack(sock)