img = cv2.imread('C:/Users/Dell/PycharmProjects/check_KeyPoint/image/right_01.png')
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    sift = cv2.xfeatures2d.SIFT_create()  #创建一个sift对象
    kp = sift.detect(img_gray, None)    #检测关键点,返回的是关键点坐标
    img_kp = cv2.drawKeypoints(img_gray, kp, None) #将关键点画到图上
  kp, feature = sift.compute(img_gray, kp)    #计算相应关键点上的特征值,是一个128维的向量
  show(img_kp)

 

kp, feature = sift.detectAndCompute(img_gray, None) #可以用一条语句替换上面detect和compute两条语句

 

 

一对一匹配:

    img1 = cv2.imread('C:/Users/Dell/PycharmProjects/check_KeyPoint/image/right_01.png')
    img2 = cv2.imread('C:/Users/Dell/PycharmProjects/check_KeyPoint/image/left_01.png')
    img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
    sift = cv2.xfeatures2d.SIFT_create()  #创建一个sift对象
    kp1, feature1 = sift.detectAndCompute(img1_gray, None) #可以用一条语句替换上面detect和compute两条语句
    kp2, feature2 = sift.detectAndCompute(img2_gray, None)
    bf = cv2.BFMatcher(crossCheck = True) #crossCheck表示互相匹配,即图像A中第i个点到B中第j个点的距离最近,则B中第j个点到A中第i个点的距离也是最近

    #一对一匹配
    match = bf.match(feature1, feature2)
    match = sorted(match, key = lambda a : a.distance) #按距离从小到大排序
    img = cv2.drawMatches(img1, kp1, img2, kp2, match[ : 10], None, flags = 2) #先取前10个
    show(img)

opencv sift and RANSAC 图像拼接_拟合

 

 

 

#多对匹配    
    bf = cv2.BFMatcher()
    match = bf.knnMatch(feature1, feature2, k = 2) #每个关键点之间找出两个匹配
    good_match = []
    for m1, m2 in match:
        if m1.distance < m2.distance * 0.75: #如果最大匹配的距离小于次大匹配距离的0.75,则认为是一个好匹配,一般都是0.75
            good_match.append(m1)
    
    img = cv2.drawMatches(img1, kp1, img2, kp2, good_match, None, flags = 2)

    show(img)

opencv sift and RANSAC 图像拼接_特征值_02

 

 

 

RANSAC(随机抽样一致算法):

opencv sift and RANSAC 图像拼接_2d_03

 

最小二乘相当于拟合时对所有的点负责,

ransac拟合时只对主要密集点负责,对于部分偏离点不负责

 

 

使用ransac找出匹配中最好的四对(至少4对),求出图像A到图像B相应部分的变换矩阵

opencv sift and RANSAC 图像拼接_拟合_04

 

其中H为变换矩阵,有8个未知数,因此需要四对,(每对一个x一个y),列出8个方程

 

 

 

图像拼接:

步骤:

1、分别计算两个图像的关键点和特征值
2、找出好的特征值,并将其对应在两个图像中的坐标存近列表中

3、根据对应坐标计算变换矩阵 使用findHomograph

4、将其中一张图像进行变换(注意长度要为两个图像加起来,宽度其中之一即可)

5、将两张图像拼接在一起(即上一步中变换完的图像的相应部分设置为第二张图像,即第二张图像应该在左边,就将左边的相应位置设置为第二张图像,若在右边,同理)

import numpy as np
import cv2


def show(img):
    cv2.imshow('name', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()




if __name__ == '__main__':
    img1 = cv2.imread('C:/Users/Dell/PycharmProjects/check_KeyPoint/image/right_01.png')
    img2 = cv2.imread('C:/Users/Dell/PycharmProjects/check_KeyPoint/image/left_01.png')

    img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
    sift = cv2.xfeatures2d.SIFT_create()  #创建一个sift对象
    kp1, feature1 = sift.detectAndCompute(img1_gray, None) #可以用一条语句替换上面detect和compute两条语句
    kp2, feature2 = sift.detectAndCompute(img2_gray, None)

    kp1 = np.float32([k.pt for k in kp1])  # 需要做计算,所以转化为np.float32格式
    kp2 = np.float32([k.pt for k in kp2])
    # bf = cv2.BFMatcher(crossCheck = True) #crossCheck表示互相匹配,即图像A中第i个点到B中第j个点的距离最近,则B中第j个点到A中第i个点的距离也是最近
    #一对一匹配
    # match = bf.match(feature1, feature2)
    # match = sorted(match, key = lambda a : a.distance) #按距离从小到大排序
    # img = cv2.drawMatches(img1, kp1, img2, kp2, match[ : 10], None, flags = 2) #先取前10个
    #k对匹配
    bf = cv2.BFMatcher()
    match = bf.knnMatch(feature1, feature2, k = 2)
    good_match = []
    for m1, m2 in match:
        if m1.distance < m2.distance * 0.75: #如果最大匹配的距离小于次大匹配距离的0.75,则认为是一个好匹配,一般都是0.75
            good_match.append((m1.trainIdx, m1.queryIdx))  #将好匹配的在两个图像中的对应坐标取出

    if len(good_match) > 4 :
        points1 = np.float32([kp1[i] for (_, i) in good_match]) #将挑选后的匹配相应的坐标取出,注意顺序
        points2 = np.float32([kp2[i] for (i, _) in good_match])
        H = cv2.findHomography(points1, points2, cv2.RANSAC, 4.0)[0] #将ransac与求矩阵封装到一起,返回变换矩阵
        img_ret = cv2.warpPerspective(img1, H, (img1.shape[1] + img2.shape[1], img1.shape[0])) #图像变换
        img_ret[0 : img2.shape[0], 0 : img2.shape[1]] = img2    #图像拼接
        show(img_ret)

    else:
        print("Error!")

 

自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。