#
Driver Camera
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.
127.0.0.1 will not work as the ip address on a computer that isn't the pi,
since it also refers to the current computer on that computer, meaning it is
expecting the stream to be hosted on that computer, not the pi!
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.