在opencv 3.4.2中更改帧速率

5gfr0r5j  于 2023-04-07  发布在  其他
关注(0)|答案(6)|浏览(269)

我想减少摄像头每秒获取的帧数,这是我使用的代码

#!/usr/bin/env python

import cv2

cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FPS, 10)
fps = int(cap.get(5))
print("fps:", fps)

while(cap.isOpened()):

    ret,frame = cap.read()
    if not ret:
        break

    cv2.imshow('frame', frame)

    k = cv2.waitKey(1)
    if k == 27:
        break

但它不起作用,我仍然有30 fps默认而不是10设置的cap.set(cv2.CAP_PROP_FPS, 10) .我想降低帧率,因为我有一个手探测器,这需要相当多的时间来处理每一帧,我不能在缓冲区中存储帧,因为它会检测到在以前的位置的手。我可以使用计时器或其他东西来运行探测器,但我认为改变fps是一种更简单的方法,但它不起作用,我不知道为什么。
我在Windows 8.1中使用OpenCV 3.4.2和Python 3.6.3

dced5bon

dced5bon1#

设置帧速率并不总是像您期望的那样工作。它取决于两件事:
1.你的相机能输出什么。
1.您使用的当前捕获后端是否支持更改帧速率。
所以点(1).您的相机将有一个格式列表,它能够提供给捕捉设备(例如您的计算机)。这可能是1920x1080@30 fps或1920x1080@60 fps,并且它还指定了像素格式。绝大多数消费相机不允许您以任何粒度更改其帧速率。大多数捕获库将拒绝更改为相机没有广告的捕获格式。
即使是机器视觉摄像机,它允许您进行更多的控制,通常也只提供一种帧速率选择(例如1,2,5,10,15,25,30等)。如果您想要在硬件级别不支持的帧速率,通常唯一的方法是使用硬件触发。
第(2)点。当你使用cv.VideoCapture时,你实际上是在调用一个特定于平台的库,比如DirectShow或V4 L2。我们称之为后端。你可以通过使用以下命令来指定正在使用的后端:
cv2.VideoCapture(0 + cv2.CAP_DSHOW)
定义了很多CAP_X,但只有一部分适用于您的平台。(例如CAP_V4L2仅适用于Linux)。在Windows上,强制系统使用DirectShow是一个相当不错的选择。然而如上所述,如果你的相机只报告它可以输出30 fps和60 fps,请求10 fps将毫无意义。更糟糕的是,很多设置只是在OpenCV中报告True,而实际上它们并没有实现。你已经看到,大多数时候阅读参数会给予你合理的结果,但是如果参数没有实现(例如曝光是一个常见的参数),那么你可能会得到废话。
你最好等待一段时间,然后阅读最后一张图像。
使用此策略时要小心。不要这样做:

while capturing:
    res, image = cap.read()
    time.sleep(1)

您需要确保不断清除相机的帧缓冲区,否则您将开始看到视频中的滞后。类似于以下内容的内容应该可以工作:

frame_rate = 10
prev = 0

while capturing:

    time_elapsed = time.time() - prev
    res, image = cap.read()

    if time_elapsed > 1./frame_rate:
        prev = time.time()

        # Do something with your image here.
        process_image()

对于像手探测器这样的应用程序,最好的方法是让一个线程捕获图像,而探测器在另一个线程中运行(该线程也控制GUI)。您的探测器提取最后捕获的图像,运行并显示结果(您可能需要在阅读/写入图像缓冲区时锁定对图像缓冲区的访问)。这样,您的瓶颈是探测器,而不是相机的性能。

juzqafwq

juzqafwq2#

我无法为我的相机设置FPS,所以我设法根据时间限制FPS,以便只有每秒1帧才能进入我的代码的其余部分。这不是精确的,但我不需要精确的,只是一个限制器而不是30fps。HTH

import time

fpsLimit = 1 # throttle limit
startTime = time.time()
cv = cv2.VideoCapture(0)
While True:
    frame = cv.read
    nowTime = time.time()
    if (int(nowTime - startTime)) > fpsLimit:
        # do other cv2 stuff....
        startTime = time.time() # reset time
cwdobuhd

cwdobuhd3#

正如Josh所说,在openCV上更改相机的fps在很大程度上取决于您的相机是否支持您试图设置的配置。
我设法在Ubuntu 18.04 LTS中更改了openCV的相机fps:
1.使用“sudo apt-get install v4 l-utils”安装v4 l2
1.运行命令“v4 l2-ctl --list-formats-ext”以显示支持的视频格式,包括帧大小和间隔。Results from running v4l2-ctl --list-formats-ext
1.在我的python脚本中:

