使用opencv和python从具有可变帧速率的IP摄像机的视频记录

时间:2019-01-15 02:31:55

标签: python opencv video-capture

首先,我想评论一下我想做的事情。

我有一个IP摄像机通过带有以太网电缆的路由器连接到我的网络(FOSCAM 9800p),并且我正尝试通过它通过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 :(得分:0)

我只能说一件事。以我自己的经验,OpenCV VideoCapture类在联机模式下与FFMPEG一起使用(OpenCV使用它来解码视频)非常糟糕。图像伪影和ffmpeg内部错误很多。但是VideoCapture可以完美地与USB摄像机配合使用。我使用XSplit Broadcaster解决了从IP摄像机进行在线捕获的问题。该软件包能够通过物理IP摄像机模拟USB摄像机。唯一的限制是将相机框架的尺寸调整为640 * 480。 XSplit Broadcaster的基本许可证是完全免费的