Как применить RANSAC к результатам сопоставления SURF, SIFT и ORB
Я работаю над обработкой изображений. Я хочу соответствовать 2D-функциям, и я сделал много тестов на SURF, SIFT, ORB.
Как я могу применить RANSAC на SURF/SIFT/ORB в OpenCV?
2 ответа
OpenCV имеет функцию cv::findHomography
который может использовать RANSAC, чтобы найти матрицу гомографии, относящуюся к двум изображениям. Вы можете увидеть пример этой функции в действии здесь.
В частности, интересующий вас раздел кода:
FlannBasedMatcher matcher;
std::vector< DMatch > matches;
matcher.match( descriptors_object, descriptors_scene, matches );
for( int i = 0; i < good_matches.size(); i++ )
{
//-- Get the keypoints from the good matches
obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
}
Mat H = findHomography( obj, scene, CV_RANSAC );
Затем вы можете использовать функцию cv::perspectiveTransform
деформировать изображения в соответствии с матрицей гомографии.
Другие варианты для cv::findHomography
Кроме как CV_RANSAC
являются 0
который использует каждую точку и CV_LMEDS
который использует метод наименьшей медианы. Более подробную информацию можно найти в документации по калибровке камеры OpenCV здесь.
Вот реализация Python для применения
ransac
с помощью
skimage
либо с
ProjectiveTransform
или же
AffineTransform
(т.е. гомография) модель на полученных ключевых точках SIFT / SURF. Эта реализация сначала выполняет тест соотношения Лоу на полученных ключевых точках, а затем выполняет поиск отфильтрованных ключевых точек из теста соотношения Лоу.
import cv2
from skimage.measure import ransac
from skimage.transform import ProjectiveTransform, AffineTransform
import numpy as np
def siftMatching(img1, img2):
# Input : image1 and image2 in opencv format
# Output : corresponding keypoints for source and target images
# Output Format : Numpy matrix of shape: [No. of Correspondences X 2]
surf = cv2.xfeatures2d.SURF_create(100)
# surf = cv2.xfeatures2d.SIFT_create()
kp1, des1 = surf.detectAndCompute(img1, None)
kp2, des2 = surf.detectAndCompute(img2, None)
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1,des2,k=2)
# Lowe's Ratio test
good = []
for m, n in matches:
if m.distance < 0.7*n.distance:
good.append(m)
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1, 2)
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1, 2)
# Ransac
model, inliers = ransac(
(src_pts, dst_pts),
AffineTransform, min_samples=4,
residual_threshold=8, max_trials=10000
)
n_inliers = np.sum(inliers)
inlier_keypoints_left = [cv2.KeyPoint(point[0], point[1], 1) for point in src_pts[inliers]]
inlier_keypoints_right = [cv2.KeyPoint(point[0], point[1], 1) for point in dst_pts[inliers]]
placeholder_matches = [cv2.DMatch(idx, idx, 1) for idx in range(n_inliers)]
image3 = cv2.drawMatches(img1, inlier_keypoints_left, img2, inlier_keypoints_right, placeholder_matches, None)
cv2.imshow('Matches', image3)
cv2.waitKey(0)
src_pts = np.float32([ inlier_keypoints_left[m.queryIdx].pt for m in placeholder_matches ]).reshape(-1, 2)
dst_pts = np.float32([ inlier_keypoints_right[m.trainIdx].pt for m in placeholder_matches ]).reshape(-1, 2)
return src_pts, dst_pts