python receive image over socket
<p>I'm trying to send an image over a socket - I'm capturing an image on my raspberry pi using pycam, sending to a remote machine for processing, and sending a response back.</p>

<p>On the server (the pi), I'm capturing the image, transforming to an array, rearranging to a 1D array and using the tostring() method.</p>

<p>On the server, the string received is not the same length. Any thoughts on what is going wrong here? Attached is the code I'm running, as well as the output on both the server and the client</p>

<p>SERVER CODE:</p>

<pre><code>from picamera.array import PiRGBArray
from picamera import PiCamera
import socket
import numpy as np
from time import sleep
import sys

camera = PiCamera()
camera.resolution = (640,480)

rawCapture = PiRGBArray(camera)

s = socket.socket()

host = 'myHost'
port = 12345
s.bind((host,port))
s.listen(1)
while True:
    c,addr = s.accept()

    signal = c.recv(1024)
    print 'received signal: ' + signal

    if signal == '1':
        camera.start_preview()
        sleep(2)

        camera.capture(rawCapture, format = 'bgr')
        image = rawCapture.array
        print np.shape(image)
        out = np.reshape(image,640*480*3)

        print out.dtype
        print 'sending file length: ' + str(len(out))

        c.send(str(len(out)))
        print 'sending file'
        c.send(out.tostring())


        print 'sent'

        c.close()
        break
</code></pre>

<p>CLIENT CODE:</p>

<pre><code>import socket, pickle
import cv2
import numpy as np

host = '192.168.1.87'
port = 12345
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

s.send('1')

#while true:
x = long(s.recv(1024))
rawPic = s.recv(x)

print 'Received'
print x

print len(rawPic)
type(rawPic)

#EDITED TO INCLUDE DTYPE
image = np.fromstring(rawPic,np.uint8)
s.close()
</code></pre>

<p>SERVER OUTPUT:</p>

<pre><code>received signal: 1
(480, 640, 3)
uint8
sending file length: 921600
sending file
</code></pre>

<p>CLIENT OUTPUT:</p>

<pre><code>Received
921600
27740
str

ValueError                                Traceback (most recent call last)
&lt;ipython-input-15-9c39eaa92454&gt; in &lt;module&gt;()
----&gt; 1 image = np.fromstring(rawPic)

ValueError: string size must be a multiple of element size
</code></pre>

<p>I'm wondering if the issue is i'm calling tostring() on a uint8, and if the fromstring() is assuming it's a uint32? I can't figure out why the received string is so much smaller than what is sent. </p>

<p><strong>EDIT</strong>
It seems for some reason the server is not fully sending the file. It never prints 'sent', which it should do at completion. If I change the send line to:</p>

<pre><code>c.send(str(len(out[0:100])))
print 'sending file'
c.send(out[0:100].tostring())
</code></pre>

<p>Everything works fine. Thoughts on what could be cutting off my sent file midway through?</p>

<h1>Decoding to the Proper Type</h1>

<p>When you call <code>tostring()</code>, datatype (and shape) information is lost. You must supply numpy with the datatype you expect.</p>

<p>Ex:</p>

<pre><code>import numpy as np

image = np.random.random((50, 50)).astype(np.uint8)
image_str = image.tostring()

# Works
image_decoded = np.fromstring(image_str, np.uint8)

# Error (dtype defaults to float)
image_decoded = np.fromstring(image_str)
</code></pre>

<h1>Recovering Shape</h1>

<p>If shape is always fixed, you can do</p>

<pre><code>image_with_proper_shape = np.reshape(image_decoded, (480, 640, 3))
</code></pre>

<p>In the client.</p>

<p>Otherwise, you'll have to include shape information in your message, to be decoded in the client.</p>

python sockets opencv raspberry-pi