Запись видео с IP-камеры с переменной частотой кадров с opencv и python - PullRequest
0 голосов
/ 15 января 2019

Прежде всего, я хочу прокомментировать то, что я пытаюсь сделать.

У меня есть IP-камера, подключенная к моей сети ( FOSCAM 9800p ) через маршрутизатор с кабелем Ethernet, и с него я пытаюсь записать видео по протоколу RTSP. В будущем я намерен добавить небольшую обработку видео посередине с opencv, но сейчас я хочу провести тесты, чтобы просто записать это.

Основная проблема заключается в том, что камера выдает переменную частоту кадров в секунду, то есть иногда она делает это до 18, другие - до 22 и так далее. При записи видео с фиксированной скоростью кадров в секунду видео проигрывается быстрее, чем должно

Что-то странное, что когда я запускаю с opencv get (CAP_PROP_FPS), он возвращает большое значение, например 180000.0

Чтобы попытаться решить эту проблему, мы читаем фреймы и помещаем их в очередь. Из другого процесса, которым управляет timer.Event (), мы читаем их и пытаемся записывать в наше видео через равные промежутки времени, чтобы получить фиксированную частоту кадров.

Код следующий:

video_capture = cv2.VideoCapture("rtsp://"+user+":"+password+"@"+ip+":"+str(port)+"/videoMain")

if (video_capture.isOpened() == False):
  print("Unable to read camera feed")
  sys.exit()

frame_width = int(video_capture.get(3))
frame_height = int(video_capture.get(4))

video_writer =cv2.VideoWriter(output_filename,cv2.VideoWriter_fourcc(*'MP4V'), fps_to_save, (frame_width,frame_height))
input_buffer = queue.Queue(20)

finished = False

read_frames = 0

def readFile():
    global finished
    global read_frames
    while not finished:
        ret, frame = video_capture.read()
        if not ret:
            finished = True
        while not finished:
            try:
                input_buffer.put_nowait(frame)
                read_frames+=1
                break
            except queue.Full:
                print("queue.Full")
                pass

def processingFile():
    global finished

    written_frames = 0
    repeated_frames = 0

    time_per_frame_elapsed = 0.0

    start_time=time.time()
    ticker = threading.Event()

    while True:
        ticker.wait(time_per_frame-time_per_frame_elapsed)
        time_per_frame_start=time.time()
        try:
            frame = input_buffer.get_nowait()
            video_writer.write(frame)
            writing_time = time.time()
            if written_frames is 0:
                start_time = writing_time
            written_frames += 1
        except queue.Empty:
            if written_frames is not 0:
                video_writer.write(frame)
                writing_time = time.time()
                written_frames += 1
                repeated_frames += 1
        except:
            pass
        total_elapsed_time = time.time() - start_time
        print("total_elapsed_time:{:f}".format(total_elapsed_time))
        if total_elapsed_time>time_to_save_seconds:
          finished = True
          ticker.clear()
          print ("Playback terminated.")
          break
        time_per_frame_elapsed=time.time()-time_per_frame_start
    print("Total readed frames:{:f}".format(read_frames))
    print("Total frames repated:{:f}".format(repeated_frames))
    print("Total frames writed:{:f}".format(written_frames))

tReadFile = threading.Thread(target=readFile)
tProcessingFile = threading.Thread(target=processingFile)

tReadFile.start()
tProcessingFile.start()

tProcessingFile.join()
tReadFile.join()

Результат близок к тому, что мы хотим, но иногда мы имеем значительные различия во времени. Мы проводим тесты с короткими видеороликами продолжительностью около 10 секунд и получаем 9,8 секунды записи.

Сначала это не кажется серьезной проблемой, но ошибка является кумулятивной, то есть, если мы увеличиваем время, увеличивая таким образом, чтобы при записи видео продолжительного времени у нас были более серьезные проблемы.

Мы хотели бы знать, как решить этот тип проблем с видеозаписью с камерами, которые выдают кадры с переменной скоростью. Это хорошая идея?

Что может быть причиной накопленной ошибки за раз?

От уже большое спасибо!

Приветствую всех!

1 Ответ

0 голосов
/ 18 января 2019

Я могу сказать только одно. По моему опыту, класс OpenCV VideoCapture работает с FFMPEG (OpenCV использует его для декодирования видео) в режиме онлайн очень плохо. Было много артефактов изображения и внутренних ошибок ffmpeg. Но VideoCapture отлично работает с USB-камерами. Решил проблему с онлайн-захватом с IP-камеры с помощью XSplit Broadcaster. Этот пакет способен эмулировать USB-камеру через физическую IP-камеру. Единственным ограничением является изменение размера кадра камеры до размера 640 * 480. Базовая лицензия XSplit Broadcaster абсолютно бесплатна

...