Exemple #1
0
def get_video_meta(video_path, one=None):
    """
    Return a bunch of video information with the fields ('length', 'fps', 'width', 'height',
    'duration', 'size')
    :param video_path: A path to the video.  May be a file path or URL.
    :param one: An instance of ONE
    :return: A Bunch of video mata data
    """
    is_url = isinstance(video_path, str) and video_path.startswith('http')
    cap = VideoStreamer(video_path).cap if is_url else cv2.VideoCapture(str(video_path))
    assert cap.isOpened(), f'Failed to open video file {video_path}'

    # Get basic properties of video
    meta = Bunch()
    meta.length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    meta.fps = int(cap.get(cv2.CAP_PROP_FPS))
    meta.width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    meta.height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    meta.duration = timedelta(seconds=meta.length / meta.fps) if meta.fps > 0 else 0
    if is_url and one:
        eid = one.eid_from_path(video_path)
        name = re.match(r'.*(_iblrig_[a-z]+Camera\.raw\.)(?:[\w-]{36}\.)?(mp4)$', video_path)
        det, = one.alyx.rest('datasets', 'list', session=eid, name=''.join(name.groups()))
        meta.size = det['file_size']
    elif is_url and not one:
        meta.size = None
    else:
        meta.size = Path(video_path).stat().st_size
    cap.release()
    return meta
Exemple #2
0
def get_video_frames_preload(
    video_path,
    frame_numbers=None,
    mask=Ellipsis,
    as_list=False,
    func=lambda x: x,
):
    """
    Obtain numpy array corresponding to a particular video frame in video_path.
    Fetching and returning a list is about 33% faster but may be less memory controlled. NB: Any
    gain in speed will be lost if subsequently converted to array.
    :param video_path: URL or local path to mp4 file
    :param frame_numbers: video frames to be returned. If None, return all frames.
    :param mask: a logical mask or slice to apply to frames
    :param as_list: if true the frames are returned as a list, this is faster but may be less
    memory efficient
    :param func: Function to be applied to each frame. Applied after masking if applicable.
    :return: numpy array corresponding to frame of interest, or list if as_list is True.
    Default dimensions are (n, w, h, 3) where n = len(frame_numbers)

    Example - Load first 1000 frames, keeping only the first colour channel:
        frames = get_video_frames_preload(video_path, range(1000), mask=np.s_[:, :, 0])
    """
    is_url = isinstance(video_path, str) and video_path.startswith('http')
    cap = VideoStreamer(video_path).cap if is_url else cv2.VideoCapture(
        str(video_path))
    assert cap.isOpened(), 'Failed to open video'

    frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    frame_numbers = frame_numbers if frame_numbers is not None else range(
        frame_count)

    # Setting the index is extremely slow; determine where frame index must be set
    # The first index is always explicitly set.
    to_set = np.insert(np.diff(frame_numbers), 0, 0) != 1

    if as_list:
        frame_images = [None] * len(frame_numbers)
    else:
        ret, frame = cap.read()
        frame_images = np.empty(
            (len(frame_numbers), *func(frame[mask or ...]).shape), np.uint8)
    for ii, i in enumerate(frame_numbers):
        sys.stdout.write(f'\rloading frame {ii}/{len(frame_numbers)}')
        sys.stdout.flush()
        if to_set[ii]:
            cap.set(cv2.CAP_PROP_POS_FRAMES, i)
        ret, frame = cap.read()
        if ret:
            frame_images[ii] = func(frame[mask or ...])
        else:
            print(f'failed to read frame #{i}')
    cap.release()
    sys.stdout.write('\x1b[2K\r')  # Erase current line in stdout
    return frame_images
Exemple #3
0
def get_video_length(video_path):
    """
    Returns video length
    :param video_path: A path to the video
    :return:
    """
    is_url = isinstance(video_path, str) and video_path.startswith('http')
    cap = VideoStreamer(video_path).cap if is_url else cv2.VideoCapture(
        str(video_path))
    assert cap.isOpened(), f'Failed to open video file {video_path}'
    length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    cap.release()
    return length