I am new to posting questions on this site so forgive me if this isn't in the best place or if I do something wrong.
I have two Pi's and I am trying to capture images in a loop (giving me a video), with the Raspberry Pi camera and send each through a socket to the other Pi and display them with pygame. I will also need low latency.
I have tried many different methods and think I have gotten fairly close. The code I have right now is posted at the bottom. There are however, a lot of other things I have tried. For example, I tried using the PiCamera module to capture an image and then make it a PIL image right away (instead of capturing an image with pygame). The code below seems to be fairly close but I can only seem to get the delay to about 5 seconds.
I also tried using UDP but could not get time image.tostring
small enough to send through the socket.
I realize there are other ways to do this, like mjpg-streamer
but I wanted something a bit less complicated that I could understand.
Any help would be appreciated!
server:
import socket
import pygame as game
import sys
from PIL import Image
port=9012
address="192.168.1.10" #server's ip
size=width, height= 640, 480
scale=width, height=40, 10
timer = 0
previousImage = ""
image = ""
message=[]
#establish socket connection
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((address, port))
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#initialize pygame
game.init()
screen=game.display.set_mode(size)
game.display.set_caption('Socket Raspi Camera Viewer')
#clock = game.time.Clock()
#listen on the port
s.listen(1)
#main loop
while 1:
for event in game.event.get():
if event.type == game.QUIT:
sys.exit()
#accept socket connection
connection, addr= s.accept()
#Recieve data from the server:
data=connection.recv(1024000)
print(sys.getsizeof(data))
#store the previous recieved image incase the client fails to recive all of the data for the new image
previousImage=image
#We use a try clause to the program will not abort if there is an error:
try:
#We turn the data we revieved into a 120x90 PIL image:
#image = Image.fromstring("RGB",(120,90),data)
#We resize the image to 640x480:
pil_image = Image.fromstring("RGBA", size, data)
pil_image= pil_image.resize(size)
new_data=pil_image.tostring()
image=game.image.fromstring(new_data, size, "RGBA")
except:
#If we failed to recieve a new image we display the last image we revieved:
print("falied to recieve image")
image = previousImage
#Set the var output to our image:
#output = image
#We use PyGame to blit the output image to the screen:
screen.blit(image,(0,0))
#We update the screen:
game.display.flip()`
client:
import pygame as game
import pygame.camera
import sys
import time
from PIL import Image
port=9012
address="192.168.1.10" #server's ip
size=width, height= 640, 480
scale=width, height= 40, 10
timer=0
game.init()
game.camera.init()
screen=game.display.set_mode(size)
camera=game.camera.Camera("/dev/video0", size )
camera.start()
time.sleep(1)
while True:
if timer < 1:
#connect to the server
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((address, port))
#get image
image=camera.get_image()
#convert to pill image to scale
string_image=game.image.tostring(image, "RGBA",False)
pil_image=Image.fromstring("RGBA",size,string_image)
pil_image =pil_image.resize(scale)
buffer=pil_image.tostring()
#print size of buffer
print(sys.getsizeof(buffer))
s.sendall(buffer)
#time.sleep(0.01)
s.close()
timer=30
#
Stream without resizing: client-
while True:
image=camera.getimage()
buffer=pygame.image.tostring(image)
socket.send(buffer)
Server:
while True:
message=[]
while True:
string=socket.recieve(1024 * 1024)
if string == '':
break
else:
message.append(string)
full_string="".join(message)
image=game.fromstring(full_string)
game.blit(image, (0,0))
game.display.update()