【MVG_in_CV】从图像恢复度量性质

本文探讨了在图像处理中,如何利用虚圆点和对偶二次曲线的射影变换来恢复图像的度量性质。重点讲解了在射影变换下平面上夹角的计算方法,以及如何从仿射变换和射影变换中进行度量矫正,以恢复图像的真实比例。

1,先验知识

1.1,虚圆点

在相似变换HS下,无穷远线l是不变量,而I上的理想点(x1,x2,0)T,经过HS变换后,虽然仍在l上,但是却发生了移动。
在这里插入图片描述【图】相似变换矩阵HS
但是,有两个称之为虚圆点的理想点I=(1,i,0)T、J=(1,-i,0)T,在相似变换HS下是不变量,即
I '= HS I = I
J = HS J = J

事实上,可以证明有如下结论:
在射影变换H下:虚圆点I和I为不动点 <=> H为相似变换

1.2对偶二次曲线的射影变换

1.2.1,形式:

在点变换x = Hx下,对偶二次曲线C的变换为C* = HC*HT

1.2.2,不变性

在某种变换下,二次曲线的系数矩阵如果或不变(相差一个常数),则称该二次曲线在次变换下不变

1.3,虚圆点的对偶二次曲线

1.3.1,退化的对偶二次曲线

秩2的退化的线二次曲线包含两个点x,y,其系数矩阵有如下形式:
在这里插入图片描述
二次曲线的系数矩阵是3×3的齐次对称矩阵,有5个自由度,而退化的二次曲线,系数矩阵不满秩,因此其行列式为0,进而又去掉一个自由度,一共4个自由度

1.3.2,虚圆点的对偶二次曲线形式

如前所述,虚圆点的对偶二次曲线的系数矩阵有如下形式:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

1.3.3,虚圆点的对偶二次曲线性质

在任何设射影变换下,C*有如下性质:
在这里插入图片描述

1.3.4,一个重要结论

在射影变换H下:虚圆点的对偶二次曲线C*是不变量 <=> H是相似变换
即:
C* = HC*HT = C* <=> H是相似变换

1.4,射影变换下平面上的夹角

1.4.1,欧氏变换下平面上的夹角

欧氏变换及相似变换下,平面上两直线 l=(l1,l2,l3),m=(m1,m2,m3)的夹角θ,可以由两者的法线计算,直线 l 和 m 的 法线分别与(l1,l2)和(m1,m2)平行,于是有:
在这里插入图片描述式(1.4.1_1)
但是在仿射和射影变换中,两直线的夹角不是不变量。因此仍使用上述公式的话,计算得到的夹角θ与真实场景中的不同。

1.4.2,射影变换下平面上的夹角

但是我们发现,借助虚圆点的对偶二次曲线系数矩阵C*可以定义一个统一的夹角计算公式:
在这里插入图片描述式(1.4.2_2)
由于C*对相似变换是不变量(自然对欧氏变换也是),C*在相似和欧氏变换下的形式为:
在这里插入图片描述
从而在相似和欧氏变换中,式(1.4.2_2)与式(1.4.1_1)完全相同。
可以证明式,式(1.4.2_2)在 射影变换 下是不变量,即通过式式(1.4.2_2)可以在射影变换下求解变换后的直线 l 和 m 所对应的真实场景下的两条直线的夹角θ,注意此时式中的C*,是经过射影变换后的C* = HC*HT

2,度量矫正

2.1,度量矫正的问题描述

已知:一个射影变换H可以分解为相似变换Hs,仿射变换HA,射影变换HP的组合的形式。

在这里插入图片描述
H产生的作用是这样的:
在这里插入图片描述
注:
π1中的C*为,虚圆点的对偶二次曲线
π2中的C* 为,π1中的C*经过相似变换HS后的像,由前述可知,相似变换不改变C*,即C*=HSC*HST
π3中的C*∞3 为,π2中的C*经过仿射变换HA后的像,即C*∞3=HAC*HAT
π4中的C*∞4 为,π3中的C*∞3经过射影变换Hp后的像,即C*∞4=HPC*∞3HPT
以后将要出现的情况,以此类推,不再赘述。

所谓度量矫正,就是找到某个变换将H射影变换后的射影图片π4矫正为π1经过某个相似变换HS_1后的图片π2_1(与图中的π2不一定相同)。这个HS_1是什么我们并不关心,因为我们只是想得到图像π2_1

在这里插入图片描述

2.2,从仿射变换中进行度量矫正

2.2.1,问题描述

先来看一种简单的情况,假设我们已经通过某个变换将π4矫正为了π1经过某个仿射变换后的图片π3_1。
在这里插入图片描述
上面从π0到π3_1的过程与我们的想做的事无关,并且射影变换是可以合并的,为了方便表示不妨简化为:

在这里插入图片描述
注:此时H是一个由相似和仿射组成的仿射变换
H=HAHS
在这里插入图片描述

那么我们的度量矫正工作就变成了:找到某个变换H将仿射变换后的射影图片π3_1矫正为π1经过某个相似变换HS_1后的图片π2_1(与图中的π2不一定相同)。同样,这个HS_1是什么我们并不关心。
即:
在这里插入图片描述

2.2.2,矫正方法

在前面的叙述中,我们已经知道的知识有:
在这里插入图片描述
在这里插入图片描述
C*∞3=HAC*HAT
于是,可以得到
在这里插入图片描述
如果我们能够找到π3_1中的两条直线 l=(l1,l2,l3),m=(m1,m2,m3),它们分别是π1(或者π2)中的两条互相垂直的直线 l 和 m 的像,那么由式(1.4.2_2)(重写在下面)
在这里插入图片描述式(1.4.2_2)
可以得到:
l’TC*∞3m = 0
在这里插入图片描述
其中KKT是2×2的对称矩阵,有三个独立元素,由于全局尺度因子无关紧要,因此只有2个自由度。
由上面的讨论可以看到,一组l,m可以提供一个约束,因此,找到两组,就可以求解处KKT,即得到C*∞3
对KKT进行Cholesky分解,可以就求解出K,即得到HA
此时,有两种方法求解出H
1,H=HA-1
2,对C*∞3进行SVD分解:
在这里插入图片描述
其中的U,即是HA,因此有H=HA-1

2.3,从射影变换中进行度量矫正

回到我们在2.1中对度量矫正的描述,即就是找到某个变换将H射影变换后的射影图片π4矫正为π1经过某个相似变换HS_1后的图片π2_1(与图中的π2不一定相同)。这个HS_1是什么我们并不关心,因为我们只是想得到图像π2_1

