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 误差应该是朝着正确方向迈出的一步。