4

ポート 5003 でデータを送信するこの画像サーバーがあります。送信するデータの形式は次のとおりです。画像タイプの 1 バイト (0 = raw、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,

この種の問題を解決する方法を知っている人はいますか?

4

2 に答える 2

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特別な方法を使用する正当な理由がない場合は、使用しないでください。

于 2012-12-15T23:36:00.537 に答える
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)
于 2013-02-25T19:17:02.730 に答える