Multiple connections via rtsp using Opencv and Python

Asked

Viewed 500 times

1

I recently made a basic Python script using the Opencv library for recognition using security cameras, but I realized that for some reason, I can’t open two or more connections on the same camera, using the same script.

Script used:

import cv2

cap = cv2.VideoCapture("rtsp://link")
while True:
    try:
        _, frame = cap.read()
        cv2.imshow("camera", frame)
        key = cv2.waitKey(1)
        if key & 0xFF == ord('q'):
            break
        pass
    except Exception as e:
        print(e)

When I run the script the first time, it normally opens a window with the image of the camera, but when I leave this script running and try to run again, I get this error in Exception:

Opencv(4.1.2) C: Projects opencv-python opencv modules highgui src window.cpp:376: error: (-215:Assertion failed) size.width>0 && size.height>0 in Function 'cv:imshow'

How can I allow the script to open more windows when running it? If it is a hardware limitation, how can I get around the situation?

Remembering that if I take the rtsp link from the camera and open it in other software, I can open several windows with the camera images, only with this script I get the error when trying to run again with it running.

Update

After searching a little on the internet, I saw that recommend using socket to be able to have a server taking the image of the camera and when clients connect to the server via socket, the image of the camera is shown.

Server.py

import base64
import cv2
import zmq

context = zmq.Context()
footage_socket = context.socket(zmq.PUB)
footage_socket.connect('tcp://localhost:5555')

camera = cv2.VideoCapture("rtsp://link")  # init the camera

while True:
    try:
        _, frame = camera.read()  # grab the current frame
        frame = cv2.resize(frame, (640, 480))  # resize the frame
        encoded, buffer = cv2.imencode('.jpg', frame)
        jpg_as_text = base64.b64encode(buffer)
        footage_socket.send(jpg_as_text)
    except KeyboardInterrupt:
        camera.release()
        cv2.destroyAllWindows()
        break

Client py.

import cv2
import zmq
import base64
import numpy as np

context = zmq.Context()
footage_socket = context.socket(zmq.SUB)
footage_socket.setsockopt_string(zmq.SUBSCRIBE, np.unicode(''))
footage_socket.bind('tcp://*:5554')

while True:
    try:
        frame = footage_socket.recv_string()
        img = base64.b64decode(frame)
        npimg = np.fromstring(img, dtype=np.uint8)
        source = cv2.imdecode(npimg, 1)
        cv2.imshow("Stream", source)
        cv2.waitKey(1)

    except KeyboardInterrupt:
        cv2.destroyAllWindows()
        break

But the problem now is when I have more than one client connected to the server, I get the answer:

Address in use

How can I fix this?

  • Checks if the path to your file is correct pq it seems that it is not finding the video image. If using \ in the path, use the escape \\

  • I believe that’s not the problem, because the script works normally, I just can’t keep two connections open.

1 answer

0

I take it you’re trying to run multiple clients on the same machine, right?

A server socket is listed on a single port, gives here a look at more info. All client connections established on that server are associated with the same port on the server side of the connection. An established connection is uniquely identified by the combination of client-side IP/port pairs and the server. Multiple connections on the same server can share the same server-side IP/port pair, provided they are associated with different client-side IP/port pairs, and the server can handle as many clients as the available system resources allow.

On the customer side, it is common practice for new outgoing connections to use a random port on the customer, or see the code below that I share to verify an available port. Using Andom, in which case you can run out of available ports if you make many connections in a short period of time.

Or use the following code to get the available port, source:

import SimpleHTTPServer
import SocketServer

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler

port = 8000
while True:
    try:
        httpd = SocketServer.TCPServer(('', port), Handler)
        print 'Serving on port', port
        httpd.serve_forever()
    except SocketServer.socket.error as exc:
        if exc.args[0] != 48:
            raise
        print 'Port', port, 'already in use'
        port += 1
    else:
        break

Browser other questions tagged

You are not signed in. Login or sign up in order to post.