Ransac算法

举报
AIBooster 发表于 2021/01/16 12:15:57 2021/01/16
【摘要】 1. Ransac算法RANSAC(随机抽样一致)算法:一种经典的数据过滤和参数拟合算法。它假设数据(内点,Inliers)分布符合一定的数学模型,通过迭代计算,去除外点 (Outliers) 和噪声点, 同时获取概率上最佳的模型参数。在全局定位中,内点指正确的匹配,外点指错误的匹配,参数模型指匹配点对的空间变换矩阵。RANSAC所期望找到的匹配子集需要满足两个指标:内点重投影误差尽可能小;...

1. Ransac算法

RANSAC(随机抽样一致)算法:一种经典的数据过滤和参数拟合算法。它假设数据(内点,Inliers)分布符合一定的数学模型,通过迭代计算,去除外点 (Outliers) 和噪声点, 同时获取概率上最佳的模型参数。在全局定位中,内点指正确的匹配,外点指错误的匹配,参数模型指匹配点对的空间变换矩阵。RANSAC所期望找到的匹配子集需要满足两个指标:内点重投影误差尽可能小;内点数量尽可能多。基本流程如下:

  • 采样初始子集
  • 计算变换矩阵
  • 根据变换矩阵计算匹配点的重投影误差
  • 去除误差较大的点
  • 循环1-5,保留最满足指标的匹配方案

 原始特征匹配:  

经过RANSAC算法优化后的匹配:  

其中,初始候选匹配是根据描述子之间的距离产生的,但重投影误差则只和关键点的空间位置有关, 与描述子本身无关。

RANSAC算法受到原始匹配误差和参数选择的影响,只能保证算法有足够高的概率合理,不一定得到最优的结果。算法参数主要包括阈值和迭代次数。RANSAC得到可信模型的概率与迭代次数成正比,所得到的匹配数量和阈值成反比。因此实际使用时需要反复尝试不同的参数设置才能得到较好结果。依据经典RANSAC算法,学术界提出了全局RANSAC(Universal- RANSAC)流程,形成普适性RANSAC架构,将预滤波、最小子集采样、由最小子集生成可靠模型、参数校验、模型精化等模块包括了进来。

2. SIFT特征点匹配和错误剔除

SIFT算法可以得到图像中的特征点以及对应的特征描述,图像间中的特征点匹配一般可采用K近邻(KNN)算法。K近邻算法求取在空间中距离最近的K个数据点,并将这些数据点归为一类。在进行特征点匹配时,一般使用KNN算法找到最近邻的两个数据点,如果最接近和次接近的比值大于设定阈值,则保留这个最接近的值,认为它和其匹配的点为good match

通过SIFT特征提取步骤可以得到两张图中的匹配点,不同视角的图像上的点具有如下关系:

其中[x1 y1 1][x2 y2 1]分别表示对应像素的齐次坐标。单应性矩阵为:

H矩阵有八个参数,求解需要八个方程,由于每一个对应的像素点可以产生2个方程(xy),则总共需要四个像素点来求解单应性矩阵。Ransac算法在opencv中调用方式:

H, mask = cv2.findHomography(ptsA,ptsB,cv2.RANSAC,ransacReprojThreshold)

 得到众多匹配点后,使用RANSAC算法每次从中筛选四个随机的点,然后求得H矩阵,依据RANSAC步骤不断迭代,直到求得最优的H矩阵。其中,最大投影误差的计算公式:

示例代码:

import numpy as np
import cv2
from matplotlib import pyplot as plt

def good_match(des1, des2):
    bf = cv2.BFMatcher()
    matches = bf.knnMatch(des1, des2, k=2)
    good = []
    for m, n in matches:
        if m.distance < 0.75 * n.distance:
            good.append(m)
    return good

def sift_kp(image):
    gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    sift = cv2.xfeatures2d_SIFT.create()
    kp,des = sift.detectAndCompute(image,None)
    kp_image = cv2.drawKeypoints(gray_image,kp,None)
    return kp_image,kp,des

def siftImageAlignment(img1,img2):
   _, kp1, des1 = sift_kp(img1)
   _, kp2, des2 = sift_kp(img2)
   goodMatch = good_match(des1, des2)
   if len(goodMatch) > 4:
       ptsA= np.float32([kp1[m.queryIdx].pt for m in goodMatch]).reshape(-1, 1, 2)
       ptsB = np.float32([kp2[m.trainIdx].pt for m in goodMatch]).reshape(-1, 1, 2)
       ransacReprojThreshold = 4
       H, mask =cv2.findHomography(ptsA,ptsB,cv2.RANSAC,ransacReprojThreshold)
       matchesMask = mask.ravel().tolist()
       img_out = cv2.warpPerspective(img2, H, (img1.shape[1], img1.shape[0]), flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)
       draw_params = dict(matchColor=(0, 255, 0),  # draw matches in green color
                          singlePointColor=None,
                          matchesMask=matchesMask,  # draw only inliers
                          flags=2)
       img3 = cv2.drawMatches(img1, kp1, img2, kp2, goodMatch, None, **draw_params)
       plt.imshow(img3, 'gray'), plt.show()
   return img_out, H, mask


if __name__ == "__main__":
    img1 = cv2.imread('D:/test/1.jpg')
    img2 = cv2.imread('D:/test/2.jpg')

    result, _, _ = siftImageAlignment(img1, img2)
    cv2.namedWindow('Result', cv2.WINDOW_NORMAL)
    cv2.imshow('Result', result)
    cv2.waitKey(0)
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。