Beispiel #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
Beispiel #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
Beispiel #3
0
def get_video_frame(video_path, frame_number):
    """
    Obtain numpy array corresponding to a particular video frame in video_path
    :param video_path: local path to mp4 file
    :param frame_number: video frame to be returned
    :return: numpy array corresponding to frame of interest.  Dimensions are (w, h, 3)
    """
    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))
    # 0-based index of the frame to be decoded/captured next.
    cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
    ret, frame_image = cap.read()
    cap.release()
    return frame_image
Beispiel #4
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
Beispiel #5
0
def test_simple():
    frame_id = 4000
    dset = one.alyx.rest('datasets',
                         'list',
                         session=eid,
                         name='_iblrig_leftCamera.raw.mp4')[0]
    url = next(fr['data_url'] for fr in dset['file_records'] if fr['data_url'])
    vs = VideoStreamer(url)
    f, im = vs.get_frame(frame_id)
    assert vs.total_frames == 77897
    assert f
    vs = VideoStreamer(dset)
    f, im2 = vs.get_frame(frame_id)
    assert np.all(im == im2)
Beispiel #6
0
 def test_video_streamer(self):
     dset = one.alyx.rest('datasets',
                          'list',
                          session=self.eid,
                          name='_iblrig_leftCamera.raw.mp4')[0]
     url = next(fr['data_url'] for fr in dset['file_records']
                if fr['data_url'])
     frame_id = 5
     vs = VideoStreamer(url)
     f, im = vs.get_frame(frame_id)
     assert f
     assert vs.total_frames == 144120
     # Test with data set dict
     vs = VideoStreamer(dset)
     f, im2 = vs.get_frame(frame_id)
     assert np.all(im == im2)
from oneibl.stream import VideoStreamer

FRAME_ID = 4000

# example 1: with URL directly
url = "http://ibl.flatironinstitute.org/mainenlab/Subjects/ZM_1743/2019" \
      "-06-17/001/raw_video_data/_iblrig_leftCamera.raw.00002677-a6d1-49fb-888b-66679184ee0e.mp4"
vs = VideoStreamer(url)
f, im = vs.get_frame(FRAME_ID)

# example 2: with URL directly
from oneibl.one import ONE  # noqa

one = ONE()
eid = "a9fb578a-9d7d-42b4-8dbc-3b419ce9f424"
dset = one.alyx.rest('datasets',
                     'list',
                     session=eid,
                     name='_iblrig_leftCamera.raw.mp4')
vs = VideoStreamer(dset[0])
f, im = vs.get_frame(FRAME_ID)