# Driver Camera

By
Calvin Ophoff

The simplest useful kind of vision program is one which just pushes an image to the driver station. We do this by using a simple mjpeg stream using mjpeg-streamer . To install, simply run:

pip install mjpeg-streamer

You'll also need OpenCV. Then, the minimally functional program is:

from mjpeg_streamer import MjpegServer, Stream
import cv2

cap = cv2.VideoCapture(0) # replace with whatever camera id you use

stream = Stream("stream_name", size=(640, 480))
server = MjpegServer("127.0.0.1", 1181)
server.add_stream(stream)
server.start()

while True:
    _, frame = cap.read()
    stream.set_frame(frame)

That's a lot, so let's go chunk by chunk:

cap = cv2.VideoCapture(0) # replace with whatever camera id you use

This creates a VideoCapture object around camera 0, but you should swap out 0 for whatever the camera id is. Finding this is notoriously difficult, but if all else fails, try -1, which should use the last available camera.

stream = Stream("stream_name", size=(640, 480))

This creates a mjpeg stream with name stream_name and a specific size. You should change the size parameter to accurately represent the width and height of the images your camera takes in form (width, height).

server = MjpegServer("127.0.0.1", 1181)
server.add_stream(stream)
server.start()

This creates an mjpeg server hosted locally (127.0.0.1 is an ip address that refers to the current computer) on port 1181, accessible from a browser by xx.xx.xx.xx:1181, replacing the xs with the pi's IP address on the network. The stream is then added to the server, and then server is started.

while True:
    _, frame = cap.read()
    stream.set_frame(frame)

Forever, this reads a frame from the camera and then pushes it through the stream.

If you run this program and then navigate to xx.xx.xx.xx:1181, as above, you should be able to see the stream! To stop it, you'll have to press ^C (control-C), potentially twice, to actually stop the program. This will cause it to get a little mad, so to fix that, we can do this instead:

from mjpeg_streamer import MjpegServer, Stream
import cv2

def main():
    cap = cv2.VideoCapture(0) # replace with whatever camera id you use

    stream = Stream("stream_name", size=(640, 480))
    server = MjpegServer("127.0.0.1", 1181)
    server.add_stream(stream)
    server.start()

    while True:
        _, frame = cap.read()
        stream.set_frame(frame)

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        pass

The notable differences are wrapping the code in the function main, and then the if statement at the bottom: __name__ will be set to __main__ if the program is being run from the shell, but not if the file has been imported into another python file; it's just generally a good practice. The try/except KeyboardInterrupt will run main(), which loops until it receives an exception, including a KeyboardInterrupt event (you pressing ^C). By excepting and passing, we can "gracefully" catch the KeyboardInterrupt and end the program from there.