0

So I got a Raspberry Pi with the Pi camera and I would like to use the camera with OpenCV in Python. The problem is, I know I can do this easily on the Pi itself but I highly doubt the Pi will be able to process what I want to do. I might be able to optimize my code sometimes in the future but I don't want to worry about that for now.

So what I wanna do instead is send the camera Data (PI camera) to my PC and run all the Python/Opencv code there. Ideally over Ethernet.

I can find a lot about streaming video to a PC using VLC but not how to get the data into Python.

On the Pi I simply use the provided code from rapid-capture-and-streaming

    import io
    import socket
    import struct
    import time
    import picamera
    
    class SplitFrames(object):
        def __init__(self, connection):
           self.connection = connection
           self.stream = io.BytesIO()
           self.count = 0
    
    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # Start of new frame; send the old one's length
            # then the data
            size = self.stream.tell()
            if size > 0:
                self.connection.write(struct.pack('<L', size))
                self.connection.flush()
                self.stream.seek(0)
                self.connection.write(self.stream.read(size))
                self.count += 1
                self.stream.seek(0)
        self.stream.write(buf)
    
    client_socket = socket.socket()
    client_socket.connect(('my_server', 8000))
    connection = client_socket.makefile('wb')
    try:
       output = SplitFrames(connection)
        with picamera.PiCamera(resolution='853x480', framerate=60) as camera:
            time.sleep(2)
            start = time.time()
            camera.start_recording(output, format='mjpeg')
            camera.wait_recording(30)
            camera.stop_recording()
            # Write the terminating 0-length to the connection to let the
            # server know we're done
            connection.write(struct.pack('<L', 0))
    finally:
        connection.close()
        client_socket.close()
       finish = time.time()
    print('Sent %d images in %d seconds at %.2ffps' % (
        output.count, finish-start, output.count / (finish-start)))

and on the client side I'm basically using the code from "capturing-to-a-network-stream" with an added cv2.imshow

import io
import socket
import struct
from PIL import Image
import cv2
import numpy as np

# Start a socket listening for connections on 0.0.0.0:8000 (0.0.0.0 means
# all interfaces)
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
        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
    image_stream.seek(0)
    image = Image.open(image_stream)
    cv_image = np.array(image)
    cv2.imshow('Stream',cv_image)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

finally:
    connection.close()
    server_socket.close()

but nothing is displayed and after a while I get the error socket.gaierror: [Errno -3] Temporary failure in name resolution

6
  • always put FULL error message (starting at word "Traceback") in question (not in comments) as text (not screenshot, not link to external portal). There are other useful information in the full error/traceback.
    – furas
    Aug 3 at 15:52
  • makefile('rb') may use local file to send from one program to another program - but I don't know if it can work when programs are on separated computers.
    – furas
    Aug 3 at 15:56
  • I use program motion on RasperryPi to detect motion - and it runs web server which I can access on other computers using web browser. And in Python I can access stream/image using module requests or urllib (which use protocol HTTP). So RasperryPi runs as server and PC runs as client.
    – furas
    Aug 3 at 16:00
  • I forgot - motion sends image as stream which you can read directly with cap = cv2.VideoCapture("http://...") without using socket - and you can use cap.read() to get frame by frame
    – furas
    Aug 3 at 22:39
  • I'm not sure but VLC should send stream which you could read also with cv2.VideoCapture("http://...") or cv2.VideoCapture("rtmp://...")
    – furas
    Aug 3 at 22:48

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.