剪切和哈特利的整改

计算科学 计算机视觉
2021-12-25 13:46:25

在执行立体视差计算之前,我正在使用Richard Hartley 的校正算法来校正一对图像。问题是我正在观察其中一个校正图像中的剪切,它导致视差计算出现问题。

考虑这两个输入图像(点对是使用 SURF 生成的):

输入图像加上 SURF 特征

Hartley 的算法产生了这两个校正后的图像:

校正图像

极线看起来很好。下图显示了一些极线和一些点对:

校正极线

修正后的 SURF 关键点看起来也很好,考虑以下小样本进行检查,d是视差,erroy坐标之间的差异(完美映射为零):

(306.28, 139.00) <-> (284.15, 138.48): d = -22.13, erro = -0.52
(259.84, 150.72) <-> (234.34, 150.51): d = -25.50, erro = -0.21
(423.93, 151.01) <-> (425.24, 150.71): d = 1.30, erro = -0.30
(220.98, 151.05) <-> (190.53, 151.05): d = -30.45, erro = -0.00
(354.21, 157.88) <-> (346.19, 157.91): d = -8.02, erro = 0.04
(304.17, 161.58) <-> (289.66, 161.80): d = -14.51, erro = 0.22
(229.47, 162.44) <-> (203.86, 162.27): d = -25.61, erro = -0.17
(406.54, 262.40) <-> (442.38, 262.91): d = 35.84, erro = 0.50
(361.67, 290.02) <-> (399.54, 289.98): d = 37.87, erro = -0.04
(356.44, 293.49) <-> (394.51, 292.96): d = 38.07, erro = -0.53
(340.01, 339.44) <-> (318.47, 339.75): d = -21.54, erro = 0.31
(245.47, 360.89) <-> (204.93, 360.18): d = -40.55, erro = -0.71
...

现在,问题。下图显示了两个重叠的校正图像

图片说明

盒子上印索泰字就是一个很好的例子。这个词在同一个平面上,理想情况下,应该呈现出相似的差异。但与“C 像素”的差异相比,观察到的剪切将产生“Z 像素”的小差异。

我使用算法的两种不同实现来计算校正:OpenCV 实现,stereoRectifyUncalibrated以及我自己使用 Python 和 NumPy 从头开始​​编码的实现(在 Hartley 和 Zisserman 的书中的第 11.12 节之后)。两种实现都得到了相同的结果。哈特利算法有什么问题?立体算法可以处理这个问题吗?还是我犯了一些错误?

[这个问题是在OpenCV 问答中提出的。因为,显然,这不是 OpenCV 问题,而是算法问题,因此这里将其作为一般计算机视觉问题提出。]

1个回答

Loop & Zhang 在本文中提出了一个解决方案。他们使用剪切变换来减少投影变换引入的失真,该投影变换将极线映射到无穷大(即,使极线平行)。考虑剪切变换

     | k1 k2 0 |
S =  | 0   1 0 |.
     | 0   0 1 |

wh分别为图像的宽度和高度。考虑图像边缘的四个中点:

a = ((w-1)/2, 0, 1),
b = (w-1, (h-1)/2, 1),
c = ((w-1)/2, h-1, 1) and
d = (0, (h-1)/2, 1).

根据 Loop & Zhang 的说法:

(...) 我们试图保持 bd 和 ca 线的垂直度和纵横比

H为整流单应性,令a' = Ha为仿射平面上的一个点,通过除法使得a' 2 = 1(注意 a' 2第三个分量,即a' = (a'[0],一个' 1,一个' 2)。

x = b' - d',
y = c' - a'

根据 Loop & Zhang 的说法:

作为仿射点的差,xy是欧几里得图像平面中的向量。当 (Sx)^T(Sy) = 0 时保持垂直,如果 [(Sx)^T(Sx)]/[(Sy)^T(Sy)] = w²/h² 则保持纵横比。

真正的解决方案是一个封闭形式

k1 = (h²x[1]² + w²y[1]²)/(hw(x[1]y[0] - x[0]y[1])) and
k2 = (h²x[0]x[1] + w²y[0]y[1])/(hw(x[0]y[1] - x[1]y[0]))

up to sign (正数是首选)。

这是在左侧图像上应用剪切S后的结果:

在此处输入图像描述

现在左右图像重叠:

在此处输入图像描述

最后,OpenCV 立体方法StereoBM可以计算出合理的视差结果:

在此处输入图像描述