简体   繁体   English

Python3.5通过套接字发送对象(Pygame cam图像)

[英]Python3.5 send object over socket (Pygame cam image)

I want to send a PyGame Image over socket with Python 3.5 and i always got a bug. 我想使用Python 3.5通过套接字发送PyGame图像,但我总是遇到一个错误。

I get the image, i pickle it, and then i send it. 我得到图像,将其腌制,然后发送。

In the client, i receive it, i unpickle it, and i show it. 在客户那里,我收到了它,给它解开了皮,然后给了我看。

But i've got an error : 但是我有一个错误:

fenetre.blit(img, (20, 30)) pygame.error: display Surface quit

Here is my code for the server ( the one wich send image ) : 这是我的服务器代码(一个发送图像):

pygame.init()
pygame.camera.init()
cam = pygame.camera.Camera("/dev/video0", (680, 480))
cam.start()
class Streaming(Thread):


    def __init__(self):
        Thread.__init__(self)
    def run(self):

        s = socket.socket()
        s.bind(('192.168.1.158', 12801))
        s.listen(1)
        while True:
            sc, info = s.accept()
            print("Video client connected : "+str(info))
            try:
                while True:
                    image = cam.get_image()
                    str_img = pickle.dumps(image)
                    sc.send(str_img)
                    print(str_img)
                    print("Sending Image")
                    time.sleep(0.005)
            except Exception as e:
                print(str(e))

And the code for the client : 和客户端的代码:

fenetre = pygame.display.set_mode((900, 900))
class Receiving(Thread):


    def __init__(self):
        Thread.__init__(self)

        self.clock = pygame.time.Clock()

    def run(self):
        global fenetre
        si = socket.socket()
        si.connect(("192.168.1.158", 12801))
        while True:
            img = si.recv(4096)
            img = pickle.loads(img)
            fenetre.blit(img, (20, 30))
            pygame.display.flip()
            self.clock.tick(60)

Thank in advance ! 预先感谢 !

I made example which sends surface with current time. 我以发送当前时间的表面为例。

(Pygame can't work with my camera). (Pygame无法与我的相机配合使用)。

It uses struc.pack() to send image size always as 4 bytes before image is send. 它使用struc.pack()在发送图像之前始终以4个字节发送图像大小。 So client first receives 4 bytes and have image size. 因此,客户端首先接收4个字节并具有图像大小。 Then it can use this information to receive image. 然后,它可以使用此信息来接收图像。

Both use loops to send/receive all the time. 两者都使用循环来始终发送/接收。

server.py server.py

#!/usr/bin/env python

import pygame
from threading import Thread
import socket
import struct # to send `int` as  `4 bytes`
import time   # for test

# --- constants ---

ADDRESS = ("localhost", 12801)

SURFACE_SIZE = (640, 480)

WHITE = (255, 255, 255)
BLACK = (  0,   0,   0)
GREEN = (  0, 255,   0)

# --- classes ---

class Streaming(Thread):

    def __init__(self):
        Thread.__init__(self)

        pygame.init()

        #pygame.camera.init()
        #self.cam = pygame.camera.Camera("/dev/video0", SURFACE_SIZE)
        #self.cam.start()

        # create surface to imitate camera image
        self.image = pygame.Surface(SURFACE_SIZE)
        self.image_rect = self.image.get_rect()

        # create font to display text on surface
        self.font = pygame.font.Font(None, 50)

    def get_image(self):
        # emulate cam.get_image()

        # get current time as string
        current_time = time.strftime('%H:%M:%S.%s')

        # render surface with text (and center it)
        text = self.font.render(current_time, True, BLACK, GREEN)
        text_rect = text.get_rect(center=self.image_rect.center)

        # clear image and put new text
        self.image.fill(WHITE)
        self.image.blit(text, text_rect)

        return self.image

    def run(self):

        s = socket.socket()

        # solution for: "socket.error: [Errno 98] Address already in use"
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        s.bind(ADDRESS)
        s.listen(1)

        print("Wait for connection")

        try:
            sc, info = s.accept()
            print("Video client connected:", info)

            while True:
                # get image surface

                #image = self.cam.get_image()
                image = self.get_image()

                # convert surface to string

                img_str = pygame.image.tostring(image, 'RGB')

                print('len:', len(img_str))

                # send string size

                len_str = struct.pack('!i', len(img_str))
                sc.send(len_str)

                # send string image

                sc.send(img_str)

                # wait

                time.sleep(0.5)

        except Exception as e:
            print(e)
        finally:
            # exit
            print("Closing socket and exit")
            sc.close()
            s.close()
            pygame.quit()

# --- main ---

Streaming().run()

client.py client.py

#!/usr/bin/env python

import pygame
from threading import Thread
import socket
import struct

# --- constants ---

ADDRESS = ("localhost", 12801)

SURFACE_SIZE = (640, 480)

# --- classes ---

class Receiving(Thread):

    def __init__(self):
        Thread.__init__(self)

        pygame.init()

        self.screen = pygame.display.set_mode((800, 600))
        self.screen_rect = self.screen.get_rect()

        self.clock = pygame.time.Clock()

    def run(self):
        s = socket.socket()
        s.connect(ADDRESS)

        try:
            running = True
            while running:
                # receive size

                len_str = s.recv(4)
                size = struct.unpack('!i', len_str)[0]

                print('size:', size)

                # receive string

                img_str = b''

                while size > 0:
                    if size >= 4096:
                        data = s.recv(4096)
                    else:
                        data = s.recv(size)

                    if not data:
                        break

                    size -= len(data)
                    img_str += data

                print('len:', len(img_str))

                # convert string to surface

                image = pygame.image.fromstring(img_str, SURFACE_SIZE, 'RGB')
                image_rect = image.get_rect(center=self.screen_rect.center)

                # blit

                self.screen.blit(image, image_rect)
                pygame.display.flip()

                #self.clock.tick(30)

                # wait for ESC or close window

                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        running = False
                    elif event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_ESCAPE:
                            running = False

        except Exception as e:
            print(e)
        finally:
            # exit
            print("Closing socket and exit")
            s.close()
            pygame.quit()

# --- main ---

Receiving().run()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM