场景检测通过检测视频中镜头之间的转换,自动将视频镜头分割成多个场景。
pyscenedetect,强大的视频场景检测库,基于python和opencv,查找场景更改或剪切。可以将输出的时间码与另一个工具(例如mkvmerge,ffmpeg)一起使用,将视频分割成单独的片段(或使用分割视频命令),还可以为视频生成逐帧分析,以帮助确定特定视频的最佳阈值或检测模式等。
API:http://scenedetect.com/projects/Manual/en/latest/
1. pyscenedetect检测方法
1)检测阈值 detect-threshold
(将每个帧与设置的黑色级别进行比较,有助于检测到黑色的剪切和淡入/淡出)ThresholdDetector使用设置的强度作为阈值来检测切割,当平均像素强度超过或低于此阈值时会触发切割。
detect-threshold参数:
- threshold = 27 (default,Sensitivity threshold from 0 to 255)
- luma-only = no (or yes)(Discard colour information and only use luminance (yes/no))
- min-scene-len = 0.6s (Minimum length of a given scene)
2)检测内容 detect-content
(按顺序比较每个帧以查找内容的更改,有助于检测视频场景之间的快速剪切,尽管处理速度较慢)ContentDetector将相邻帧之间的内容差异与设置的阈值/分数进行比较,如果超过该阈值/分数,将触发场景剪切。
detect-content参数:
- threshold = 12(Average pixel intensity from 0-255)
- fade-bias 0(from -100.0 to 100.0 of timecode,-100 indicates start frame, +100 indicates end frame)
- add-last-scene = yes
- luma-only = no
- min-scene-len = 0.6s
3)自定义检测算法 detect-adaptive
所有的检测算法必须继承自SceneDetector这个类,AdaptiveDetector与ContentDetector类似,比较相邻帧之间的内容差异,但阈值不是固定的,而是相邻帧变化的滚动平均值。这有助于减少相机快速移动等情况下的错误检测。
detect-adaptive参数:
- threshold = 27
- min-delta-hsv = 15
- rame-window = 2
- luma-only = no
- min-scene-len = 0.6s
- 如果要使用淡入/淡出到黑色来检测场景边界,使用检测阈值模式
- 如果视频在内容之间使用了大量快速剪切,并且没有定义良好的场景边界,则应使用检测内容模式
2. pyscenedetect中主要的类
- VideoManager类:用于加载视频并提供搜索;
- SceneManager类:用于协调SceneDetector,VideoManager和可选的StatsManager对象的高级管理器;
- FrameTimecode类:用于存储时间码以及对时间码值进行算术运算(加/减/比较),并具有帧级的精确度;
- StatsManager类:用于存储/缓存帧指标,以加快在同一视频上后续场景检测的运行速度,并可以保存到CSV文件或从CSV中加载缓存;
- SceneDetector类:用于实现检测算法的基类,如ContentDetector,ThresholdDetector等。
# 示例
import scenedetect as slib
def detect_video_scenes():
scenelist = []
if os.path.isfile(video_file):
try:
videoManager = slib.VideoManager(video_file)
statsManager = slib.StatsManager()
sceneManager = slib.SceneManager(statsManager)
sceneManager.add_detector(slib.ContentDetector())
baseTimecode = videoManager.get_base_timecode()
videoManager.set_downscale_factor()
videoManager.start()
sceneManager.detect_scenes(frame_source=videoManager)
scenelist = sceneManager.get_scene_list(baseTimecode)
if len(scenelist) == 0:
scenelist = [(videoManager.get_base_timecode(), videoManager.get_current_timecode())]
except Exception as e:
print(e)
return scenelist