簡體   English   中英

二進制數據到原始python圖像

[英]binary data to image raw python

因此,這是我要嘗試的操作:有一個此圖像服務器將在端口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,

有誰知道如何解決這種問題?

當同時提供了服務器和客戶端的代碼時,最好調試這些問題(但簡化為僅顯示問題)。

因此,以下是一個基於您的初始代碼和描述的非常基本的客戶端。 請注意,沒有使用image_type ,而是使用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本身調用。 如果沒有充分的理由使用特殊方法,則不要這樣做。

您提到使用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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM