def test_metrics():
    """ Test StatsManager metric registration/setting/getting with a set of pre-defined
    key-value pairs (metric_dict).
    """
    metric_dict = {'some_metric': 1.2345, 'another_metric': 6.7890}
    metric_keys = list(metric_dict.keys())

    stats = StatsManager()
    frame_key = 100
    assert not stats.is_save_required()

    stats.register_metrics(metric_keys)

    assert not stats.is_save_required()
    with pytest.raises(FrameMetricRegistered):
        stats.register_metrics(metric_keys)

    assert not stats.metrics_exist(frame_key, metric_keys)
    assert stats.get_metrics(frame_key, metric_keys) == [None] * len(metric_keys)

    stats.set_metrics(frame_key, metric_dict)

    assert stats.is_save_required()

    assert stats.metrics_exist(frame_key, metric_keys)
    assert stats.metrics_exist(frame_key, metric_keys[1:])

    assert stats.get_metrics(frame_key, metric_keys) == [
        metric_dict[metric_key] for metric_key in metric_keys]
def test_metrics():
    """ Test StatsManager metric registration/setting/getting with a set of pre-defined
    key-value pairs (metric_dict).
    """
    metric_dict = {'some_metric': 1.2345, 'another_metric': 6.7890}
    metric_keys = list(metric_dict.keys())

    stats = StatsManager()
    frame_key = 100
    assert not stats.is_save_required()

    stats.register_metrics(metric_keys)

    assert not stats.is_save_required()
    with pytest.raises(FrameMetricRegistered):
        stats.register_metrics(metric_keys)

    assert not stats.metrics_exist(frame_key, metric_keys)
    assert stats.get_metrics(frame_key, metric_keys) == [None] * len(metric_keys)

    stats.set_metrics(frame_key, metric_dict)

    assert stats.is_save_required()

    assert stats.metrics_exist(frame_key, metric_keys)
    assert stats.metrics_exist(frame_key, metric_keys[1:])

    assert stats.get_metrics(frame_key, metric_keys) == [
        metric_dict[metric_key] for metric_key in metric_keys]
Exemplo n.º 3
0
def test_load_hardcoded_file():
    """ Test loading a stats file with some hard-coded data generated by this test case. """

    stats_manager = StatsManager()
    with open(TEST_STATS_FILES[0], 'w') as stats_file:

        stats_writer = get_csv_writer(stats_file)

        some_metric_key = 'some_metric'
        some_metric_value = 1.2
        some_frame_key = 100
        base_timecode = FrameTimecode(0, 29.97)
        some_frame_timecode = base_timecode + some_frame_key

        # Write out a valid file.
        stats_writer.writerow(
            [COLUMN_NAME_FRAME_NUMBER, COLUMN_NAME_TIMECODE, some_metric_key])
        stats_writer.writerow([
            some_frame_key,
            some_frame_timecode.get_timecode(),
            str(some_metric_value)
        ])

        stats_file.close()

        stats_file = open(TEST_STATS_FILES[0], 'r')
        stats_manager.load_from_csv(csv_file=stats_file)

        # Check that we decoded the correct values.
        assert stats_manager.metrics_exist(some_frame_key, [some_metric_key])
        assert stats_manager.get_metrics(
            some_frame_key,
            [some_metric_key])[0] == pytest.approx(some_metric_value)
def test_save_load_from_video(test_video_file):
    """ Test generating and saving some frame metrics from TEST_VIDEO_FILE to a file on disk, and
    loading the file back to ensure the loaded frame metrics agree with those that were saved.
    """
    video_manager = VideoManager([test_video_file])
    stats_manager = StatsManager()
    scene_manager = SceneManager(stats_manager)

    base_timecode = video_manager.get_base_timecode()

    scene_manager.add_detector(ContentDetector())

    try:
        video_fps = video_manager.get_framerate()
        start_time = FrameTimecode('00:00:00', video_fps)
        duration = FrameTimecode('00:00:20', video_fps)

        video_manager.set_duration(start_time=start_time, end_time=duration)
        video_manager.set_downscale_factor()
        video_manager.start()
        scene_manager.detect_scenes(frame_source=video_manager)

        with open(TEST_STATS_FILES[0], 'w') as stats_file:
            stats_manager.save_to_csv(stats_file, base_timecode)

        stats_manager_new = StatsManager()

        with open(TEST_STATS_FILES[0], 'r') as stats_file:
            stats_manager_new.load_from_csv(stats_file, base_timecode)

        # Choose the first available frame key and compare all metrics in both.
        frame_key = min(stats_manager._frame_metrics.keys())
        metric_keys = list(stats_manager._registered_metrics)

        assert stats_manager.metrics_exist(frame_key, metric_keys)
        orig_metrics = stats_manager.get_metrics(frame_key, metric_keys)
        new_metrics = stats_manager_new.get_metrics(frame_key, metric_keys)

        for i, metric_val in enumerate(orig_metrics):
            assert metric_val == pytest.approx(new_metrics[i])

    finally:
        os.remove(TEST_STATS_FILES[0])

        video_manager.release()
def test_save_load_from_video(test_video_file):
    """ Test generating and saving some frame metrics from TEST_VIDEO_FILE to a file on disk, and
    loading the file back to ensure the loaded frame metrics agree with those that were saved.
    """
    video_manager = VideoManager([test_video_file])
    stats_manager = StatsManager()
    scene_manager = SceneManager(stats_manager)

    base_timecode = video_manager.get_base_timecode()

    scene_manager.add_detector(ContentDetector())

    try:
        video_fps = video_manager.get_framerate()
        start_time = FrameTimecode('00:00:00', video_fps)
        duration = FrameTimecode('00:00:20', video_fps)

        video_manager.set_duration(start_time=start_time, end_time=duration)
        video_manager.set_downscale_factor()
        video_manager.start()
        scene_manager.detect_scenes(frame_source=video_manager)

        with open(TEST_STATS_FILES[0], 'w') as stats_file:
            stats_manager.save_to_csv(stats_file, base_timecode)

        stats_manager_new = StatsManager()

        with open(TEST_STATS_FILES[0], 'r') as stats_file:
            stats_manager_new.load_from_csv(stats_file, base_timecode)

        # Choose the first available frame key and compare all metrics in both.
        frame_key = min(stats_manager._frame_metrics.keys())
        metric_keys = list(stats_manager._registered_metrics)

        assert stats_manager.metrics_exist(frame_key, metric_keys)
        orig_metrics = stats_manager.get_metrics(frame_key, metric_keys)
        new_metrics = stats_manager_new.get_metrics(frame_key, metric_keys)

        for i, metric_val in enumerate(orig_metrics):
            assert metric_val == pytest.approx(new_metrics[i])

    finally:
        os.remove(TEST_STATS_FILES[0])

        video_manager.release()
Exemplo n.º 6
0
def test_detector_metrics(test_video_file):
    """ Test passing StatsManager to a SceneManager and using it for storing the frame metrics
    from a ContentDetector.
    """
    video_manager = VideoManager([test_video_file])
    stats_manager = StatsManager()
    scene_manager = SceneManager(stats_manager)
    #base_timecode = video_manager.get_base_timecode()

    assert not stats_manager._registered_metrics
    scene_manager.add_detector(ContentDetector())
    # add_detector should trigger register_metrics in the StatsManager.
    assert stats_manager._registered_metrics

    try:
        video_fps = video_manager.get_framerate()
        start_time = FrameTimecode('00:00:00', video_fps)
        duration = FrameTimecode('00:00:20', video_fps)

        video_manager.set_duration(start_time=start_time, end_time=duration)
        video_manager.set_downscale_factor()
        video_manager.start()
        scene_manager.detect_scenes(frame_source=video_manager)

        # Check that metrics were written to the StatsManager.
        assert stats_manager._frame_metrics
        frame_key = min(stats_manager._frame_metrics.keys())
        assert stats_manager._frame_metrics[frame_key]
        assert stats_manager.metrics_exist(
            frame_key, list(stats_manager._registered_metrics))

        # Since we only added 1 detector, the number of metrics from get_metrics
        # should equal the number of metric keys in _registered_metrics.
        assert len(
            stats_manager.get_metrics(
                frame_key, list(stats_manager._registered_metrics))) == len(
                    stats_manager._registered_metrics)

    finally:
        video_manager.release()
def test_load_hardcoded_file(test_video_file):
    """ Test loading a stats file with some hard-coded data generated by this test case. """
    from scenedetect.stats_manager import COLUMN_NAME_FPS
    from scenedetect.stats_manager import COLUMN_NAME_FRAME_NUMBER
    from scenedetect.stats_manager import COLUMN_NAME_TIMECODE

    stats_manager = StatsManager()
    stats_file = open(TEST_STATS_FILES[0], 'w')

    try:
        stats_writer = get_csv_writer(stats_file)

        some_metric_key = 'some_metric'
        some_metric_value = 1.2
        some_frame_key = 100
        base_timecode = FrameTimecode(0, 29.97)
        some_frame_timecode = base_timecode + some_frame_key

        # Write out a valid file.
        stats_writer.writerow([COLUMN_NAME_FPS, '%.10f' % base_timecode.get_framerate()])
        stats_writer.writerow(
            [COLUMN_NAME_FRAME_NUMBER, COLUMN_NAME_TIMECODE, some_metric_key])
        stats_writer.writerow(
            [some_frame_key, some_frame_timecode.get_timecode(), str(some_metric_value)])

        stats_file.close()

        stats_file = open(TEST_STATS_FILES[0], 'r')
        stats_manager.load_from_csv(csv_file=stats_file, base_timecode=base_timecode)

        # Check that we decoded the correct values.
        assert stats_manager.metrics_exist(some_frame_key, [some_metric_key])
        assert stats_manager.get_metrics(
            some_frame_key, [some_metric_key])[0] == pytest.approx(some_metric_value)

    finally:
        stats_file.close()
        os.remove(TEST_STATS_FILES[0])
def test_detector_metrics(test_video_file):
    """ Test passing StatsManager to a SceneManager and using it for storing the frame metrics
    from a ContentDetector.
    """
    video_manager = VideoManager([test_video_file])
    stats_manager = StatsManager()
    scene_manager = SceneManager(stats_manager)
    #base_timecode = video_manager.get_base_timecode()

    assert not stats_manager._registered_metrics
    scene_manager.add_detector(ContentDetector())
    # add_detector should trigger register_metrics in the StatsManager.
    assert stats_manager._registered_metrics

    try:
        video_fps = video_manager.get_framerate()
        start_time = FrameTimecode('00:00:00', video_fps)
        duration = FrameTimecode('00:00:20', video_fps)

        video_manager.set_duration(start_time=start_time, end_time=duration)
        video_manager.set_downscale_factor()
        video_manager.start()
        scene_manager.detect_scenes(frame_source=video_manager)

        # Check that metrics were written to the StatsManager.
        assert stats_manager._frame_metrics
        frame_key = min(stats_manager._frame_metrics.keys())
        assert stats_manager._frame_metrics[frame_key]
        assert stats_manager.metrics_exist(frame_key, list(stats_manager._registered_metrics))

        # Since we only added 1 detector, the number of metrics from get_metrics
        # should equal the number of metric keys in _registered_metrics.
        assert len(stats_manager.get_metrics(
            frame_key, list(stats_manager._registered_metrics))) == len(
                stats_manager._registered_metrics)

    finally:
        video_manager.release()
Exemplo n.º 9
0
def test_load_hardcoded_file_backwards_compat():
    """ Test loading a stats file with some hard-coded data generated by this test case.

    Ensures backwards compatibility with old statsfiles which included an addional header.
    """

    stats_manager = StatsManager()
    with open(TEST_STATS_FILES[0], 'w') as stats_file:
        stats_writer = get_csv_writer(stats_file)

        some_metric_key = 'some_metric'
        some_metric_value = 1.2
        some_frame_key = 100
        base_timecode = FrameTimecode(0, 29.97)
        some_frame_timecode = base_timecode + some_frame_key

        # Write out a valid file as per PySceneDetect v0.5.4 and prior.
        stats_writer.writerow(['Video Framerate', '23.976'])
        stats_writer.writerow(
            [COLUMN_NAME_FRAME_NUMBER, COLUMN_NAME_TIMECODE, some_metric_key])
        stats_writer.writerow([
            some_frame_key,
            some_frame_timecode.get_timecode(),
            str(some_metric_value)
        ])

        stats_file.close()

        stats_file = open(TEST_STATS_FILES[0], 'r')
        stats_manager.load_from_csv(csv_file=stats_file)

        # Check that we decoded the correct values.
        assert stats_manager.metrics_exist(some_frame_key, [some_metric_key])
        assert stats_manager.get_metrics(
            some_frame_key,
            [some_metric_key])[0] == pytest.approx(some_metric_value)
