1

My IP camera seems to be a little unstable and disconnects randomly. I'd like my script to be able to determine when its disconnected and attempt to reconnect a few times, probably waiting 5-10 seconds between attempts. I've tried a few things, but nothing is working.

This is my basic script, when ret is false the script ends:

#!/usr/local/bin/python3

import cv2
import time
import datetime

print("start time: " + datetime.datetime.now().strftime("%A %d %B %Y %I:%M:%S%p"))

cap = cv2.VideoCapture('rtsp://<ip><port>/live0.264')

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()

    # Confirm we have a valid image returned
    if not ret:
        print("disconnected!")
        break

    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)

    # Display the resulting frame
    cv2.imshow('frame', gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

print("end time: " + time.strftime("%X"))
# When everything is done, release the capture
cap.release()
cv2.destroyAllWindows()

Edit: I would also like the script to try to reconnect to the camera in the event that my network goes down temporarily or anything like that as well.

brewcrazy
  • 623
  • 13
  • 30
  • 1
    what isn't working? is there an error? – Salmaan P Nov 26 '17 at 23:07
  • Actualy I don't know the solution but I think you havbe to fix your ip camera I have never seen randomly disconnected ip camera before – Berkay Yıldız Nov 26 '17 at 23:09
  • This is a cheap camera. I have no control over its firmware or whatever is causing it to disconnect. Even if the issue wasn't the camera, I want the script to be able to recover the connection to the camera if it disconnects for any other reason. – brewcrazy Nov 26 '17 at 23:15
  • What have you tried? You say "a few things"? Is the problem in the delay or in the reconnection itself? It looks like you've already nailed a way of having it check if the camera is disconnected so I'm guessing that's not what you're asking about? It might also be best practice not to use a While True and instead incorporate the `if cv2.waitKey` into the While check. – neophlegm Nov 27 '17 at 00:09
  • The problem is reconnecting. I've tried creating a function that calls `cv2.VideoCapture()`. That function would be called when there's nothing returned from `cap.read()` in `if not ret:` – brewcrazy Nov 27 '17 at 00:30

2 Answers2

4

I was finally able to solve this myself. Hopefully this is useful for anyone else looking to do the same thing.

This is actually a shell of a more complex script that has logic for motion detection and video recording when motion is detected. Everything is working very well with this basic logic (and my crappy IP camera) although I am still doing testing.

#!/usr/local/bin/python3

import cv2
import datetime
import time


def reset_attempts():
    return 50


def process_video(attempts):

    while(True):
        (grabbed, frame) = camera.read()

        if not grabbed:
            print("disconnected!")
            camera.release()

            if attempts > 0:
                time.sleep(5)
                return True
            else:
                return False


recall = True
attempts = reset_attempts()

while(recall):
    camera = cv2.VideoCapture("rtsp://<ip><port>/live0.264")

    if camera.isOpened():
        print("[INFO] Camera connected at " +
              datetime.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p"))
        attempts = reset_attempts()
        recall = process_video(attempts)
    else:
        print("Camera not opened " +
              datetime.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p"))
        camera.release()
        attempts -= 1
        print("attempts: " + str(attempts))

        # give the camera some time to recover
        time.sleep(5)
        continue
brewcrazy
  • 623
  • 13
  • 30
2

More detailed description:

https://github.com/Combinacijus/various-code-samples/tree/master/Python/OpenCV/ip_cam_reconnecting

Wrote a class to deal with IP camera disconnecting randomly. Main idea is to check if cap.read() returns a frame and if it doesn't it tries to reconnect to the camera.

import cv2
import requests  # NOTE: Only used for forceful reconnection
import time  # NOTE: Only used for throttling down printing when connection is lost


class IPVideoCapture:
    def __init__(self, cam_address, cam_force_address=None, blocking=False):
        """
        :param cam_address: ip address of the camera feed
        :param cam_force_address: ip address to disconnect other clients (forcefully take over)
        :param blocking: if true read() and reconnect_camera() methods blocks until ip camera is reconnected
        """

        self.cam_address = cam_address
        self.cam_force_address = cam_force_address
        self.blocking = blocking
        self.capture = None

        self.RECONNECTION_PERIOD = 0.5  # NOTE: Can be changed. Used to throttle down printing

        self.reconnect_camera()

    def reconnect_camera(self):
        while True:
            try:
                if self.cam_force_address is not None:
                    requests.get(self.cam_force_address)

                self.capture = cv2.VideoCapture(self.cam_address)

                if not self.capture.isOpened():
                    raise Exception("Could not connect to a camera: {0}".format(self.cam_address))

                print("Connected to a camera: {}".format(self.cam_address))

                break
            except Exception as e:
                print(e)

                if self.blocking is False:
                    break

                time.sleep(self.RECONNECTION_PERIOD)

    def read(self):
        """
        Reads frame and if frame is not received tries to reconnect the camera

        :return: ret - bool witch specifies if frame was read successfully
                 frame - opencv image from the camera
        """

        ret, frame = self.capture.read()

        if ret is False:
            self.reconnect_camera()

        return ret, frame


if __name__ == "__main__":
    CAM_ADDRESS = "http://192.168.8.102:4747/video"  # NOTE: Change
    CAM_FORCE_ADDRESS = "http://192.168.8.102:4747/override"  # NOTE: Change or omit
    cap = IPVideoCapture(CAM_ADDRESS, CAM_FORCE_ADDRESS, blocking=True)
    # cap = IPVideoCapture(CAM_ADDRESS)  # Minimal init example

    while True:
        ret, frame = cap.read()

        if ret is True:
            cv2.imshow(CAM_ADDRESS, frame)

        if cv2.waitKey(1) == ord("q"):
            break
Combinacijus
  • 405
  • 2
  • 8