关于 VLFeat 的说明可参考:
[1] - VLFeat指南——SIFT检测器和描述子 - 2014.11.20
[2] - 图像检索(1): 再论SIFT-基于vlfeat实现 - 2018.06.13
VLFeat 的参数说明可见:https://www.vlfeat.org/api/sift_8h.html
1. 命令行实现
1.1. 下载编译vlfeat
下载: https://www.vlfeat.org/download.html
Github:https://www.github.com/vlfeat/vlfeat.git
由于 VLFeat 0.9.21 编译后运行 sift 输出的结果为空,这里采用 VLFeat 0.9.20.
wget https://www.vlfeat.org/download/vlfeat-0.9.21.tar.gz
tar -xzvf vlfeat-0.9.21.tar.gz
cd vlfeat-0.9.20
make
即可以在 vlfeat-0.9.20/bin
路径生成 sift
工具.
1.2. Python 调用命令行
Vlfeat sift:https://www.vlfeat.org/man/sift.html
import os
from PIL import Image
def vlfeat_sift_extract(img_file, params="--edge-thresh 10 --peak-thresh 1"):
img_pil = Image.open(img_file).convert('L')
gray_imgfile = os.path.basename(img_file) + '.pgm'
img_pil.save(gray_imgfile)
#
sift_file = os.path.basename(img_file) + '.sift'
cmd_str = "vlfeat-0.9.20/bin/glnxa64/sift {} --output={} {}".format(gray_imgfile, sift_file, params)
msg = os.system(cmd_str)
print('[INFO]msg: ', msg)
2. Cyvlfeat 实现
2.1. 安装
Github - menpo/cyvlfeat
Conda 安装(推荐):
#https://anaconda.org/menpo/cyvlfeat
conda install -c conda-forge cyvlfeat
# 或pip
#pip install cyvlfeat (调用时可能会出错)
2.2. 示例
import numpy as np
from cyvlfeat.sift import sift as vlsift
def vlfeat_sift_extract(img_file):
img_cv2 = cv2.imread(img_file)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY).astype(np.float32)
kp, des = vlsift(gray, peak_thresh=5.0, compute_descriptor=True, float_descriptors=True)
sift_vector = kp + des
#
sift_file = os.path.basename(img_file) + '.sift'
np.savetxt(sift_file, np.array(sift_vector), fmt='%0.8f')
3. SIFT 可视化
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
def vis_sifts(imgfile, locs, circle=True):
def draw_circle(c,r):
t = np.arange(0,1.01,.01)*2*np.pi
x = r*np.cos(t) + c[0]
y = r*np.sin(t) + c[1]
plt.plot(x,y,'b',linewidth=2)
plt.figure(figsize=(10, 8))
img_pil = Image.open(imgfile)
plt.imshow(img_pil)
if circle:
for p in locs:
draw_circle(p[:2],p[2])
else:
plt.plot(locs[:,0],locs[:,1],'ob')
plt.axis('off')
plt.title('{} sift features'.format(len(locs)))
plt.show()