繁体   English   中英

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

[英]Video record from an IP camera with variable frame rate with opencv and python

首先,我想评论一下我要做什么。

我有一台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秒钟的录制时间。

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

我们想知道如何使用以可变速率传送帧的摄像机来解决此类视频记录问题。 这样做是个好主意吗?

在什么时候会产生累积误差?

从已经非常感谢你!

祝福大家!

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM