티스토리 뷰

3.8. 파이카메라 네트워크 스트림 캡처

이는 timelapse 시퀀스 캡처의 변형입니다. 여기서 우리는 두 개의 스크립트를 가지고 있습니다 : 서버 (아마도 빠른 머신에 있음)는 Raspberry Pi로부터의 연결을 청취하고, 클라이언트는 Raspberry Pi에서 실행되어 이미지를 연속적으로 서버로 전송합니다. 우리는 아주 간단한 통신 프로토콜을 사용합니다 : 먼저 이미지의 길이가 32 비트 정수 (Little Endian 형식)로 전송 된 다음 이미지 데이터의 바이트가옵니다. 길이가 0이면 더 이상 이미지가 제공되지 않으므로 연결을 닫아야 함을 나타냅니다. 이 프로토콜은 다음과 같습니다.

먼저 서버 스크립트 (JPEG를 읽는 데 PIL을 사용하지만 OpenCV 또는 GraphicsMagick과 같은 다른 적합한 그래픽 라이브러리로 대체 할 수 있음)

import io import socket import struct from PIL import Image # Start a socket listening for connections on 0.0.0.0:8000 (0.0.0.0 means # all interfaces)0.0.0.0:8000에서 연결을 수신하는 소켓 시작 (0.0.0.0은 모든 인터페이스를 의미

server_socket = socket.socket() server_socket.bind(('0.0.0.0', 8000)) server_socket.listen(0) # Accept a single connection and make a file-like object out of it 단일 연결을 수락하고 파일과 같은 객체를 생성합니다

connection = server_socket.accept()[0].makefile('rb')
try:
    while True:
        # Read the length of the image as a 32-bit unsigned int. If the
        # length is zero, quit the loop 이미지의 길이를 32 비트 부호없는 int로 읽습니다. 길이가 0이면 루프를 종료합니다.
 
        image_len = struct.unpack('<L', connection.read(struct.calcsize('<L')))[0]
        if not image_len:
            break
        # Construct a stream to hold the image data and read the image
        # data from the connection 이미지 데이터를 저장하고 연결에서 이미지 데이터를 읽을 스트림을 구성합니다.
        image_stream = io.BytesIO()
        image_stream.write(connection.read(image_len))
        # Rewind the stream, open it as an image with PIL and do some
        # processing on it 스트림을 되감고, PIL로 이미지로 열고 그것을 처리한다.
        image_stream.seek(0)
        image = Image.open(image_stream)
        print('Image is %dx%d' % image.size)
        image.verify()
        print('Image is verified')
finally:
    connection.close()
    server_socket.close()



이제 클라이언트의 측면에서 보면 Raspberry Pi :


import io
import socket
import struct
import time
import picamera

# Connect a client socket to my_server:8000 (change my_server to the
# hostname of your server)클라이언트 소켓을 my_server : 8000에 연결합니다 (my_server를 서버의 호스트 이름으로 변경).
client_socket = socket.socket()
client_socket.connect(('my_server', 8000))

# Make a file-like object out of the connection 파일과 같은 객체를 연결에서 제외시킵니다.
connection = client_socket.makefile('wb')
try:
    camera = picamera.PiCamera()
    camera.resolution = (640, 480)
    # Start a preview and let the camera warm up for 2 seconds 미리보기를 시작하고 2 초 동안 예열하도록합니다.
    camera.start_preview()
    time.sleep(2)

    # Note the start time and construct a stream to hold image data
    # temporarily (we could write it directly to connection but in this
    # case we want to find out the size of each capture first to keep
    # our protocol simple) 시작 시간에주의하고 이미지 데이터를 일시적으로 보관할 스트림을 만듭니다 
    #(연결에 직접 쓸 수는 있지만이 경우 간단하게 프로토콜을 유지하기 위해 각 캡처의 크기를 알아 내야합니다)

start = time.time() stream = io.BytesIO() for foo in camera.capture_continuous(stream, 'jpeg'): # Write the length of the capture to the stream and flush to # ensure it actually gets sent 캡처의 길이를 스트림에 쓰고 플러시하여 실제로 전송되는지 확인합니다. connection.write(struct.pack('<L', stream.tell())) connection.flush() # Rewind the stream and send the image data over the wire 스트림을 되감고 이미지 데이터를 와이어를 통해 전송합니다. stream.seek(0) connection.write(stream.read()) # If we've been capturing for more than 30 seconds, quit 우리가 30 초 이상 캡처하면, 그만두기 if time.time() - start > 30: break # Reset the stream for the next capture 다음 캡처를 위해 스트림 재설정 stream.seek(0) stream.truncate() # Write a length of zero to the stream to signal we're done 우리가 완료되었음을 알리기 위해 길이 0을 스트림에 쓴다. connection.write(struct.pack('<L', 0)) finally: connection.close() client_socket.close()

클라이언트 스크립트에서 연결을 허용 할 준비가 된 리스닝 소켓이 있는지 확인하기 위해 먼저 서버 스크립트를 실행해야합니다.

댓글
최근에 달린 댓글
글 보관함
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Total
Today
Yesterday
    뽀로로친구에디
    최근에 올라온 글