SVT-AV1中的global-MV/仿射运动实现分析

一 逻辑实现
函数作用

这是一个路由函数,router function,根据配置的 correspondence_method, 选择使用哪种方法来收集对应点,correspondences, 对应点是全局运动估计的基础数据。

在全局运动估计流程中的位置。

全局运动估计的完整流程

1 收集阶段,-本函数,根据配置选择方法收集对应点

方法A,角点检测方法,correspondence from corners

方法B, MV方法,correspondence from mvs

输出:对应点数组,当前帧位置,参考帧位置。

2 合并阶段,RANSAC算法,将收集到的对应点聚合成全局运动模型

在compute+global motion中调用determine gm parames()->svt_aom_ransac()

RANSAC算法从大量对应点中找出最能代表全局运动的模型参数

输出:全局运动模型参数,放射变换矩阵等

3 应用阶段,在模式决策中使用全局运动模型为每个块计算MV

两种方法的对比:

角点方法

原理:基于图像特征,角点进行匹配,不依赖运动估计结果

优点:更鲁棒,精度高,不依赖ME质量,适合复杂运动

缺点:计算复杂度中等

适用场景:复杂运动,ME质量差时,需要高精度时

MV方法,(MV_64x64, MV_32x32, MV_16x16/MV_8x8)

原理:从运动估计结果中提取MV,转换为对应点

优点:计算速度快,利用已有的ME结果

缺点:依赖ME质量,精度受ME影响

适用场景:ME质量好时,需要快速计算时。

函数参数说明:

复制代码
pcs 图像父控制集,包含`
` gm_ctrls.correspondence_method 对应点收集方法配置`
 `pa_me_data: 运动估计数据MV方法需要`
 `其他全局运动相关配置`
`frm_buffer 当前帧图像缓冲区,亮度分量`
`frm_width 当前帧宽度,像素`
`frm_height 当前帧高度`
`frm_stride 当前帧行跨度,字节数,用于访问图像数据`
`frm_corners 输入,当前帧已经检测的角点数组,仅角点方法使用`
    `格式[x0, y0, x1, y1, x2, y2, ...]`
    `在调用本函数前已经通过svt_av1_fast_corner_detect() 检测完成`
    `MV方法不使用此参数`
`num_frm_corners 输入,当前帧角点数量,仅角点方法使用`
`ref 参考帧图像缓冲区,亮度分量`
`ref_stride 参考帧行跨度`
`correspondences 输出:收集到的对应点数组,每个对应点表示,当前帧位置(x,y) 参考帧位置(rx, ry)`
`这些对应点将被传递给RANSAC算法进行聚合`

`num_correspondences 输出 实际手机到的对应点数量`
`list_idx 参考帧列表索引,MV方法使用`
`0 list0 前向参考帧`
`1 list1 后向参考帧`
`ref_idx 参考帧索引,仅MV方法使用`
`在指定列表中的位置 (0,1,2,....)`

`void gm_compute_correspondence(PictureParentControlSet* pcs, uint8_t *frm_buffer, int frm_width, int frm_height, int frm_stride, int *frm_corners, int num_frm_corners, uint8_t *ref, `
`int ref_stride, `
`COrrespondence* correspondences, int* num_correspondences, uint8_t list_idx, uint8_t ref_idx)`
`{`
`//根据配置选择对应点收集方法`
`//检查 correspondence method配置,决定使用哪种方法收集对应点`
    `if (pcs->gm_ctrls.correspondence_method == CORNERS) `
    `{`
        `//方法A,角点检测方法`
        `//使用角点检测和匹配来收集对应点`
        `//这是更常用和更鲁棒的方法,不依赖运动估计的质量`
        `corresppondence_from_corners(`
        `&pcs->gm_ctrls, //全局运动控制参数,包含角点数量配置等`
        `frm_buffer, //当前帧图像缓冲区`
`        frm_height,             // 当前帧高度`
`            frm_stride,             // 当前帧行跨度`
`            frm_corners,            // 当前帧已检测的角点数组(输入)`
`            num_frm_corners,        // 当前帧角点数量(输入)`
`            ref,                    // 参考帧图像缓冲区`
`            ref_stride,             // 参考帧行跨度`
`            correspondences,        // 输出:匹配得到的对应点数组`
`            num_correspondences);   // 输出:匹配成功的对应点数量`
        
        `//角点方法的工作流程`
        `//1 在参考帧中检测角点,correspondence from corners 内部完成`
        `//2 匹配当前帧和参考帧的角点,通过NCC归一化互相关`
        `//精炼匹配结果,提高亚像素精度`
        `//4 输出高质量的对应点数组`
    `} else {`
    `//方法B MV方法`
    `//从运动估计结果中提取MV,转换为对应点`
    `//这种方法利用已有ME结果,计算速度快`
    `//断言检查,确保correspondence method 最有效的MV方法`
    `//MV方法包括,MV_64x64(0), MV_32x32(1), MV_16x16(2), MV_8x8(3)`
    `    orrespondence_from_mvs(`
`            pcs,                    // 图像父控制集(包含ME结果数据)`
`            correspondences,        // 输出:从MV转换得到的对应点数组`
`            num_correspondences,    // 输出:收集到的对应点数量`
`            list_idx,               // 参考帧列表索引(0=List0, 1=List1)`
`            ref_idx);               // 参考帧索引(在列表中的位置)`
    `}`
`//MV方法的工作流程`
`//1 遍历所有SB super block  64x64块`
`//2 从每个SB内部的子块,根据correspondence method选择块大小,提取MV`
`//3 将MV转换为对应点,当前帧位置 x,y 参考帧位置, rx = x + mv.x , ry = y + mv.y`
`//4输出对应点数组`    
`}`

`/*`
`通过角点检测和匹配来收集对应点,这是角点聚合MV模式的核心函数`

`角点检测方法 vs MV方法`
`角点方法,基于图像特征,角点进行匹配,不依赖运动结果`
`MV方法,基于运动估计的MV结果,依赖ME的质量`
`角点方法通常更准确,因为角点事图像中的稳定特征点。`

`完整流程,三步`
`第一步:角点检测,在调用本函数前已完成`
    `当前帧的角点已经通过svt_av1_fast_corner_detect() 检测完成`
    `角点存储在frm_corners 中,数量为num_frm_corners`
    `角点检测使用FAST算法,找到图像中的特征点,边缘,角落等`
`第二步:参考帧角点检测,本函数内部`
    `在参考帧中检测角点,找到对应的特征点`
    `使用相同的FAST角点检测算法`
`第三部:角点匹配,本函数内部`
    `将当前帧的角点与参考帧的角点进行匹配`
    `通过计算归一化互相关NCC找到最佳匹配`
`     - 只有匹配质量超过阈值的角点对才会被保留`
` * - 匹配结果会被进一步精炼以提高精度`
 `匹配过程详解 在svt_av1_determine_correspondence中`
` * 1. 对当前帧的每个角点:`
` *    - 在参考帧的所有角点中搜索最佳匹配`
` *    - 计算两个角点周围区域的归一化互相关(NCC)`
` *    - 只考虑距离合理的候选(避免匹配到太远的点)`
` *    - 选择NCC值最高的匹配`
` * 2. 匹配质量检查:`
` *    - 只有当 NCC > THRESHOLD_NCC * variance 时才保留匹配`
` *    - 这确保了匹配的可靠性`
`  * 3. 匹配精炼(improve_correspondence):`
` *    - 在匹配点周围的小窗口(SEARCH_SZ x SEARCH_SZ)内进行精细搜索`
` *    - 双向精炼:先精炼参考帧位置,再精炼当前帧位置`
` *    - 找到亚像素精度的最佳匹配位置`
` * 输出:`
` * - 对应点数组:每个对应点表示当前帧角点(x,y)和参考帧角点(rx,ry)的匹配`
` * - 这些对应点将被传递给RANSAC算法,聚合成全局运动模型`
` * `
` * 为什么角点方法更常用?`
` * - 角点是图像中的稳定特征,对光照变化、噪声等更鲁棒`
` * - 不依赖运动估计的质量,即使ME失败也能工作`
` * - 匹配精度高,能提供高质量的对应点`
` * - 适合处理复杂运动(旋转、缩放等)`
` * @param gm_ctrls 全局运动控制参数`
` * @param frm_buffer 当前帧图像缓冲区`
` * @param frm_width 当前帧宽度`
` * @param frm_height 当前帧高度`
` * @param frm_stride 当前帧行跨度`
` * @param frm_corners 输入:当前帧已检测的角点数组(格式:[x0,y0, x1,y1, ...])`
` * @param num_frm_corners 输入:当前帧角点数量`
` * @param ref 参考帧图像缓冲区`
` * @param ref_stride 参考帧行跨度`
` * @param correspondences 输出:匹配得到的对应点数组`
` * @param num_correspondences 输出:匹配成功的对应点数量`
`*/`
`static void correspondence_from_corners(GmControls* gm_ctrls, uint8_t* frm_buffer, int frm_width, int frm_height,`
`                                        int frm_stride, int* frm_corners, int num_frm_corners, uint8_t* ref,`
`                                        int ref_stride, Correspondence* correspondences, int* num_correspondences)`
`{`
`//第一步,在参考帧中检测角点,`
`/使用FAST 角点检测算法在参考帧中找到特征点`
`//角点存储格式:[x0, y0, x1, y1, x2, y2, ...],所以数组大小是 2 * MAX_CORNERS`
    `int ref_corners[2 * MAX_CORNERS]; //最大4096 个角点`
    `//在参考帧中检测角点,最多检测 MAX_CORNERS个`
    `//角点存储格式 [x0, y0, x1, y1, x2, y2, ...] 所以数组大小事2 * MAX_CORNERS`
    `//在参考帧中检测角点,最多检测MAX_CORNERS个`
    `//返回实际检测到的角点数量`
    `int num_ref_corners = svt_av1_fast_corner_detect(`
    `(unsigned char*)ref, frm_width, frm_height, ref_stride, ref_corners, MAX_CORNERS);`
    `//第二步,根据配置调整使用的角点数量`
    `//gm_ctrls->corners 控制使用多少比例的角点`
    `//1 使用1/4 的角点,`
    `//2 使用1/2的角点`
    `//使用3/4的角点`
    `//使用全部的角点,`
    `//这样可以平衡计算复杂度和匹配精度`
`    num_ref_corners = num_ref_corners * gm_ctrls->corners / 4;`
`    num_frm_corners = num_frm_corners * gm_ctrls->corners / 4;`
    `//第三步,匹配当前帧和参考帧的角点,生成对应点`
    `//这是核心步骤,通过归一化互相关NCC匹配角点`
    
    `//匹配过程 在svt_av1_determine_correspondence 中实现,`
    `//1 对当前帧的每个角点,在参考帧的所有角点中找到最佳匹配`
    `//2计算两个角点周围match_sz x match_sz 区域的归一化互相关`
    `//3保留NCC > THREASHOLD_NCC * variance 的高质量匹配`
    `//4 对匹配结果进行精炼,提高亚像素精度`
    `//输出:对应点数组,每个对应点表示`
    `//x,y 当前帧中的角点位置`
    `//rx, ry 参考帧中匹配的角点位置`
    `//这些对应点奖杯传递给RANSAC算法,聚合成全局运动模型参数`
    `*num_correspondences = svt_av1_determine_correspondence(frm_buffer, (int*)frm_corners`
    `,`  `num_frm_corners,`
    `ref, `
    `(int*)ref_corners,`
    `num_ref_corners,`
    `frm_width,`
    `frm_height,`
    `frm_stride,`
    `ref_stride,`
    `correspondences,`
    `gm_ctrls->match_sz);`
`}`

`/*`
`FAST-9` `角点检测,带非极大值抑制,全局运动估计中角点检测的核心函数`
`函数作用`
    `这是FAST` `Features` `from Accelerated` `Segment` `Test` `角点检测算法的完整实现,包含三个步骤,检测,评分,非极大值抑制,函数用于在全局运动估计中检测图像特征点。`
`FAST算法原理`
`FAST算法通过检查像素周围16个点的亮度差异来快速判断是否为角点,`
    `如果中心像素周围有连续9个,或者更多点的亮度明显高于或者低于中心的像素,则认为是角点9` `表示需要连续9个点满足条件。FAST-9` `变体。`
    
`算法流程:`
`步骤1:角点检测,svt_aom_fast9_detect`
    `遍历图像中的每个像素,边界除外`
    `检查像素周围16个采样点的亮度`
    `如果满足FAST9条件,标记为候选角点`
    `输出:所有候选角点的坐标数组`
`步骤2:角点评分svt_aom_fast9_score`
    `为每个候选角点计算一个分数`
    `分数表示该角点的强度或显著性`
    `分数越高,角点越明显,越稳定`
    `输出:每个角点对于的分数数组`
`步骤3:非极大值抑制` `svt_aom_nonmax_suppression`
    `在焦点密集区域,只保留分数最高的角点`
    `抑制周围分数较低的角点,避免重复检测`
    `输出,经过筛选的高质量角点数组`
    
`在全局运动估计中的作用`
    `1` `在当前帧和参考帧中匹配对应点`
    `2` `通过RANSAC算法拟合生成全局运动模型`
    `3实现从局部特征到全局运动的聚合`
`im 输入图像缓冲区,亮度分量,8位灰度图`
    `图像数据按行存储,每一行stride字节`
`xsize 图像宽度,像素数`
`ysize 图像高度,像素数`
`stride` `图像行跨度,字节数`
    `通常等于图像宽度,但是可能包含对齐填充`
    `用于计算像素在缓冲区中的位置im[y * stride + x]`
`b` `角点检测阈值,brightness` `threshold`
    `控制角点检测的敏感度`
    `值越大,检测到的角点越少,只检测非常明显的角点`
    `值越小,检测到的角点越多,包括较弱的角点`
    `典型值范围` `10-30`
    `ret_num_corners 输出参数,返回检测到的角点数量`
        `经过非极大值抑制后的最终角点数量`
    `xy*` `返回角点坐标数组的指针`
        `每个元素是一个xy结构体,包含角点(x,y)坐标`
        `数组大小为ret_num_corners` 
        `调用者需要负责释放内存,使用free`
`内存管理`
    `函数内部会分配内存存储角点数组`
    `调用者需要在使用完成后调用free 释放返回的指针`
    `函数内部会释放中间结果,corners和scores数组`
`*/`
`xy*` `svt_aom_fast9_detect_nonmax(const byte* im, `
`int xsiez, int ysize, int stride, int b, int *ret_num_corners)`
`{`
    `//变量声明`
    `//corners 存储第一步检测到的所有候选角点坐标`
    `//类型xy是结构体,包含x和y两个整数成员`
    `xy*` `corners;`
    `//num_corners` `候选角点的数量,检测过程中会被更新,`
    `//scores 存储每个候选角点的分数数组`
    `//分数表示角点的显著性` `强度,用于后续的非极大值抑制`
    `int *scores;`
    `//nonmax 存储经过非极大值抑制后的最终角点坐标`
    `//这是函数的返回值,包含高质量的,非重复的角点`
    
    `xy*` `nonmax;`
    `//步骤1,角点检测`
    `//调用FAST-9` `检测算法,在图像中找出所有候选角点。`
    `//参数说明`
    `//im 输入图像缓冲区`
    `//xsize,` `ysize 图像尺寸`
    `//stride` `行跨度`
    `//b 检测阈值`
    `//&num_corners` `输出参数,返回检测的角点数量`
    `//返回值,候选角点坐标数组,需要后续释放内存`
    `/检测原理`
    `//遍历图像中每个像素,边界3像素除外需要16个采样蒂娜`
    `//检查像素周围16个采样点的亮度`
    `//如果连续9个点都明显亮于,或者暗于中心像素,标记为角点。`
    `corners = svt_aom_fast9_detect(im, xsize, ysize, stride, b, &num_corners);`
    `//步骤2,角点评分,`
    `//为每一个候选点计算一个分数,表示角点的显著性`
    `//参数说明`
    `//im 输入图像,用于计算分数`
    `//` `stride` `行跨度`
    `//corners 候选角点数组,步骤1的输出`
    `//num_corners` `角点数量`
    `//b` `检查阈值` `用于评分计算`
    
    `//返回值,分数数组,每个角点对应一个分数`
    `//评分原理`
    `//通过二分搜索找到使该点仍然能被检测为角点的最大阈值`
    `//这个阈值就是该角点的分数,`
    `//分数越高,说明角点越明显,越稳定`
    `scores` `= svt_aom_fast9_score(im, stride, corners, num_corners, b);`
    `//步骤3,非极大值抑制`
    `//在角点密集区域,只保留分数最高的角点,抑制周围的低分角点`
    
    `//参数说明`
    `//corners` `候选角点数组`
    `//scores` `角点分数数组`
    `//num_corners` `角点数量`
    `//ret_num_corners 输出参数,返回抑制后的角点数量`
    
    `//返回值,经过筛选的最终角点数组,需要调用者释放内存`
    `//抑制原理`
    `//对于每个角点,检查其3x3邻域内的其他角点`
    `//如果领域内有分数更高的角点,则抑制当前角点`
    `//只保留局部最大值,非极大值抑制`
    `//这也可以避免在同一个特征区域监测到多个重要的角点`
    `nonmax = svt_aom_nonmax_suppresion(corners, scores, num_corners, ret_num_corners);`
    `//内存清理`
    `//释放中间结果的内存,只保留最终的非极大值抑制结果`
    
    `//释放候选角点数组,步骤1的输出,已被nonmax替代`
    `free(corners);`
    `//释放角点分数数组,(步骤2的输出,不再需要)`
    `free(scores);`
    `//返回值最终结果`
    `//返回经过非极大值抑制后的高质量角点数组`
    `//调用者需要在使用完后调用free(nonmax)释放内存`
    `return nonmax;`
`}`

`最小二乘法计算线性回归。通过找到的参考帧中的角点和编码帧中的角点,`
`计算映射关系。`
`x' = a1*x + a2*y + a3`
`y' = b1*x + b2*y + b3`







`
相关推荐
九狼13 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS13 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区14 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈14 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang15 小时前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx
shengjk116 小时前
NanoClaw 深度剖析:一个"AI 原生"架构的个人助手是如何运转的?
人工智能
西门老铁18 小时前
🦞OpenClaw 让 MacMini 脱销了,而我拿出了6年陈的安卓机
人工智能
恋猫de小郭19 小时前
AI 可以让 WIFI 实现监控室内人体位置和姿态,无需摄像头?
前端·人工智能·ai编程
是一碗螺丝粉19 小时前
5分钟上手LangChain.js:用DeepSeek给你的App加上AI能力
前端·人工智能·langchain