import cv2

cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')) # depends on fourcc available camera
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
cap.set(cv2.CAP_PROP_FPS, 5)
2o7dmzc5

2o7dmzc54#

属性 CV_CAP_PROP_FPS 仅适用于视频。如果您使用以下命令:

fps = cap.get(cv2.CAP_PROP_FPS)

它返回零。如果你想减少每秒的帧数,那么你可以增加waitkey()的一个参数。例如:

k = cv2.waitKey(100)
svmlkihl

svmlkihl5#

这是我开发的一个类,用于对视频或实时流进行子采样。

from time import time
from typing import Union
import cv2

class Stream():
    """
    extends [cv2::VideoCapture class](https://docs.opencv.org/3.4/d8/dfe/classcv_1_1VideoCapture.html)
    for video or stream subsampling.

    Parameters
    ----------
    filename : Union[str, int]
        Open video file or image file sequence or a capturing device
        or a IP video stream for video capturing.
    target_fps : int, optional
        the target frame rate. To ensure a constant time period between
        each subsampled frames, this parameter is used to compute a
        integer denominator for the extraction frequency. For instance,
        if the original stream is 64fps and you want a 30fps stream out,
        it is going to take one frame over two giving an effective frame
        rate of 32fps.
        If None, will extract every frame of the stream.
    """

    def __init__(self, filename: Union[str, int], target_fps: int = None):
        self.stream_id = filename
        self._cap = cv2.VideoCapture(self.stream_id)
        if not self.isOpened():
            raise FileNotFoundError("Stream not found")

        self.target_fps = target_fps
        self.fps = None
        self.extract_freq = None
        self.compute_extract_frequency()
        self._frame_index = 0

    def compute_extract_frequency(self):
        """evaluate the frame rate over a period of 5 seconds"""
        self.fps = self._cap.get(cv2.CAP_PROP_FPS)
        if self.fps == 0:
            self.compute_origin_fps()

        if self.target_fps is None:
            self.extract_freq = 1
        else:
            self.extract_freq = int(self.fps / self.target_fps)

            if self.extract_freq == 0:
                raise ValueError("desired_fps is higher than half the stream frame rate")

    def compute_origin_fps(self, evaluation_period: int = 5):
        """evaluate the frame rate over a period of 5 seconds"""
        while self.isOpened():
            ret, _ = self._cap.read()
            if ret is True:
                if self._frame_index == 0:
                    start = time()

                self._frame_index += 1

                if time() - start > evaluation_period:
                    break

        self.fps = round(self._frame_index / (time() - start), 2)

    def read(self):
        """Grabs, decodes and returns the next subsampled video frame."""
        ret, frame = self._cap.read()
        if ret is True:
            self._frame_index += 1

            if self._frame_index == self.extract_freq:
                self._frame_index = 0
                return ret, frame

        return False, False

    def isOpened(self):
        """Returns true if video capturing has been initialized already."""
        return self._cap.isOpened()

    def release(self):
        """Closes video file or capturing device."""
        self._cap.release()

使用方法:

stream = Stream(0, 5) # subsample your webcam from probably 30fps to 5fps
stream = Stream("filename_60fps.mp4", 10) # will take on frame over 6 from your video

while stream.isOpened():
    ret, frame = stream.read()
    if ret is True:
        do_something(frame)
wfauudbj

wfauudbj6#

这会解决你的问题

import cv2
import time

cap = cv2.VideoCapture(your video)

initial_time = time.time()
to_time = time.time()

set_fps = 25 # Set your desired frame rate

# Variables Used to Calculate FPS
prev_frame_time = 0 # Variables Used to Calculate FPS
new_frame_time = 0

while True:
    while_running = time.time() # Keep updating time with each frame

    new_time = while_running - initial_time # If time taken is 1/fps, then read a frame

    if new_time >= 1 / set_fps:
        ret, frame = cap.read()
        if ret:
            # Calculating True FPS
            new_frame_time = time.time()
            fps = 1 / (new_frame_time - prev_frame_time)
            prev_frame_time = new_frame_time
            fps = int(fps)
            fps = str(fps)
            print(fps)

            cv2.imshow('joined', frame)
            initial_time = while_running # Update the initial time with current time

        else:
            total_time_of_video = while_running - to_time # To get the total time of the video
            print(total_time_of_video)
            break

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

cap.release()
cv2.destroyAllWindows()

相关问题