2

skimage.measure.ransac在估计一对图像的基本矩阵时,我无法实现稳健的性能。与 OpenCV 的findFundamentalMatrix.

我在同一组关键点上运行 skimage 和 opencv 的 ransac,并使用(我假设是)等效参数。我使用与OpenCV python tutorials相同的图像对。

这是我的演示脚本:

import cv2
import numpy as np

from skimage import io
from skimage.measure import ransac
from skimage.feature import ORB, match_descriptors
from skimage.transform import FundamentalMatrixTransform

orb = ORB(n_keypoints=500)

img1 = io.imread('images/right.jpg', as_grey=True)
orb.detect_and_extract(img1)
kp1 = orb.keypoints
desc1 = orb.descriptors

img2 = io.imread('images/left.jpg', as_grey=True)
orb.detect_and_extract(img2)
kp2 = orb.keypoints
desc2 = orb.descriptors

matches = match_descriptors(desc1, desc2, metric='hamming', cross_check=True)
kp1 = kp1[matches[:, 0]]
kp2 = kp2[matches[:, 1]]

n_iter = 10
skimage_inliers = np.empty((n_iter, len(matches)))
opencv_inliers = skimage_inliers.copy()

for i in range(n_iter):
    fmat, inliers = ransac((kp1, kp2), FundamentalMatrixTransform,
                           min_samples=8, residual_threshold=3,
                           max_trials=5000, stop_probability=0.99,
                           random_state=i)
    skimage_inliers[i, :] = inliers

    cv2.setRNGSeed(i)
    fmat, inliers = cv2.findFundamentalMat(kp1, kp2, method=cv2.FM_RANSAC,
                                           param1=3, param2=0.99)
    opencv_inliers[i, :] = (inliers.ravel() == 1)

skimage_sum_of_vars = np.sum(np.var(skimage_inliers, axis=0))
opencv_sum_of_vars = np.sum(np.var(opencv_inliers, axis=0))

print(f'Scikit-Image sum of inlier variances: {skimage_sum_of_vars:>8.3f}')
print(f'OpenCV sum of inlier variances:       {opencv_sum_of_vars:>8.3f}')

和输出:

Scikit-Image sum of inlier variances:   13.240
OpenCV sum of inlier variances:          0.000

我使用从不同随机种子中获得的内点的方差之和作为鲁棒性的度量。

我希望这个数字非常接近于零,因为真正强大的 ransac 应该收敛到相同的模型,而与它的随机初始化无关。

我怎样才能使 skimage 的ransac行为像 opencv 一样健壮?


我的代码主要基于:


后期编辑:我最后也在 skimage 邮件列表上问了这个问题,结果发现不一致可能是由每个库中计算模型错误的不同方式引起的。

这没有回答我原来的问题,所以我没有将其标记为已解决,但是我发现它足够令人满意,我停止了进一步的追求。

对于任何感兴趣的人,邮件列表中的 Johannes 建议重新实现残差计算FundamentalMatrixTransform以使用点到极线距离而不是 Sampson 误差应该是朝着正确方向迈出的一步。

4

0 回答 0