在这里插入图片描述
求解H的过程和2.2中几乎完全相同。
不同之处在于:
这里的H是射影变换:
在这里插入图片描述
因此,
C*∞4=HPHAC*(HAHPT
= HPHAC*HATHPT
在这里插入图片描述
由于C*∞4为对偶二次曲线的系数矩阵,所以其为3×3的齐次对称矩阵,,有5个自由度。

和2.2中一样,如果我们能够找到π3_1中的两条直线 l=(l1,l2,l3),m=(m1,m2,m3),它们分别是π1(或者π2)中的两条互相垂直的直线 l 和 m 的像,那么由式(1.4.2_2)可以得到:
l’TC*∞4m = 0
每对直线l和m可以提供一个约束,从而找到5组这样的直线对就可以求解出C*∞4
同样,对C*∞4进行SVD分解:
在这里插入图片描述
其中的U,即是HPHA,因此有H= U-1

3, 总结

进行度量矫正,首先要在变换后的图像中找到n组直线对<l=(l1,l2,l3)T,m=(m1,m2,m3)T>,然后求解一个m×m齐次对称矩阵C*,在对该矩阵进行SVD分解:
在这里插入图片描述
得到的U的逆就是需要的矫正变换矩阵
矫正仿射图片时,n=2,m=2
矫正射影图片时,n=5,m=3

<think>首先,用户的问题是关于C/C++预处理指令的:"我想判断 '#if MVG_EIS' 是否与宏定义相关 请问在C/C++预处理中,#if MVG_EIS 是否用于判断宏定义" 这是一个具体的编程问题。用户想知道在C/C++中,#if MVG_EIS 是否用于检查宏定义。 回想一下C/C++预处理器的知识: - #if 指令用于条件编译,它检查一个表达式是否为真。 - 表达式可以是宏定义的值。例如,#ifdef MACRO 检查宏是否定义,#if defined(MACRO) 也类似。 - 但 #if MVG_EIS 直接使用标识符 MVG_EIS。如果 MVG_EIS 是一个宏定义,它会扩展为其值;否则,它可能被解释为0。 在C/C++标准中: - 如果 MVG_EIS 没有被定义,那么 #if MVG_EIS 会尝试将其解释为一个整数常量。由于它不是定义,预处理器会将其视为0。 - 所以,#if MVG_EIS 只有在 MVG_EIS 被定义为一个非零值时,条件才为真。 用户的问题是:"#if MVG_EIS 是否用于判断宏定义",意思是它是否用于检查宏定义的存在。 实际上,#if MVG_EIS 主要用于检查宏的值,而不是其存在。如果宏未定义,它默认为0。 相比之下: - #ifdef MVG_EIS 或 #if defined(MVG_EIS) 直接检查宏是否定义。 - #if MVG_EIS 检查宏的值是否为真(非零)。 所以,回答是:是的,它用于判断宏定义,但具体是检查其值而非仅存在。 用户引用了几个文本片段,但它们似乎不直接相关: - 引用[1] 是关于硬件配置的C代码。 - 引用[2] 是关于OpenMVG库。 - 引用[3] 是关于MTK平台的eMMC和DDR频率。 - 引用[4] 是关于固件刷机。 这些引用可能来自用户之前的上下文,但与当前问题无关。我应该专注于问题本身。 系统指令: - 所有行内数学表达式用 $...$,但这个问题没有数学内容。 - 独立公式用 $$...$$,但不需要。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾添加引用标识。但用户提供的引用可能不相关,所以我应该基于知识回答,不强制引用。 用户可见层:回答结构清晰,逐步解决问题,保证真实可靠。 我的回答结构: 1. 直接回答用户的问题。 2. 解释 #if MVG_EIS 的工作原理。 3. 对比 #ifdef 和 #if。 4. 提供例子。 5. 生成相关问题。 最终输出:用中文。</think>### 回答:C/C++预处理中 `#if MVG_EIS` 是否用于判断宏定义 在C/C++预处理中,`#if MVG_EIS` 确实**用于判断宏定义**,但它不是直接检查宏是否被定义,而是**检查宏的值是否为真(非零)**。以下是详细解释: 1. **`#if` 指令的基本作用**: - `#if` 是预处理指令,用于条件编译。它会对表达式求值,如果结果为真(非零),则编译后续代码块;否则跳过。 - 表达式 `MVG_EIS` 会被视为宏名:如果 `MVG_EIS` 已定义,预处理器会将其替换为定义的值(例如 `#define MVG_EIS 1`),然后计算该值。 - 如果 `MVG_EIS` 未定义,预处理器会将其视为 `0`(根据C/C++标准),因此 `#if MVG_EIS` 会等价于 `#if 0`,条件为假[^1]。 2. **与 `#ifdef` 的区别**: - `#ifdef MVG_EIS` 或 `#if defined(MVG_EIS)` 专门用于**检查宏是否被定义**,不关心宏的值(即使定义为0,条件也为真)。 - `#if MVG_EIS` 则**依赖于宏的值**:只有当 `MVG_EIS` 被定义且值非零时,条件才为真。 - 示例: ```c #define MVG_EIS 1 // 宏定义为非零 #if MVG_EIS // 此代码块会被编译,因为 MVG_EIS 的值是1(真) #endif // 如果未定义 MVG_EIS 或定义为0: #if MVG_EIS // 此代码块不会被编译 #endif ``` 3. **实际应用场景**: - `#if MVG_EIS` 常用于基于配置开关的代码分支,例如在硬件抽象层或跨平台开发中,根据宏的值启用特定功能(如引用[1]中的硬件电压调整逻辑)。 - 在您提供的引用[1]中,`#ifdef LVcore_HVmem` 使用了 `#ifdef` 来检查宏定义,而 `#if MVG_EIS` 的行为类似,但更侧重于值判断。 **总结**:`#if MVG_EIS` 用于判断宏定义,但它检查的是宏的值(非零为真),而不是单纯的存在性。如果宏未定义,默认视为0。建议在需要严格检查宏定义时使用 `#ifdef`,而在需要基于值控制逻辑时使用 `#if`。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值