用OpenCV和PYTHON实现可变帧速率的IP摄像机录像

Video record from an IP camera with variable frame rate with opencv and python(用OpenCV和PYTHON实现可变帧速率的IP摄像机录像)

本文介绍了用OpenCV和PYTHON实现可变帧速率的IP摄像机录像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我想对我正在尝试做的事情发表评论。 我有一台IP摄像机通过带有以太网线的路由器连接到我的网络(FOSCAM 9800p),我正尝试从它录制使用RTSP协议的视频。我未来的打算是在中间添加一个OpenCV的小视频处理功能,但目前我想做一些测试,以便简单地录制它。

主要问题是摄像机每秒传输的帧速率是可变的,也就是说,有时它会传输到18帧,其他时候会传输到22帧,以此类推。当以每秒固定的帧速率录制视频时,最终会出现视频播放速度过快

奇怪的是,当我使用OpenCV GET(CAP_PROP_FPS)运行时,它返回一个很大的值,如180000.0

要尝试解决此问题,我们要做的是读取帧并将它们放入队列。从计时器控制的另一个进程。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秒的记录。

起初,这似乎不是一个严重的问题,但错误是累积的,也就是说,如果我们增加时间增加,那么录制时间更长的视频就会有更严重的问题。

我们想知道如何使用以不同速率传送帧的相机来解决这种类型的视频录制问题。这样做好吗?

是什么原因导致时间累积误差?

从已经开始非常感谢!

大家好!

推荐答案

我只能说一件事。在我个人的经验中,OpenCV视频捕获类在在线模式下与FFMPEG(OpenCV使用它来解码视频)的工作非常糟糕。有很多图像伪像和ffmpeg内部错误。但VideoCapture与USB摄像头配合使用效果非常好。我用XSplit广播器解决了IP摄像机的在线捕捉问题。这个包能够通过物理IP摄像头模拟USB摄像头。唯一的限制是将相机帧的大小调整为640*480大小。XSplit广播公司的基本许可证是完全免费的

这篇关于用OpenCV和PYTHON实现可变帧速率的IP摄像机录像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:用OpenCV和PYTHON实现可变帧速率的IP摄像机录像