Exemplo n.º 10
0
def make_dataset(video_path, video_name, timecodes, save_dir):
    # type: (str) -> List[Tuple[FrameTimecode, FrameTimecode]]
    video_manager = VideoManager([video_path])
    stats_manager = StatsManager()
    # Construct our SceneManager and pass it our StatsManager.
    scene_manager = SceneManager(stats_manager)

    # Add ContentDetector algorithm (each detector's constructor
    # takes detector options, e.g. threshold).
    scene_manager.add_detector(ContentDetector())
    base_timecode = video_manager.get_base_timecode()

    # We save our stats file to {VIDEO_PATH}.stats.csv.
    stats_file_path = 'stats/%s.stats.csv' % video_name

    scene_list = []

    try:
        # If stats file exists, load it.
        if os.path.exists(stats_file_path):
            # Read stats from CSV file opened in read mode:
            with open(stats_file_path, 'r') as stats_file:
                stats_manager.load_from_csv(stats_file, base_timecode)

        # Set downscale factor to improve processing speed.
        video_manager.set_downscale_factor()

        # Start video_manager.
        video_manager.start()

        # Perform scene detection on video_manager.
        scene_manager.detect_scenes(frame_source=video_manager)

        # We only write to the stats file if a save is required:
        if stats_manager.is_save_required():
            with open(stats_file_path, 'w') as stats_file:
                stats_manager.save_to_csv(stats_file, base_timecode)

        start_timecode = ""
        start_content_val = 0
        end_timecode = ""
        end_content_val = 0
        metric_keys = sorted(
            list(
                stats_manager._registered_metrics.union(
                    stats_manager._loaded_metrics)))
        frame_keys = sorted(stats_manager._frame_metrics.keys())
        for frame_key in frame_keys:
            frame_timecode = base_timecode + frame_key
            timecode = frame_timecode.get_timecode()
            if timecode > timecodes[0] and timecode < timecodes[1]:
                content_val = stats_manager.get_metrics(
                    frame_key, metric_keys)[0]
                if start_content_val < content_val:
                    start_content_val = content_val
                    start_timecode = timecode
            if timecode > timecodes[2] and timecode < timecodes[3]:
                content_val = stats_manager.get_metrics(
                    frame_key, metric_keys)[0]
                if end_content_val < content_val:
                    end_content_val = content_val
                    end_timecode = timecode
        threshold = min(start_content_val, end_content_val)

        print(f"Start Time: {start_timecode}, End Time: {end_timecode}")

    finally:
        video_manager.release()

    video_manager = VideoManager([video_path])
    stats_manager = StatsManager()
    scene_manager = SceneManager(stats_manager)
    scene_manager.add_detector(ContentDetector(threshold=threshold))
    base_timecode = video_manager.get_base_timecode()

    scene_list = []

    try:
        # If stats file exists, load it.
        if os.path.exists(stats_file_path):
            # Read stats from CSV file opened in read mode:
            with open(stats_file_path, 'r') as stats_file:
                stats_manager.load_from_csv(stats_file, base_timecode)

        # Set downscale factor to improve processing speed.
        video_manager.set_downscale_factor()

        # Start video_manager.
        video_manager.start()

        # Perform scene detection on video_manager.
        scene_manager.detect_scenes(frame_source=video_manager)

        # Obtain list of detected scenes.
        scene_list = scene_manager.get_scene_list(base_timecode)
        # Each scene is a tuple of (start, end) FrameTimecodes.

        start_video_num = 0
        end_video_num = 0
        for i, scene in enumerate(scene_list):
            if scene[0].get_timecode(
            ) >= start_timecode and start_video_num == 0:
                start_video_num = i
                print(f"start video: {start_video_num}")
            if scene[1].get_timecode() >= end_timecode and end_video_num == 0:
                end_video_num = i
                print(f"end video: {end_video_num}")

    finally:
        video_manager.release()

    video_dir = os.path.join(save_dir, video_name)
    if not os.path.exists(video_dir):
        os.makedirs(video_dir)

    split_video_ffmpeg([video_path], scene_list,
                       os.path.join(video_dir,
                                    "${VIDEO_NAME}-${SCENE_NUMBER}.mp4"),
                       video_name)

    return start_video_num, end_video_num, len(scene_list)