- 音视频
- 视频处理
- 图形学
- 桌面应用
【免费下载链接】Natron
Open-source video compositing software. Node-graph based. Similar in functionalities to Adobe After Effects and Nuke by The Foundry.
Natron 是一个基于节点图的开源视频合成软件,其 Tracker(跟踪器)节点用于在画面中放置标记点(Track)并沿时间轴自动跟踪目标。本文以官方开发者文档(PythonTutorials/tracker.rst)为核心,完整讲解如何通过 Python 脚本访问 Tracker 节点、读取每条 Track 的动画数据(如中心点关键帧),以及如何用代码创建和驱动 Track;读完你将能够脱离界面、纯脚本化完成跟踪数据的提取与跟踪任务的启动与停止。
一、核心对象模型:Tracker 与 Track
Natron 的所有跟踪功能都集中在Tracker类中(详见 PythonReference/NatronEngine/Tracker.rst)。目前只有 Tracker 节点能够持有一个Tracker对象。该对象由 Natron 在创建节点时自动声明(auto-declared),可以直接作为节点的属性访问:
app.Tracker1.trackerTracker对象本身是若干条Track的容器。Track类表示用户能在查看器(Viewer)上看到的一个跟踪标记点,其完整方法说明见 PythonReference/NatronEngine/Track.rst。
这种自动声明变量的机制在 Natron 中被广泛使用(节点、参数、图层、Bezier 曲线等都适用),其背景是:与其调用一串函数(如app1.getNode("app1.Blur1")),不如直接使用一个简单变量(如app1.Blur1)。相关约定可参考 scriptvslabel.rst。要使用自动声明变量,对象必须采用合法的 Python 命名规则(script-name 只包含字母数字字符且不以数字开头)。
通过 script-name 访问 Track
Track可以通过其 script-name 直接访问:
app.Tracker1.tracker.track1Track 的 script-name 可以在 Tracker 节点的设置面板(settings panel)中查看到——将鼠标悬停在列表的 Label 列上,工具提示会显示该标记点的 script-name:
在命令行模式或脚本编辑器中,也可以调用Track类的getScriptName()函数获取 script-name(对应源码 Engine/PyTracker.cpp,内部读取TrackMarker::getScriptName_mt_safe())。
提示:script-name 与 label 是两个不同的概念——script-name 用于脚本/代码中唯一标识对象,创建后不可更改;label 是界面上显示的名字,可以任意修改。同一 Tracker 中多个 track 的 label 可以重复,但 script-name 必须唯一。
二、从 Track 中读取跟踪数据
在 Natron 内部,一条 Track 实际上就是一组参数(Param)的集合,这些参数和普通效果节点的参数一样,可以保存动画曲线(关键帧)数据。每条 Track 内置的数据参数包括(参数 script-name 定义于 Engine/TrackMarker.h):
| 参数 script-name | 含义 | 说明 |
|---|---|---|
centerPoint | 跟踪中心点 | 二维参数,被跟踪目标的位置,即“要跟踪的点” |
offset | 偏移 | 相对真实跟踪位置施加到中心点的偏移量 |
patternTopLeft/patternTopRight/patternBtmRight/patternBtmLeft | Pattern 四角 | 定义被跟踪模式(Pattern)的四边四边形四个角 |
searchWndBtmLeft/searchWndTopRight | 搜索窗口 | 搜索窗口的左下/右上点,相对中心点定义 |
motionModel | 运动模型 | 跟踪使用的变换模型(见下文) |
errorValue | 误差值 | 每帧跟踪后得到的误差,等于 1 减去互相关得分 |
trackWeight | 权重 | 该标记点对最终求解结果的贡献权重 |
enabled | 启用开关 | 勾选时该 track 数据才会用于生成最终的 Transform/CornerPin 输出,可动画化以控制 track 的生命周期 |
这些参数在 Engine/TrackMarker.cpp 中由AppManager::createKnob<...>创建并绑定(如centerKnob->setName(kTrackerParamCenter),kTrackerParamCenter即字符串"centerPoint")。
两种访问参数的方式
既可以按 script-name 直接作为属性访问:
app.Tracker1.tracker.track1.centerPoint也可以调用getParam(paramScriptName)函数:
app.Tracker1.tracker.track1.getParam("centerPoint")getParam()的源码实现(Engine/PyTracker.cpp)会从内部的TrackMarker中按名字查找 Knob,并将其包装成 Python 可用的Param对象返回;若找不到则返回空。getParams()则返回该 track 的全部参数列表。
实战示例:提取中心点的全部关键帧
下面的示例来自官方教程,演示如何取出一条 track 在中心点上的所有(X, Y 同时存在的)关键帧:
myTrack = app.Tracker1.tracker.track1 keyframes = [] # get the number of keys for the X dimension only and try match the Y keyframes nKeys = myTrack.centerPoint.getNumKeys(0) for k in range(0,nKeys): # getKeyTime returns a tuple with a boolean value indicating if it succeeded and # the keyframe time gotXKeyTuple = myTrack.centerPoint.getKeyTime(k, 0) frame = gotXKeyTuple[1] # Only consider keyframes which have an X and Y value # If Y does not have a keyframe at this frame, ignore the keyframe # getKeyIndex returns a value >=0 if there is a keyframe yKeyIndex = myTrack.centerPoint.getKeyIndex(frame, 1) if yKeyIndex == -1: continue # Note that even if the x curve or y curve didn't have a keyframe we # could still call getValueAtTime but the value would be interpolated by # Natron with surrounding keyframes, which is not what we want. x = myTrack.centerPoint.getValueAtTime(frame, 0) y = myTrack.centerPoint.getValueAtTime(frame, 1) keyframes.append((x,y)) print keyframes代码要点拆解:
getNumKeys(0):返回 X 维度上的关键帧数量(参数是维度号,0表示 X、1表示 Y)。getKeyTime(k, 0):返回一个元组,第一个元素是布尔值表示是否成功,第二个元素是关键帧时间。getKeyIndex(frame, 1):查询 Y 曲线上在指定帧是否存在关键帧,返回值>= 0表示存在,-1表示不存在。- 为什么用
getKeyIndex做双重校验?因为即使 X 或 Y 曲线上没有关键帧,也可以调用getValueAtTime取值,但这时值会被 Natron 用周围关键帧插值得到,这通常不是我们想要的——本示例只收集“X 与 Y 都有真实关键帧”的数据点。
跟踪完成后,得到的keyframes列表即可用于后续的脚本化处理,例如写入导出文件、驱动 CornerPin 或 Transform 节点,或作为二次求解(如 openMVG 的 PROSAC 鲁棒估计,参考 Tests/Tracker_Test.cpp)的输入。
三、创建 Track 与重置
用 createTrack() 新建跟踪点
要新建一条 track,使用Tracker类提供的createTrack()函数:
track = app.Tracker1.tracker.createTrack()随后就可以像操作 Natron 中其他对象一样,对返回的 track 参数设置数值。其底层实现(Engine/PyTracker.cpp)调用TrackerContext::createMarker()(见 Engine/TrackerContext.h),创建一个带默认值的TrackMarker并包装成 PythonTrack返回。
Tracker类完整的方法一览(均可在 Python 中调用):
| 方法 | 作用 |
|---|---|
createTrack() | 在 tracker 中新建一条 track,返回Track对象 |
getTrackByName(scriptName) | 按 script-name 查找并返回对应的Track,找不到则返回空 |
getAllTracks() | 返回该 Tracker 中的所有Track(序列) |
getSelectedTracks() | 返回当前用户在界面中选中的Track(序列) |
startTracking(tracks, start, end, forward) | 对给定 tracks 从start帧跟踪到end帧 |
stopTracking() | 停止该 Tracker 上任何正在进行的跟踪 |
对应的 C++ 声明见 Engine/PyTracker.h,其中getAllTracks/getSelectedTracks内部遍历TrackerContext的标记列表并逐个包装为Track(Engine/PyTracker.cpp)。
Track 的脚本管理方法
Track类还提供以下方法用于脚本化管理:
setScriptName(scriptName):设置 track 的 script-name,设置后即可通过Tracker1.tracker.MyTrackScriptName这样的形式在脚本中访问。源码见 Engine/PyTracker.cpp。getScriptName():获取 track 的 script-name。getParam(paramScriptName):按 script-name 获取参数。getParams():返回该 track 的所有参数列表。reset():完全重置 track,清除所有参数上的动画与 Pattern 上的关键帧(底层调用TrackMarker::resetTrack())。
用脚本启动与停止跟踪
startTracking(tracks, start, end, forward)是对给定 tracks 发起跟踪的核心接口。需要注意的语义(与官方文档一致):
- 跟踪范围是
[start, end),即end帧本身不会被跟踪; forward为True时正向跟踪(end应大于start);forward为False时反向跟踪,此时end应小于start。
例如从第 1 帧正向跟踪到第 100 帧:
tracks = app.Tracker1.tracker.getAllTracks() app.Tracker1.tracker.startTracking(tracks, 1, 100, True)停止正在进行的跟踪:
app.Tracker1.tracker.stopTracking()从源码看,startTracking会把这些Track解包为内部的TrackMarker列表并交给TrackerContext::trackMarkers(...)(Engine/PyTracker.cpp),最终由TrackScheduler(继承自GenericSchedulerThread,见 Engine/TrackerContext.h)在后台线程中逐帧调度执行;stopTracking则调用TrackerContext::abortTracking()中止任务。跟踪过程中每帧的误差会写入errorValue参数(其 hint 注明“误差 = 1 - 互相关得分”),可用于脚本化评估跟踪质量。
四、底层实现速览:从 Python 到 C++ 的调用链
理解底层调用链有助于排查脚本问题。当你在 Python 中访问app.Tracker1.tracker时,实际发生的是(Engine/Node.cpp 的declareTrackerPythonField()):
- 拼出完全限定名(如
app.Tracker1),执行 Python 语句nodeFullName + ".tracker = " + nodeFullName + ".getTrackerContext()",把 Tracker 对象绑定为节点属性; - 随后调用
TrackerContext::declarePythonFields(),把每个 TrackMarker 作为属性(如track1)声明到tracker对象上,这样app.Tracker1.tracker.track1才能直接访问。
Tracker/Track的 Python 包装类(NATRON_PYTHON_NAMESPACE下的Tracker与Track,见 Engine/PyTracker.h)内部各持有一个TrackerContextPtr/TrackMarkerPtr智能指针,所有 Python 调用最终都落到 Engine 层的TrackerContext与TrackMarker实现上——这也是为什么通过脚本读写参数、启动跟踪,与在 GUI 上操作的效果完全一致。
五、小结与延伸
本文覆盖了 Natron Tracker 节点 Python 脚本化的全部核心能力:
- 通过自动声明变量访问
Tracker与Track对象; - 使用
getParam()/ 属性访问读取centerPoint、offset、Pattern 四角、errorValue等动画参数; - 用
getNumKeys/getKeyTime/getKeyIndex/getValueAtTime安全地提取双维度关键帧数据; - 用
createTrack()/setScriptName()/reset()管理 track; - 用
startTracking(tracks, start, end, forward)与stopTracking()脚本化驱动跟踪任务。
更系统的功能讲解可继续阅读 tracker.rst(使用 tracker 功能)、类参考 Tracker.rst 与 Track.rst;若希望了解跟踪求解(鲁棒变换估计)的算法层细节,可进一步研读 TrackerContext.h 与 Tracker_Test.cpp 中的测试用例。
- 音视频
- 视频处理
- 图形学
- 桌面应用
【免费下载链接】Natron
Open-source video compositing software. Node-graph based. Similar in functionalities to Adobe After Effects and Nuke by The Foundry.
相关推荐
Natron Python API 深入解析:使用 Track 类读取与操作 Tracker 节点的跟踪数据
Natron Python API 深入解析:使用 Track 类读取与操作 Tracker 节点的跟踪数据 导读 本文以 Natron 官方 Python 参
音视频视频处理图形学桌面应用Natron 节点图脚本实战:用 Python 批量读取 Roto 节点条目标签
Natron 节点图脚本实战:用 Python 批量读取 Roto 节点条目标签 本篇技术指南围绕 Natron 官方开发文档中的 getRotoItemsLa
音视频视频处理图形学桌面应用Natron 的 Tracker Python API 完全指南:从轨迹容器到自动化跟踪实战
Natron 的 Tracker Python API 完全指南:从轨迹容器到自动化跟踪实战 Natron 中的 Tracker 类是为需要跟踪能力的特效节点(
音视频视频处理图形学桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考