OpenCV 4.x and multiple IP cameras
2020-07-21 15:23
Versions used: OpenCV v4.4.0, Python v3.8.5
Camera used: TP-Link Tapo C200
The code below shows how you can capture and display video frames from multiple IP cameras.
import cv2
print("Connecting to cameras ...")
cam1 = cv2.VideoCapture("rtsp://<username>:<password>@<ip>:<port>/stream1")
cam2 = cv2.VideoCapture("rtsp://<username>:<password>@<ip>:<port>/stream1")
cam3 = cv2.VideoCapture("rtsp://<username>:<password>@<ip>:<port>/stream1")
cam4 = cv2.VideoCapture("rtsp://<username>:<password>@<ip>:<port>/stream1")
while True:
ret, frame1 = cam1.read()
ret, frame2 = cam2.read()
ret, frame3 = cam3.read()
ret, frame4 = cam4.read()
if (ret):
cv2.imshow('west', frame1)
cv2.imshow('north', frame2)
cv2.imshow('south', frame3)
cv2.imshow('south-west', frame4)
# keyboard shortcut to kill the application
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
print("Quitting, cleaning up ...")
cv2.destroyAllWindows()
The method shown above is a straightforward approach, especially for OpenCV beginners. The code is to the point, short, and easy to understand.
Still, let us break down what is going on.
Using VideoCapture()
we connect to our cameras with RTSP (Real Time Streaming Protocol), and store the connection in objects cam1-cam4.
Inside an indefinite loop, while True:
, we continously read the frames from VideoCapture instances (cam1-cam4). The read()
method returns the next video frame, it returns false if it receives no frames.
If read()
returned True, we use imshow()
to draw the video frames.
Stacking the camera frames
If you have multiple cameras (or images/other video sources), as in this example, you will have noticed that each camera gets its own window. This is rarely what we would like, as it makes for cumbersome window management. We can fix this by stacking our frames, in a single window, using Numpy and simple matrix operations.
Add the import statement to the top of your source.
import numpy as np
Be sure to install Numpy: pip install numpy
.
Resize our frames so they can all fit inside a single window.
frame1_resized = cv2.resize(frame1, (0, 0), None, 0.5, 0.5)
frame2_resized = cv2.resize(frame2, (0, 0), None, 0.5, 0.5)
frame3_resized = cv2.resize(frame3, (0, 0), None, 0.5, 0.5)
frame4_resized = cv2.resize(frame4, (0, 0), None, 0.5, 0.5)
Using Numpy’s hstack()
we create two horizontal stacks, then feed vstack()
those two horizontal stacks, creating a new vertical one. Now we have a 2x2 grid of cameras.
horizontal_stack1 = np.hstack((frame1_resized, frame2_resized))
horizontal_stack2 = np.hstack((frame3_resized, frame4_resized))
vertical_stack = np.vstack((horizontal_stack1, horizontal_stack2))
cv2.imshow('Camera Monitor', vertical_stack)
The full code:
import cv2
import numpy as np
print("Connecting to cameras ...")
cam1 = cv2.VideoCapture("rtsp://<username>:<password>@<ip>:<port>/stream1")
cam2 = cv2.VideoCapture("rtsp://<username>:<password>@<ip>:<port>/stream1")
cam3 = cv2.VideoCapture("rtsp://<username>:<password>@<ip>:<port>/stream1")
cam4 = cv2.VideoCapture("rtsp://<username>:<password>@<ip>:<port>/stream1")
cameras = cam1, cam2, cam3, cam4
while True:
ret, frame1 = cam1.read()
ret, frame2 = cam2.read()
ret, frame3 = cam3.read()
ret, frame4 = cam4.read()
# resize frames to fit in a single window
frame1_resized = cv2.resize(frame1, (0, 0), None, 0.5, 0.5)
frame2_resized = cv2.resize(frame2, (0, 0), None, 0.5, 0.5)
frame3_resized = cv2.resize(frame3, (0, 0), None, 0.5, 0.5)
frame4_resized = cv2.resize(frame4, (0, 0), None, 0.5, 0.5)
if (ret):
horizontal_stack1 = np.hstack((frame1_resized, frame2_resized))
horizontal_stack2 = np.hstack((frame3_resized, frame4_resized))
# stack the two horizontal stacks vertically, thereby creating a 2x2 grid
vertical_stack = np.vstack((horizontal_stack1, horizontal_stack2))
cv2.imshow('Camera Monitor', vertical_stack)
# keyboard shortcut to kill the application
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
print("Quitting, cleaning up ...")
cv2.destroyAllWindows()