本次实验主要使用两种局部描述子算法,分别是Harris算法和SIFT算法。其中代码参考链接 http://yongyuan.name/pcvwithpython/
这个算法主要思想是:如果像素周围显示存在多于一个方向的边,就认为改点为兴趣点,也称改点为角点。
以下是角点检测的特征匹配代码
# -*- coding: utf-8 -*-
from pylab import *
from PIL import Image
from PCV.localdescriptors import harris
from PCV.tools.imtools import imresize
"""
This is the Harris point matching example in Figure 2-2.
"""
piop
# Figure 2-2上面的图
#im1 = array(Image.open("../data/crans_1_small.jpg").convert("L"))
#im2= array(Image.open("../data/crans_2_small.jpg").convert("L"))
# Figure 2-2下面的图
im1 = array(Image.open("尚大楼/尚大楼15.jpg").convert("L"))
im2 = array(Image.open("尚大楼/尚大楼20.jpg").convert("L"))
# resize加快匹配速度
im1 = imresize(im1, (im1.shape[1]//2, im1.shape[0]//2))
im2 = imresize(im2, (im2.shape[1]//2, im2.shape[0]//2))
wid = 5
harrisim = harris.compute_harris_response(im1, 5)
filtered_coords1 = harris.get_harris_points(harrisim, wid+1)
d1 = harris.get_descriptors(im1, filtered_coords1, wid)
harrisim = harris.compute_harris_response(im2, 5)
filtered_coords2 = harris.get_harris_points(harrisim, wid+1)
d2 = harris.get_descriptors(im2, filtered_coords2, wid)
print ('starting matching')
matches = harris.match_twosided(d1, d2)
figure()
gray()
harris.plot_matches(im1, im2, filtered_coords1, filtered_coords2, matches)
show()
要注意的是,如果从网络教材中复制代码的话,请一定记住,所以的print后面内容用括号括起来(本文以下其他代码也是)!!!这个代码还有一个可能出错的地方就是resize加快匹配速度那一部分的除号原文只有一条“/”,会出现下图错误
这时候只需要改成本文中的两条“/”就行了,因为cv2.resize内的参数是要求为整数。
结果如下图,可以看出匹配结果还行,但是也有较大一部分匹配不准确。
使用SIFT算法需要下载vlfeat,具体操作我是参考链接 http://yongyuan.name/pcvwithpython/installation.html#sec-0-4 当然按照链接做也是会出现一些奇奇怪怪的问题。
首先登陆vlfeat官网 http://www.vlfeat.org/ 然后点击上方download会出现下图页面,选择Downloads中的Previous versions …进入下载内容选择
推荐选择前面的,毕竟比较新,我是选择vlfeat-0.9.20-bin.tar.gz那个文件,没有bin的下载之后好像都是C文件,我们需要的是python文件。下载解压后进入文件夹 vlfeat-0.9.20,再进入bin文件夹,会发现有以下几个文件,根据自己的电脑操作系统选择文件夹,像我是win64位的就选win64,复制出来,放在某个记得住的地方(不知道有没有关系,我放在了跟PCV包一个文件夹之下,并且改名为win64vlfeat)
然后选择上面的PCV,进入PCV-master\PCV\localdescriptors这个目录下,可以看到有harris和sift两个.py文件
打开sift.py文件,找到cmmd这一块内容,在cmmd = str后面括号内加入之前我们安装的win64vlfeat文件夹中sift.exe的路径,在路径前加上r转义,如下图,强调print加括号!!!
然后辛辛苦苦检查了每一个括号,却会在运行测试代码时出现下图错误:
明明括号已经加了却还提示print错误,这时候不要慌,也不要像我一样检查了半个小时的print,请退到PCV-master文件夹之下找到setup这个文件,在这个文件夹之下重装一次PCV,左shift加鼠标右键选择在此处打开PowerShell窗口,输入python setup.py install 重装PCV包。然后理论上测试函数就能成功运行了。以下是SIFT算法代码:
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 = '../data/sf_view1.jpg'
# im2f = '../data/sf_view2.jpg'
im1f = '尚大楼/尚大楼15.jpg'
im2f = '尚大楼/尚大楼20.jpg'
# im1f = '../data/climbing_1_small.jpg'
# im2f = '../data/climbing_2_small.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()
首先是两张结果图的对比:
很显然,右图的SFIT算法更加准确,而Harris算法会出现一些奇怪的匹配结果,当然两个算法都存在一些不正确匹配,这是因为与现代的一些方法相比,图像像素块的互相关矩阵具有较弱的描述性,所以还是需要更好的算法来过滤掉这些不正确的匹配。