sift特征检测与匹配

一 实验背景

1.sift算法介绍

1.1sift算法特点

1.sift特征是图像的局部特征,其对旋转、尺度缩放、亮度变化保持不变性,对视角变化、仿射变换、噪声也保持一定程度的稳定性。
2.独特性好,信息量丰富,适用于在海量特征库进行快速、准确的匹配。
3.多量性,即使是很少几个物体也可以产生大量的SIFT特征
4.高速性,经优化的SIFT匹配算法甚至可以达到实时性
5.扩招性,可以很方便的与其他的特征向量进行联合。

1.2sift算法可以解决的问题

目标的旋转、缩放、平移;图像仿射投影变换 ;弱光照影响;部分目标遮挡;杂物场景;噪声

1.3 sift算法实现具体步骤

算法实质:在不同尺度空间上查找特征点(关键点)
主要工序:
(1)提取关键点
(2)对关键点附加详细的信息(局部特征)也就是所谓的描述器
(3)通过两方特征点(附带上特征向量的关键点)的两两比较找出相互匹配的若干对特征点,也就建立了景物间的对应关系。
在这里插入图片描述

2.关键点相关概念

2.1关键点(特征点)

所谓关键点,就是在不同尺度空间的图像下检测出的具有方向信息的局部极值点。
sift中要查找的关键点是十分突出的点,不会因光照、尺度、旋转等因素的改变而消失。两幅图像中有相同的景物,那么使用某种方法分别提取各自的稳定点,这些点之间会有相互对应的匹配点。

2.2尺度空间

尺度空间理论最早于1962年提出,其主要思想是通过对原始图像进行尺度变换,获得图像多尺度下的空间表示。 从而实现边缘、角点检测和不同分辨率上的特征提取,以满足特征点的尺度不变性。在一定范围内,人眼可以分辨出物体的大小,但计算机并未具有相同的能力,因此在未知场景中,计算机视觉不能够提供物体的尺度大小,所以采用的方法是:将物体不同尺度下的图像都提供给计算机这样计算机就能够对一个物体的不同尺度有一个统一认识,也就是说,要考虑图像在不同尺度下都存在的特点。尺度空间中各尺度图像的模糊程度逐渐变大,能够模拟人在距离目标由近到远时目标在视网膜上的形成过程。并且尺度越大图像越模糊。

3.高斯模糊

3.1高斯函数

在这里插入图片描述

3.2高斯模糊

高斯模糊是在Adobe Photoshop等图像处理软件中广泛使用的处理 效果,通常用它来减小图像噪声以及降低细节层次。这种模糊技术生成 的图像的视觉效果是好像经过一个半透明的屏幕观察图像。
在这里插入图片描述
高斯模板大小的选择:
在这里插入图片描述
通常,图像处理程序只需要计算(6σ+1)(6σ-1)

4.高斯金字塔

高斯金字塔的构建过程可构成两步:
(1)对图像做高斯平滑
(2)对图像做降采样
在这里插入图片描述
高斯图像金字塔共o组,s层,则有:
在这里插入图片描述
最后可将组内和组间尺度归为:
在这里插入图片描述

5.关键点检测-DOG

5.1LOG

LOG算子即由高斯函数梯度算子GoG构建
在这里插入图片描述
LOG算子与高斯核函数的关系:
在这里插入图片描述
通过推导可以看出,LOG算子与高斯核函数的差有直接关系,由此引入一种新的算子DOG,即高斯差分算子。

5.2DOG

原理:
在这里插入图片描述
DOG在计算上只需相邻尺度高斯平滑后图像相减。
对应DOG算子,我们要构建DOG金字塔:

在这里插入图片描述
通过高斯差分图像可以看出图像上的像素值变化情况。(如果没有变化,也就没有特征。特征必须是变化尽可能多的点。)DOG图像描绘的是目标的轮廓。

基本步骤:
(1)将原始图像做高斯卷积
(2)将处理后的图像做高斯差分,此时可输出金字塔类型图
(3)找候选极值点
(4)通过构造Hessian矩阵去除边缘响应

局部极值检测:
关键点是由DOG空间的局部极值点组成的。为了寻找DOG函数的极值点,每一个像素点要和它的所有相邻点比较,看其是否比它的图像域和尺度域的相邻点大或者小。
在这里插入图片描述
中间的检测点和它同尺度的8个相邻点和上下相邻尺度对应的9*2个点共26个点比较,以确保在尺度空间和二维图像空间都检测到极值点。
从上面的描述中可以知道,每组图像的首末两层是无法进行比较取得极值的。为了满足尺度变换的连续性,在每一组图像的顶层继续使用高斯模糊生成3幅图像,高斯金字塔每组有S+3层图像,DoG金字塔的每组有S+2组图像。这样产生的极值点并不全都是稳定的特征点,因为某些极值点响应较弱,而且DOG算子会产生较强的边缘响应。

去除边缘响应:
DOG函数的峰值点在横跨边缘的方向上有较大的主曲率,而在垂直边缘的方向有较小的主曲率。主曲率可以通过计算在该点位置尺度的2*2的Hessian矩阵得到,导数由采样点相邻差来估计:
在这里插入图片描述
D的主曲率和H的特征值成正比。令 α ,β为特征值,则
在这里插入图片描述在两特征值相等时值达到最小,随r的增长而增长。Lowe论文中建议r取10。
在这里插入图片描述
这时将关键点保留,反之剔除。

6.关键点方向分配

我们通过求每个极值点的梯度来为极值点赋予方向。
像素点的梯度表示:
在这里插入图片描述
确定关键点的方向采用梯度直方图统计法,统计以关键点为原点,一定区域内的图像像素点对关键点方向生成所做的贡献。

方向分配实现步骤:
(1)确定计算关键点直方图的高斯函数权重函数参数。
(2)生成含有36柱的方向直方图,梯度直方图范围0-360°,其中每10°一个柱。由半径为图像区域生成。
(3)对方向直方图进行两次平滑。
(4)求取关键点方向。
(5)对方向直方图的Taylor展开式进行二次曲线拟合,精确关键点方向。

7.关键点描述

描述的思路是通过对关键点周围图像区域分块,计算块内梯度直方图,生成具有独特性的向量,这个向量是该区域图像信息的一种抽象,具有唯一性。
以旋转之后的主方向为中心取8x8的窗口,左图中点为当前关键点的位置,每一个小格都代表了特征点邻域所在的尺度空间的一个像素,箭头方向代表了像素梯度方向,箭头长度代表该像素的幅值。然后在每个4x4的小块上绘制8个方向的梯度直方图,计算每个梯度方向的累加值,即可形成一个种子点,如右图所示,每个特征的由4个种子点组成,每个种子点有8个方向的向量信息,这种邻域方向性信息联合增强了算法的抗噪能力,同时对于含有定位误差的特征匹配也提供了比较理性的容错性。
在这里插入图片描述
在这里插入图片描述
旋转后的新坐标:在这里插入图片描述
Lowe实验结果表明:描述子采用4×4×8=128维向量表征综合效果最优(不变性与独特性)

8.关键点匹配

分别对模板图和实时图建立关键点描述子集合。目标的识别是通过两点集内关键点描述子的比对来完成。具有128维的关键点描述子的相似性度量采用欧式距离。
在这里插入图片描述
穷举匹配:
在这里插入图片描述
关键点的匹配可以采用穷举法来完成,但耗费时间太多,一般都采用一种叫kd数的数据结构来完成搜索。搜索的内容是以目标图像的关键点为基准,搜索与目标图像的特征点最邻近的原图像特征点和次邻近的原图像特征点。
kd树是一个平衡二叉树:
在这里插入图片描述

9.消除错配点(RANSAC)

