文章目录
- 一、SIFT特征匹配原理
- 1.1简介
- 1.2特点
- 1.3算法步骤
- 二、数据集
- 三、SIFT特征检测兴趣点
- 四、SIFT特征描述子匹配
- 五、目标图片匹配特征点最多的三张图片
- 六、 地理标记图像匹配
- 七、RANSAC算法剔除误匹配
- 7.1关于RANSAC算法的论述
- 7.2算法代码
- 7.3结果展示与分析
- 7.4 小结
- 八、总结
- 8.1 小结
- 8.2遇到的问题及解决
一、SIFT特征匹配原理
1.1简介
SIFT,也叫尺度不变特征变换算法,是David Lowe于1999年提出的局部特征描述子。SIFT算法的实质是:“不同的尺度空间上查找关键点(特征点),并计算出关键点的方向”。
1.2特点
Sift算子具有以下特性:
(1)Sift特征是图像的局部特征,对平移、旋转、尺度缩放、亮度变化、遮挡和噪声等具有良好的不变性,对视觉变化、仿射变换也保持一定程度的稳定性。
(2)独特性好,信息量丰富,适用于在海量特征数据库中进行快速、准确的匹配。
(3)多量性,即使少数的几个物体也可以产生大量Sift特征向量。
(4)速度相对较快,经优化的Sift匹配算法甚至可以达到实时的要求。
(5)可扩展性强,可以很方便的与其他形式的特征向量进行联合。
1.3算法步骤
- 尺度空间极值检测
搜索所有尺度上的图像位置。通过高斯微分函数来识别潜在的对于尺度和旋转不变的兴趣点。
Lowe使用更为高效的高斯差分算子(DOG)进行极值检测,如下:
对应DOG算子建立DOG金字塔(如下图)使用DOG金字塔,每组中相邻上下两层图像相减,得到高斯差分图像。通过高斯差分图像可以看出图像像素值的变化情况。
此处高斯金字塔的构建主要为两部分(1)对图像做不同尺度的高斯模糊(2)对图像做降采样(隔点采样)
当我们得到DoG之后,图像在尺度空间中搜寻局部极值。为了寻找DoG函数的极值点, 每一个像素点要和它所有的相邻点比较,看其是否比它的图像域和尺度域 的相邻点大或者小。如下图所示
2. 关键点定位
检测到的极值点是离散空间的极值点,以下通过拟合三维二次函数来精确确定关键点的位置和尺度,同时去除低对比度的关键点和不稳定的边缘响应点(因为DoG算子会产生较强的边缘响应),以增强匹配稳定性、提高抗噪声能力。
3…方向确定
利用直方图统计领域内像素对应的梯度和幅值:梯度方向角为横轴刻度,取45度为一个单位,那么横轴就有8个刻度;纵轴是对应梯度的幅值累加值。取幅值最高的方向为主方向。
4.关键点描述
确定描述子采样区域后,生成描述子,为了保证特征矢量具有旋转不变性,需要以特征点为中心,将特征点附近邻域内图像梯度的位置和方向旋转一个方向角θ,即将原图像x轴转到与主方向相同的方向。而后生成特征匹配点。
关于原理的详细解释可见这位博主的博客非常详细的sift算法原理解析
二、数据集
本数据集为自行采集的16张主体物体主要为建筑的图像。
三、SIFT特征检测兴趣点
代码
处理图像部分源码:
def process_image(imagename, resultname, params="--edge-thresh 10 --peak-thresh 5"):
""" 处理一幅图像,然后将结果保存在文件中"""
if imagename[-3:] != 'pgm':
#创建一个pgm文件
im = Image.open(imagename).convert('L')
im.save('tmp.pgm')
imagename ='tmp.pgm'
cmmd = str("sift "+imagename+" --output="+resultname+" "+params)
os.system(cmmd)
print ('processed', imagename, 'to', resultname)
读取并保存特征值部分源码:
def read_features_from_file(filename):
"""读取特征属性值,然后将其以矩阵的形式返回"""
f = loadtxt(filename)
return f[:,:4], f[:,4:] #特征位置,描述子
def write_featrues_to_file(filename, locs, desc):
"""将特征位置和描述子保存到文件中"""
savetxt(filename, hstack((locs,desc)))
显示特征图像部分源码:
def plot_features(im, locs, circle=False):
"""显示带有特征的图像
输入:im(数组图像),locs(每个特征的行、列、尺度和朝向)"""
def draw_circle(c,r):
t = arange(0,1.01,.01)*2*pi
x = r*cos(t) + c[0]
y = r*sin(t) + c[1]
plot(x, y, 'b', linewidth=2)
imshow(im)
if circle:
for p in locs:
draw_circle(p[:2], p[2])
else:
plot(locs[:,0], locs[:,1], 'ob')
axis('off')
主体源码:
# -*- coding: utf-8 -*-
from PIL import Image
from pylab import *
from PCV.localdescriptors import sift
from PCV.localdescriptors import harris
# 添加中文字体支持
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
imname = 'image/15.jpg'
im = array(Image.open(imname).convert('L'))
sift.process_image(imname, '15.sift')
l1, d1 = sift.read_features_from_file('15.sift')
figure()
gray()
subplot(131)
sift.plot_features(im, l1, circle=False)
title(u'SIFT特征',fontproperties=font)
subplot(132)
sift.plot_features(im, l1, circle=True)
title(u'用圆圈表示SIFT特征尺度',fontproperties=font)
# 检测harris角点
harrisim = harris.compute_harris_response(im)
subplot(133)
filtered_coords = harris.get_harris_points(harrisim, 6, 0.1)
imshow(im)
plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')
axis('off')
title(u'Harris角点',fontproperties=font)
show()
结果:
下面展示数据集中16张图片的SIFT特征检测及角点检测结果
分析:
图二中圆圈表示特征尺度,图中可看出特征点检测较稀疏的地方,圆圈较大即特征尺度较大。SIFT检测出的结果与角点检测的结果不同,明显SIFT特征检测出的特征点多于使用角点检测出的特征点。这是因为SIFT特征检测选取的对象会使用DoG检测关键点,并且对每个关键点各个方向计算特征向量,因而能检测到较多特征点。SIFT特征检测对物体检测出大量的特征,体现了其多量性。
四、SIFT特征描述子匹配
代码
匹配部分代码:
def match(desc1, desc2):
"""对于第一幅图像中的每个描述子,选取其在第二幅图像中的匹配
输入:desc1(第一幅图像中的描述子),desc2(第二幅图像中的描述子)"""
desc1 = array([d/linalg.norm(d) for d in desc1])
desc2 = array([d/linalg.norm(d) for d in desc2])
dist_ratio = 0.6
desc1_size = desc1.shape
matchscores = zeros((desc1_size[0],1),'int')
desc2t = desc2.T #预先计算矩阵转置
for i in range(desc1_size[0]):
dotprods = dot(desc1[i,:],desc2t) #向量点乘
dotprods = 0.9999*dotprods
# 反余弦和反排序,返回第二幅图像中特征的索引
indx = argsort(arccos(dotprods))
#检查最近邻的角度是否小于dist_ratio乘以第二近邻的角度
if arccos(dotprods)[indx[0]] < dist_ratio * arccos(dotprods)[indx[1]]:
matchscores[i] = int(indx[0])
return matchscores
匹配部分代码:
def match_twosided(desc1, desc2):
"""双向对称版本的match()"""
matches_12 = match(desc1, desc2)
matches_21 = match(desc2, desc1)
ndx_12 = matches_12.nonzero()[0]
# 去除不对称的匹配
for n in ndx_12:
if matches_21[int(matches_12[n])] != n:
matches_12[n] = 0
return matches_12
绘制匹配线代码:
def plot_matches(im1,im2,locs1,locs2,matchscores,show_below=True):
""" 显示一幅带有连接匹配之间连线的图片
输入:im1, im2(数组图像), locs1,locs2(特征位置),matchscores(match()的输出),
show_below(如果图像应该显示在匹配的下方)
"""
im3=appendimages(im1,im2)
if show_below:
im3=vstack((im3,im3))
imshow(im3)
cols1 = im1.shape[1]
for i in range(len(matchscores)):
if matchscores[i]>0:
plot([locs1[i,0],locs2[matchscores[i,0],0]+cols1], [locs1[i,1],locs2[matchscores[i,0],1]],'c')
axis('off')
总体源代码:
from PIL import Image
from pylab import *
import sys
from PCV.localdescriptors import sift
if len(sys.argv) >= 3:
im1f, im2f = sys.argv[1], sys.argv[2]
else:
im1f = 'image/1.jpg'
im2f = 'image/2.jpg'
im1 = array(Image.open(im1f))
im2 = array(Image.open(im2f))
sift.process_image(im1f, 'out_sift_1.txt')
l1, d1 = sift.read_features_from_file('out_sift_1.txt')
figure()
gray()
subplot(121)
sift.plot_features(im1, l1, circle=False)
sift.process_image(im2f, 'out_sift_2.txt')
l2, d2 = sift.read_features_from_file('out_sift_2.txt')
subplot(122)
sift.plot_features(im2, l2, circle=False)
#matches = sift.match(d1, d2)
matches = sift.match_twosided(d1, d2)
print '{} matches'.format(len(matches.nonzero()[0]))
figure()
gray()
sift.plot_matches(im1, im2, l1, l2, matches, show_below=True)
show()
结果
选取不同角度的一组
旋转角度的一组
遮挡以及光线不同的一组
拉近拉远的一组
分析
由结果可知,在旋转,远近,遮挡等不同角度等变换下的图像检测到的特征点几乎都能匹配,说明不论平移,变换角度,光线变化等对特征点匹配几乎没有影响。
对于尺度缩放保持不变性的分析,是因为构建了高斯金字塔,对图片进行高斯卷积操作,寻找尺度空间的极值点,每一个采样点要和它所有的相邻点比较,看其是否比它的图像域和尺度域的相邻点大或者小。一个点如果在DOG尺度空间本层以及上下两层的26个领域中是最大或最小值时,就认为该点是图像在该尺度下的一个特征点,使得图片在任何尺度都能够有对应的特征点。
对于光照影响的分析,在求出128维特征向量后,此时SIFT特征向量已经去除了尺度变化、旋转等几何变形因素的影响。而图像的对比度变化相当于每个像素点乘上一个因子,光照变化是每个像素点加上一个值,但这些对图像归一化的梯度没有影响。因此将特征向量的长度归一化,则可以进一步去除光照变化的影响。
值得一提的是,后两组图像中出现了几处特征点匹配错误的情况,且能匹配到的特征点少,虽然代码中有去除匹配错误的操作,但还是出现了匹配错误的情况,说明特征点匹配是存在误匹配率的。据此,查找资料发现,有研究者通过基于距离比率准则的方法改进了SIFT检测来去除SIFT特征匹配中的错误匹配。此方法,直接通过两条匹配直线斜率的一致性判断,剔除不在斜率范围内的匹配,有效提高了特征匹配的正确率。详见一种提高SIFT特征匹配正确率的方法.
五、目标图片匹配特征点最多的三张图片
代码
opencv结合SIFT算法提取物体特征点,利用FLANN匹配器进行匹配,匹配时循环检测数据集中的每张图片及其特征点,而后输出匹配到的特征点最多的3张图片。FLANN 代表 Fast Library for Approximate Nearest Neighbors. 它包含一组算法,这些算法针对大型数据集中的快速最近邻搜索和高维特征进行了优化,对于数据集可以较快处理。
# -*- coding: utf-8 -*-
from os.path import join
from os import walk
import numpy as np
import cv2
import matplotlib.pyplot as plt
from matplotlib.pyplot import figure
query = cv2.imread('image/1.jpg', 0)
folder = 'F:\PycharmProjects\Test\image'
descriptors = []
# 获取特征数据文件名
for (dirpath, dirnames, filenames) in walk(folder):
for f in filenames:
if f.endswith("npy"):
descriptors.append(f)
print(descriptors)
# 使用SIFT算法检查图像的关键点和描述符
sift = cv2.xfeatures2d.SIFT_create()
query_kp, query_ds = sift.detectAndCompute(query, None)
# 创建FLANN匹配器
index_params = dict(algorithm=0, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
potential_culprits = {}
for d in descriptors:
# 将图像query与特征数据文件的数据进行匹配
matches = flann.knnMatch(query_ds, np.load(join(folder, d)), k=2)
# 清除错误匹配
good = []
for m, n in matches:
if m.distance < 0.7 * n.distance:
good.append(m)
# 输出每张图片与目标图片的匹配数目
print("img is %s ! matching rate is (%d)" % (d, len(good)))
potential_culprits[d] = len(good)
c=sorted(potential_culprits.items(),key=lambda s: s[1],reverse=True)
b=c[:3]
print(b)
结果
数据库中外的图片对数据库的匹配
数据库中已有的图片匹配
分析
数据库外的图片,与数据库中图片匹配,可看出匹配度较高的3张图,与输入图片中的建筑确实是同一建筑,可见SIFT匹配检测独特性好,在数据库中能准配匹配到特征点相同的图片局部图像块。
由上图,可知,输入图片1后,输出的图片与图片1,7,8有较高匹配度。从图片中也可以看出,输入的图片有两个主体建筑,匹配结果匹配度最高的是原图,其次是两张是以两个主体建筑的为主的图片,可见SIFT匹配检测正确率还是很高的。
六、 地理标记图像匹配
源码
# -*- coding: utf-8 -*-
from pylab import *
from PIL import Image
from PCV.localdescriptors import sift
from PCV.tools import imtools
import pydot
import os
#os.environ['PATH'] = os.environ['PATH'] + (';d:\\Alike\\python_dw\\graphviz_dw\\bin\\')
os.environ['PATH'] = os.environ['PATH'] + (';F:\\Program Files (x86)\\Graphviz2.38\\bin\\')
""" This is the example graph illustration of matching images from Figure 2-10.
To download the images, see ch2_download_panoramio.py."""
#download_path = "panoimages" # set this to the path where you downloaded the panoramio images
#path = "/FULLPATH/panoimages/" # path to save thumbnails (pydot needs the full system path)
download_path = "F:/PycharmProjects/ComputerVision/ch2/panoimages" # set this to the path where you downloaded the panoramio images
path = "F:/PycharmProjects/ComputerVision/ch2/panoimages/" # path to save thumbnails (pydot needs the full system path)
# list of downloaded filenames
imlist = imtools.get_imlist(download_path)
nbr_images = len(imlist)
# extract features
featlist = [imname[:-3] + 'sift' for imname in imlist]
for i, imname in enumerate(imlist):
sift.process_image(imname, featlist[i])
matchscores = zeros((nbr_images, nbr_images))
for i in range(nbr_images):
for j in range(i, nbr_images): # only compute upper triangle
print 'comparing ', imlist[i], imlist[j]
l1, d1 = sift.read_features_from_file(featlist[i])
l2, d2 = sift.read_features_from_file(featlist[j])
matches = sift.match_twosided(d1, d2)
nbr_matches = sum(matches > 0)
print 'number of matches = ', nbr_matches
matchscores[i, j] = nbr_matches
print "The match scores is: \n", matchscores
# copy values
for i in range(nbr_images):
for j in range(i + 1, nbr_images): # no need to copy diagonal
matchscores[j, i] = matchscores[i, j]
#可视化
threshold = 2 # min number of matches needed to create link
g = pydot.Dot(graph_type='graph') # don't want the default directed graph
for i in range(nbr_images):
for j in range(i + 1, nbr_images):
if matchscores[i, j] > threshold:
# first image in pair
im = Image.open(imlist[i])
im.thumbnail((100, 100))
filename = path + str(i) + '.png'
im.save(filename) # need temporary files of the right size
g.add_node(pydot.Node(str(i), fontcolor='transparent', shape='rectangle', image=filename))
# second image in pair
im = Image.open(imlist[j])
im.thumbnail((100, 100))
filename = path + str(j) + '.png'
im.save(filename) # need temporary files of the right size
g.add_node(pydot.Node(str(j), fontcolor='transparent', shape='rectangle', image=filename))
g.add_edge(pydot.Edge(str(i), str(j)))
g.write_png('result.png')
结果
分析:
为方便分析,对图片做了标号如下:
由地理标记结果,可看出,中间部分,图1和图6为可匹配到数据库中较多图片,均有6张图片可与其匹配。这一结果与图片实际符合契合程度很高。SIFT特征检测在匹配过程中,准确的匹配了同一建筑在不同角度,不同远近下的特征点,体现了SIFT特征检测的尺度不变性。
左边部分图15.16是其他场景的图片,与图1-14实际并不在同一地域内,但结果与图5有匹配点。这是出现了误匹配,我认为原因在于SIFT特征检测在构建高斯金字塔对图像进行高斯模糊后提取局部特征点的过程中,两图片出现了可匹配的特征点(实际上两图片中建筑有局部确是构造相似,图5与图6都是有尖顶且下方是一层一层的建筑)。
右边部分,图12,13,14实际中与图9,10,11并没有相同的建筑或场景,所以理论上不应出现特征匹配并在图中建立关联,但实际上检测结果是有可匹配的特征点。由右边部分图片在标记关联的图中相对距离较远,也可得知,图12,13,14与图9,10,11可匹配的特征点很少。仍出现有特征点匹配情况的原因,还是由于高斯模糊后提取到的图像块有局部特征点被匹配。
图中建筑群丰富,图片特征较多,但SIFT特征检测能在数据库中较准确的匹配出在不同图片中的同一建筑,体现了其多量性。
七、RANSAC算法剔除误匹配
7.1关于RANSAC算法的论述
RANSAC核心思想就是随机性和假设性,随机性用于减少计算,循环次数是利用正确数据出现的概率。所谓的假设性,就是说随机抽出来的数据都认为是正确的,并以此去计算其他点,获得其他满足变换关系的点,然后利用投票机制,选出获票最多的那一个变换。
采用RANSAC算法寻找一个最佳单应性矩阵H,矩阵大小为3×3。RANSAC目的是找到最优的参数矩阵使得满足该矩阵的数据点个数最多,通常令h33=1h33=1来归一化矩阵。由于单应性矩阵有8个未知参数,至少需要8个线性方程求解,对应到点位置信息上,一组点对可以列出两个方程,则至少包含4组匹配点对。
算法思路:
1.首先从数据集中随机选出一组局内点(其数目要保证能够求解出模型的所有参数), 计算出一套模型参数。
2.用得到的模型去测试其他所有的数据点,如果某点的误差在设定的误差阈值之内,就判定其为局内点,否则为局外点,只保留目前为止局内点数目最多的模型,将其记录为最佳模型。
3.重复执行1,2步足够的次数(即达到预设的迭代次数)后,使用最佳模型对应的局内点来最终求解模型参数,该步可以使用最小二乘法等优化算法。
4.最后可以通过估计局内点与模型的错误率来评估模型。
RANSAC算法在SIFT特征筛选中的主要流程是:
- 从匹配点的样本集中随机抽选一个RANSAC样本,即4个匹配点对(因为最少四个点才能描述变换过程,四个点有八个自由度,而射影变换也有八个自由度)
- 根据这4个匹配点对计算得到一个变换矩阵M
- 根据样本集,变换矩阵M,和误差度量函数计算满足当前变换矩阵的一致集
- 根据当前一致集中元素个数判断是否最优(最大)一致集,若是则更新当前最优一致集
7.2算法代码
def matchKeyPoints(self,kp1, kp2, des1, des2, ratio, reprojThresh):
#初始化BF,因为使用的是SIFT ,所以使用默认参数
matcher = cv.DescriptorMatcher_create('BruteForce')
matches = matcher.knnMatch(des1, des2, 2)
#获取理想匹配
good = []
for m in matches:
if len(m) == 2 and m[0].distance < ratio * m[1].distance:
good.append((m[0].trainIdx, m[0].queryIdx))
print(len(good))
#最少要有四个点才能做透视变换
if len(good) > 4:
#获取关键点的坐标
src_pts = np.float32([kp1[i] for (_, i) in good])
dst_pts = np.float32([kp2[i] for (i, _) in good])
#通过两个图像的关键点计算变换矩阵
(M, mask) = cv.findHomography(src_pts, dst_pts, cv.RANSAC, reprojThresh)
#返回最佳匹配点、变换矩阵
return (good, M, mask)
#如果不满足最少四个 就返回None
return None
此函数实现了用RANSAC算法筛选匹配点,返回结果是计算好的最佳匹配点和变换矩阵。
7.3结果展示与分析
景深丰富的两组图
组图(1)没有RANSAC的SIFT特征匹配结果图(上)与经过RANSAC的SIFT特征匹配结果图(下):
组图(2)没有RANSAC的SIFT特征匹配结果图(上)与经过RANSAC的SIFT特征匹配结果图(下):
分析:
- 在组图(1)中,利用SIFT特征对两图进行未剔除误匹配的特征点匹配,首先两图景深都很大,图中有较多的景物,SIFT特征匹配因在构建高斯金字塔对图像进行高斯模糊后提取局部特征点的过程中,误匹配了大量特征点,且较远处的特征点未被匹配,在利用RANSAC算法剔除误匹配后,剩余的特征匹配正确率一般,还有一半误匹配的特征点未被剔除;
- 在组图(2)中,一幅图景深较大,另一幅相对景深小一些,也存在误匹配了特征点,在利用RANSAC算法剔除误匹配后,剩余的特征匹配正确率整体较高,很明显的误匹配特征点大部分被剔除了;
- 但存在正确的匹配被剔除,如组图(2)最高建筑的顶部SIFT特征匹配是正确匹配结果,但在用RANSAC算法后此匹配未被检测出来;
- 也存在部分误匹配点未剔除,如组图(1)中较矮的建筑都是误匹配(实际确实两个建筑确实十分相似,但不是同一个),组图(2)最高建筑的中部有两对误匹配的特征,在用RANSAC算法后此匹配没有被剔除;
- 原因是RANSAC算法在迭代次数到达设定的最大值后即停止而后得到结果,在有限得迭代次数中得到的结果还不是最优的正确匹配数。设置更高的迭代次数可以得到更优的结果,但这也会影响算法的运行效率。所以剔除结果的正确性与设置合适迭代次数有很大关系。
- 另外,算法存在一定误差也是导致误匹配点未剔除的原因。
景深较单一的两组图
组图(1)没有RANSAC的SIFT特征匹配结果图(上)与经过RANSACSIFT特征匹配结果图(下):
组图(2)没有RANSAC的SIFT特征匹配结果图(上)与经过RANSACSIFT特征匹配结果图(下):
分析:
在景深较单一组图(1)中,利用SIFT特征对两图进行未剔除误匹配的特征点匹配,由结果可知匹配出了215对特征点,在利用RANSAC算法剔除误匹配后,剩余的匹配点还有186对,比例高达86%,且均是正确的匹配。
在景深较单一组图(2)中,利用SIFT特征对两图进行未剔除误匹配的特征点匹配,由结果可知匹配出了104对特征点,在利用RANSAC算法剔除误匹配后,剩余的匹配点还有58%,60对。
两组图未剔除误匹配的结果中,可明显看出有许多距离远的误匹配线,特征点并不对应,甚至部分误匹配的连线与正确的特征点匹配连线交叉角度大,RANSAC算法剔除后的匹配特征点集中,留下了匹配连线斜率较近的匹配特征点,确实为正确匹配特征点,可见剔除误匹配的正确率较高,体现了RANSAC算法的鲁棒性。
7.4 小结
SIFT特征匹配对景深较大的图,高斯模糊后提取局部特征点过于相似,易产生大量误匹配;对近处的景物能能测出匹配特征点,远处的景物则较难检测出匹配特征点。
RANSAC算法对景深丰富的图剔除结果不如景深较单一的图理想,这与算法的误差和迭代次数有关系。
对于RANSAC算法:
- 优点:
RANSAC算法鲁棒性强,对景深较单一图能准确剔除误匹配的特征点。 - 缺点:
1.算法由于需阈值有所局限,阈值的大小与是否能得到最优匹配结果有很大关系;
2.应用范围小,只能从特定的数据集中得到一个模型;
3.受迭代次数影响,若设置迭代次数不够合理难以得到最优的模型。
八、总结
8.1 小结
- SIFT特征检测具有旋转、缩放、平移不变性,光照,遮挡等对特征匹配几乎没有影响。
- 优点:
(1)SIFT特征检测独特性好,能在数据库中准确匹配。
(2)具有多量性,同一图片相对于Harris检测,SIFT特征检测能检测出更多的特征点。 - 缺点:
(1)实时性差,一方面图片分辨率过大,影响算法运行效率,导致实时性不高,可调整图像为合适大小的尺寸;另一方面,Sift匹配算法本身其实相对匹配速度不慢,但可优化Sift匹配算法,选取更高效的匹配算法,可以提高实时性。
(2)有时匹配到的特征点少 ,这里于Sift匹配算法有关,优化算法可以改进一点。
(3)存在误匹配率,对于剔除误匹配:一个思路是取可信的匹配点计算出矫正矩阵,如果加入的匹配点导致这个矫正矩阵有一个大的变化。
8.2遇到的问题及解决
- 问题:找不到.sift文件
解决:根据下图成功解决
2.问题:运行很久都未显示检测的图像结果
解决:经几次实验经验,发现图片分辨率过大,算法运行较慢,因此需调整图片大小为合适的大小,调整后算法能较快运行出结果。
3.问题:关于pydot包与graphviz包导入问题
解决:可以参考这位同学的解决方法计算机视觉–SIFT特征提取与检索 4.问题:提示错误如下
解决:原因是没有导入该opencv包。需要导入含有xfeature2d的opencv包。