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()