RANSAC的全称是“RANdom SAmple Consensus(随机抽样一致)”。它可以从一组包含“局外点”的观测数据集中,通过迭代方式估计数学模型的参数。它是一种不确定的算法,也就是说它有一定的概率得出一个合理的结果,所以为了提高概率必须提高迭代次数。RANSAC是一种鲁棒性的参数估计方法。实质上就是一个反复测试不断迭代的过程。

(1)基本思想

首先根据具体问题设计出某个目标函数,然后通过反复提取最小点集估计该函数中参数的初始值,利用这些初始值把所有的数据分为“内点”和“外点”,最后用所有的内点重新计算和估计函数的参数。

(2)基本步骤

① 随机选择四对匹配特征
② 根据DLT计算单应矩阵 H (唯一解)
③ 对所有匹配点,计算映射误差ε= ||pi’, H pi||
④ 根据误差阈值,确定inliers(例如3-5像素)
⑤ 针对最大inliers集合,重新计算单应矩阵 H

(3)RANSAC示例:直线拟合

① 给定若干二维空间中的点,求直线 y=ax+b ,使得该直线对空间点的拟合误差最小
在这里插入图片描述
② 随机选择两个点,根据该点构造直线。给定阈值,计算inliers数量
在这里插入图片描述
③ 重复②步骤
在这里插入图片描述
在这里插入图片描述
④ 循环迭代,其中inliers最大的点集即为最大一致集,最后将该最大一致集里面的点利用最小二乘拟合出一条直线。

(4)参数

用w表示每次从数据集中选取一个局内点的概率,如下式所示:
w = 局内点的数目 / 数据集的数目
通常情况下,我们事先并不知道w的值,但是可以给出一些鲁棒的值。假设估计模型需要选定n个点,w的n次方是所有n个点均为局内点的概率;1-w^n是n个点中至少有一个点为局外点的概率,此时表明我们从数据集中估计出了一个不好的模型。
(1-wn)k表示算法永远都不会选择到n个点均为局内点的概率,它和1-p相同。因此,
1-p = (1 - wn)k
我们对上式的两边取对数,得出
在这里插入图片描述
如果希望成功率提高,p = 0.99,当n不变时,k越大,p越大;当 w 不变时,n越大,所需的k就越大,通常,w位置,所以选小一点比较好。
为了得到更可信的参数,标准偏差或它的乘积可以被加到k上。k的标准偏差定义为:
在这里插入图片描述

二 实验内容

1. 构造数据集

针对自己所处环境,拍摄多张照片(来自不同场景),构造出一个小数据集
如下图所示:
在这里插入图片描述

2. 提取每张图片的sift特征并展示特征点

实验代码:
在这里插入图片描述
结果如下:
图1
在这里插入图片描述
图2
在这里插入图片描述
图3
[在这里插入图片描述
图4
在这里插入图片描述
图5
![在这里插入图片描述
图6
在这里插入图片描述
图7
在这里插入图片描述
图8
在这里插入图片描述
图9
在这里插入图片描述
图10
在这里插入图片描述
图11
在这里插入图片描述
图12
!在这里插入图片描述
图13
在这里插入图片描述
图14
在这里插入图片描述
图15
在这里插入图片描述
小结:
提取出的关键点主要分布在一些比较突出的点。如:
角点:结果显示测出的sift特征点与测出的角点有很大一部分是重合的。
暗区域的亮点或暗区域的亮点:图13,14,15是在晚上拍的,大部分区域属于暗区域,而测出的特征点几乎都是分布在有灯的地方,即亮区域。
还可以看出边缘点也是容易提取出关键点的位置。
并且特征提取的速度与图片的大小有关,图片越小,结果越快。图片越大,结果越慢,甚至有些无法检测出。
对于同一场景,白天的照片和晚上的照片检测出的特征点相差较大,说明光照对于sift特征是有一定影响的。

3. 计算给定两张图片的sift特征匹配结果

实验代码:
在这里插入图片描述
结果如下:
图1与图2:
在这里插入图片描述
图3与图4:
在这里插入图片描述
图9和图10:
在这里插入图片描述
图1和图3:
在这里插入图片描述
小结:
同一场景下的两张图片匹配结果较高:如图1和图2,图3和图4。但当图片比较复杂时,也可能存在匹配度为0的情况:如图9和图10。不同场景下的两张图片匹配度很低,如图1和图3。
同一场景下的不同照片(角度,尺度大小不同)能够匹配成功,说明sift特征具有角度和旋转不变性,尺度不变性。

4.在数据集内部检索匹配前三的图片

运行代码会出现:<Figure size 432x288 with 0 Axes>。但是检查了图片的大小和格式感觉都没有问题。于是就想用书上的图片试试,构造了一个新的数据集再运行,结果就出来了,说明代码是没有问题的。但是我现在还不知道原因出在哪,所以只能先用这个新的数据集。
构造的新数据集如下:
在这里插入图片描述
实验代码:

# -*- coding: utf-8 -*-
from PIL import Image
from pylab import *
from numpy import *
import os
from PCV.localdescriptors import sift
from PCV.tools.imtools import get_imlist # 导入原书的PCV模块
import matplotlib.pyplot as plt # plt 用于显示图片
import matplotlib.image as mpimg # mpimg 用于读取图片
# 匹配最多的三张照片
# 获取project2_data文件夹下的图片文件名(包括后缀名)
filelist = get_imlist(r'D:\mydata')
# 输入的图片
im1f = r'D:\IMG_0399.jpg'
im1 = array(Image.open(im1f))
sift.process_image(im1f, 'out_sift_1.txt')
l1, d1 = sift.read_features_from_file('out_sift_1.txt')
i=0
num = [0]*30 # 存放匹配值
for infile in filelist: # 对文件夹下的每张图片进行如下操作
    im2 = array(Image.open(infile))
    sift.process_image(infile, 'out_sift_2.txt')
    l2, d2 = sift.read_features_from_file('out_sift_2.txt')
    matches = sift.match_twosided(d1, d2)
    num[i] = len(matches.nonzero()[0])
    i=i+1
    print ('{} matches'.format(num[i-1])) # 输出匹配值
i=1
figure()
gray()
#while i<4: # 循环三次,输出匹配最多的三张图片
    #index=num.index(max(num))
    #print (index, filelist[index])
    #lena = mpimg.imread(filelist[index])  # 读取当前匹配最大值的图片
    # 此时 lena 就已经是一个 np.array 了,可以对它进行任意处理
    #subplot(1,3,i)
    #plt.imshow(lena)  # 显示图片
    #plt.axis('off')  # 不显示坐标轴
    #num[index] = 0  #将当前最大值清零
    #i=i+1
show()

要进行匹配的图片:
在这里插入图片描述
结果如下:
在这里插入图片描述
小结:
输入一张要进行匹配的图片,与数据集中每一张图片一一进行匹配,每一次的匹配值存放在num中,最后是通过对num的值进行排序取前三大的值,即为匹配度前三的图片。
sift算法提取的图像特征点数不是一个固定值,维度是统一的128倍。

5.匹配地理特征

实验代码:
在这里插入图片描述
在这里插入图片描述
结果如下:
在这里插入图片描述
小结:
匹配地理特征采用的是循环嵌套匹配,一共15张图片即需要进行15*15次匹配。并且图片的读取是随机的。最终结果用可视化表示,匹配的图片相连,观察结果基本是正确的,但还是有出现一定的错误。

6.RANSAC特征匹配

(1)实验代码

# -*- coding: utf-8 -*-
import cv2
import numpy as np
import random

def compute_fundamental(x1, x2):
    n = x1.shape[1]
    if x2.shape[1] != n:
        raise ValueError("Number of points don't match.")
        
# build matrix for equations

A = np.zeros((n, 9))

 for i in range(n):
        A[i] = [x1[0, i] * x2[0, i], x1[0, i] * x2[1, i], x1[0, i] * x2[2,i],
                x1[1, i] * x2[0, i], x1[1, i] * x2[1, i], x1[1, i] * x2[2,i],
                x1[2, i] * x2[0, i], x1[2, i] * x2[1, i], x1[2, i] * x2[2,i]]

# compute linear least square solution

  U, S, V = np.linalg.svd(A)
  F = V[-1].reshape(3, 3)

 # constrain F
    # make rank 2 by zeroing out last singular value

U, S, V = np.linalg.svd(F)
    S[2] = 0
    F = np.dot(U, np.dot(np.diag(S), V))
    return F / F[2, 2]

def compute_fundamental_normalized(x1, x2):
    """    Computes the fundamental matrix from corresponding points
        (x1,x2 3*n arrays) using the normalized 8 point algorithm. """

n = x1.shape[1]

if x2.shape[1] != n:
        raise ValueError("Number of points don't match.")

x1 = x1 / x1[2]
    mean_1 = np.mean(x1[:2], axis=1)
    S1 = np.sqrt(2) / np.std(x1[:2])
    T1 = np.array([[S1, 0, -S1 * mean_1[0]], [0, S1, -S1 * mean_1[1]], [0, 0, 1]])
    x1 = np.dot(T1, x1)
    x2 = x2 / x2[2]
    mean_2 = np.mean(x2[:2], axis=1)
    S2 = np.sqrt(2) / np.std(x2[:2])
    T2 = np.array([[S2, 0, -S2 * mean_2[0]], [0, S2, -S2 * mean_2[1]], [0, 0, 1]])
    x2 = np.dot(T2, x2)
    # compute F with the normalized coordinates
    F = compute_fundamental(x1, x2)
    # print (F)
    # reverse normalization
    F = np.dot(T1.T, np.dot(F, T2))
    return F / F[2, 2]


def randSeed(good, num = 8):
    '''
    :param good: 初始的匹配点对
    :param num: 选择随机选取的点对数量
    :return: 8个点对list
    '''
    eight_point = random.sample(good, num)
    return eight_point

def PointCoordinates(eight_points, keypoints1, keypoints2):
    '''
    :param eight_points: 随机八点
    :param keypoints1: 点坐标
    :param keypoints2: 点坐标
    :return:8个点
    '''
    x1 = []
    x2 = []
    tuple_dim = (1.,)
    for i in eight_points:
        tuple_x1 = keypoints1[i[0].queryIdx].pt + tuple_dim
        tuple_x2 = keypoints2[i[0].trainIdx].pt + tuple_dim
        x1.append(tuple_x1)
        x2.append(tuple_x2)
    return np.array(x1, dtype=float), np.array(x2, dtype=float)

def ransac(good, keypoints1, keypoints2, confidence,iter_num):
    Max_num = 0
    good_F = np.zeros([3,3])
    inlier_points = []
    for i in range(iter_num):
        eight_points = randSeed(good)
        x1,x2 = PointCoordinates(eight_points, keypoints1, keypoints2)
        F = compute_fundamental_normalized(x1.T, x2.T)
        num, ransac_good = inlier(F, good, keypoints1, keypoints2, confidence)
        if num > Max_num:
            Max_num = num
            good_F = F
            inlier_points = ransac_good
    print(Max_num, good_F)
    return Max_num, good_F, inlier_points

def computeReprojError(x1, x2, F):
    """
    计算投影误差
    """
    ww = 1.0/(F[2,0]*x1[0]+F[2,1]*x1[1]+F[2,2])
    dx = (F[0,0]*x1[0]+F[0,1]*x1[1]+F[0,2])*ww - x2[0]
    dy = (F[1,0]*x1[0]+F[1,1]*x1[1]+F[1,2])*ww - x2[1]
    return dx*dx + dy*dy

def inlier(F,good, keypoints1,keypoints2,confidence):
    num = 0
    ransac_good = []
    x1, x2 = PointCoordinates(good, keypoints1, keypoints2)
    for i in range(len(x2)):
        line = F.dot(x1[i].T)
        #在对极几何中极线表达式为[A B C],Ax+By+C=0,  方向向量可以表示为[-B,A]
        line_v = np.array([-line[1], line[0]])
        err = h = np.linalg.norm(np.cross(x2[i,:2], line_v)/np.linalg.norm(line_v))
        # err = computeReprojError(x1[i], x2[i], F)
        if abs(err) < confidence:
            ransac_good.append(good[i])
            num += 1
    return num, ransac_good
if __name__ =='__main__':
    im1 = cv2.imread('D:/mydada/1.jpg')
    im2 = cv2.imread('D:/mydata/2.jpg')
    #im2 = r'D:\CVphoto\03065.jpg'
    print(cv2.__version__)
    psd_img_1 = cv2.imread(im1, cv2.IMREAD_COLOR)
    psd_img_2 = cv2.imread(im2, cv2.IMREAD_COLOR)

 # 3) SIFT特征计算
    sift = cv2.xfeatures2d.SIFT_create()
    # find the keypoints and descriptors with SIFT
    kp1, des1 = sift.detectAndCompute(psd_img_1, None)
    kp2, des2 = sift.detectAndCompute(psd_img_2, None)

 # FLANN 参数设计
    match = cv2.BFMatcher()
    matches = match.knnMatch(des1, des2, k=2)
    # Apply ratio test
    # 比值测试,首先获取与 A距离最近的点 B (最近)和 C (次近),
    # 只有当 B/C 小于阀值时(0.75)才被认为是匹配,
    # 因为假设匹配是一一对应的,真正的匹配的理想距离为0
    good = []
    for m, n in matches:
        if m.distance < 0.75 * n.distance:
            good.append([m])
    print(good[0][0])
    print("number of feature points:",len(kp1), len(kp2))
    print(type(kp1[good[0][0].queryIdx].pt))
    print("good match num:{} good match points:".format(len(good)))
    for i in good:
        print(i[0].queryIdx, i[0].trainIdx)

Max_num, good_F, inlier_points = ransac(good, kp1, kp2, confidence=30, iter_num=500)
    # cv2.drawMatchesKnn expects list of lists as matches.
    # img3 = np.ndarray([2, 2])
    # img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good[:10], img3, flags=2)
    # cv2.drawMatchesKnn expects list of lists as matches.
    img3 = cv2.drawMatchesKnn(psd_img_1,kp1,psd_img_2,kp2,good,None,flags=2)
    img4 = cv2.drawMatchesKnn(psd_img_1,kp1,psd_img_2,kp2,inlier_points,None,flags=2)

cv2.namedWindow('image1', cv2.WINDOW_NORMAL)
    cv2.namedWindow('image2', cv2.WINDOW_NORMAL)
    cv2.imshow("image1",img3)
    cv2.imshow("image2",img4)
    cv2.waitKey(0)#等待按键按下
    cv2.destroyAllWindows()#清除所有窗口

(2)实验过程

(1)景深丰富场景
原图:
在这里插入图片描述
没有RANSAC结果:
在这里插入图片描述
经过RANSAC结果:
在这里插入图片描述
小结:景深丰富场景中,没有经过RANSEC的sift特征结果中匹配点非常多,但其中有一些是错误的匹配点。经过RANSEC后匹配点减少部分,即留下更为精准的匹配点,但也还存在错误的匹配点,并且会删除部分正确的匹配点。相对于近景来说,远景(后面的房子和山)产生的匹配点更少。

(2)景深单一场景
原图:
在这里插入图片描述
没有RANSAC结果:
在这里插入图片描述
经过RANSAC结果:
在这里插入图片描述
小结:景深单一场景中,没有经过RANSEC的sift算法匹配出的匹配点也是较多,经过RANSAC后去掉了一些错误的匹配点,同时也会去掉少数正确的匹配点。在这种场景中,RANSAC算法的效果较好。

(3)实验总结

(1)RANSAC算法应用于sift特征检测中消除错配点中,能够有效的去除大部分的错误匹配点中,但是也有去掉正确匹配点的概率,所以并不是百分百准确的。
(2)RANSAC算法只能描述同一平面的问题,当特征匹配处于不同平面时,特征匹配不同。
(3)RANSAC算法的优缺点:
优点:能鲁棒的估计模型参数。例如,它能从包含大量局外点的数据集中估计出高精度的参数。
缺点:计算参数的迭代次数没有上限;如果设置迭代次数的上限,得到的结果可能不是最优的结果,甚至可能得到错误的结果。RANSAC只有一定的概率得到可信的模型,概率与迭代次数成正比。另一个缺点是它要求设置跟问题相关的阀值。而且RANSAC只能从特定的数据集中估计出一个模型,如果存在两个(或多个)模型,RANSAC不能找到别的模型。
(4)RANSAC常被应用在计算机视觉,例如对应点问题和估算立体摄影机双眼相对点的基本矩阵

三 遇到的问题及解决方案

3.1实验内容2遇到的问题

1.运行检测特征点的代码时出现错误:empire.sift not found
解决方法:为了解决这个问题,需要下载开源工具包VLfeat。而且需要下载vlfeat-0.9.20-bin.tar.gz这个版本。下载好之后进行解压。然后进行如下步骤:()
(1)把文件夹里win64中的sift.ext和vl.dll这两个文件复制到项目所在的文件夹中。
(2)修改Anaconda文件夹中的PCV文件夹中的localdescriptors文件夹中的sift.py文件。修改其中的cmmd路径为:cmmd=str(r"路径文件夹中的sift.exe的路径 “+imagename+” --output="+resultname+" "+params)即可。

2.解决了第1个问题之后,重新运行代码,发现如果是运行之前下载的文件包里的图片就能显示结果,而运行自己拍的图片的时候结果久久显示不出来。怀疑可能是图片太大了的原因。看了一下果然手机拍下的图片有2M多,而书上的图片只有几十Kb。于是使用ps软件将图片弄小了一点,结果就能显示了。
在这里插入图片描述

3.2实验内容3遇到的问题

3.运行匹配两张图片特征点的代码时出现错误:all the input arrays must have same number of dimensions
解决方法:这个问题是说进行匹配的两张图片的维度要一样,即像素要一致。于是对图片单击右键,进入编辑中的重新编辑图片大小,将两张图片的像素改为同一数据,再次运行代码结果就出来了。
在这里插入图片描述

3.3实验内容4遇到的问题

4.运行数据集内部检索匹配图片前三的代码时出现错误:[WinError 2] “dot” not found in path
百度后解决方法如下:
(1)修改set_prog函数如下:
在这里插入图片描述
(2)修改create函数如下:
在这里插入图片描述

3.4实验内容5遇到的问题

5.运行匹配地理特征代码时结果仅出现:The match scores is[ ]
解决方法:把数据集里面的图片后缀从JPG改为jpg即可。

3.5实验内容6遇到的问题

6.运行RANSEC算法代码时出现:
在这里插入图片描述
解决方法:这个问题是由于这个算法已经申请了专利,而OpenCV4.n版本下没有使用该算法的权限。所以需要降低OpenCV的版本。
在cmd进行操作,先卸载原有版本:
pip uninstall opencv-python
pip uninstall opencv-contrib-python
然后安装新版本:
pip install opencv-python3.4.2.16
pip install opencv-contrib-python
3.4.2.16

四 实验总结

1.sift算法对于特征值检测的准确度高于Hariis算法。
2.sift算法具有旋转,尺度不变性。并且对于仿射变换,噪声有一定的稳定性。
4.sift算法的缺点:实时性低,对边缘光滑的目标无法准确提取特征点。

发布了11 篇原创文章 · 获赞 1 · 访问量 1821

猜你喜欢

转载自blog.csdn.net/zencci/article/details/104702649