SIFT包括兴趣点检测器和描述子。SIFT描述子具有非常强的稳健性,经常和许多不同的兴趣点检测器结合使用。SIFT特征对于尺度,旋转和亮度都具有不变性,因此,它可用于三维视角和噪声的可靠匹配。
SIFT 描述子h(x, y,θ)是对特征点附近邻域内高斯图像梯度统计结果的一种表示,它是一个三维的阵列,但通常将它表示成一个矢量。矢量是通过对三维阵列按一定规律进行排列得到的。特征描述子与特征点所在的尺度有关,因此,对梯度的求取应在特征点对应的高斯图像上进行。
介绍:该数据集取自家乡的田野拍摄,照片之间有些有重合场景,但每张照片都互不相同,共16张。
原理介绍:SIFT是一种检测局部特征的算法,该算法通过求一幅图中的特征点及其有关scale 和 orientation 的描述子得到特征并进行图像特征点匹配,获得了良好效果。
# -*- 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 = '../data/empire.jpg'
im = array(Image.open(imname).convert('L'))
sift.process_image(imname, 'empire.sift')
l1, d1 = sift.read_features_from_file('empire.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()
SIFT特征提取与Harris角点提取的比较:
对数据集中每张图片SIFT特征提取,展示特征点:
原理介绍:SIFT特征匹配算法是一种基于尺度空间的、对图像缩放、旋转甚至仿射变换保持不变性的特征匹配算法。SIFT特征匹配算法分两个阶段来实现:第1阶段是SIFT特征的生成,即从多幅待匹配图像中提取出对尺度缩放、旋转、亮度变化无关的特征向量; 第2阶段是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 = '../data/c3.jpg'
im2f = '../data/c4.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()
1)有匹配特征点:
如下图,特征点匹配数量为75.
尺度与光线变化,如下图,特征点匹配数量为6.
2)无匹配特征点:
如下图,特征点匹配数量为0.
需要实现:给定一张输入的图片(数据集中没有),在数据集内部进行检索,输出与其匹配最多的三张图片。
原理介绍:将输入图片与数据集内每张图片进行两两SIFT特征匹配,将匹配值最高的三张图片输出。
# -*- coding: utf-8 -*-
from PIL import Image
from pylab import *
from numpy import *
import os
from PCV.tools.imtools import get_imlist # 导入原书的PCV模块
import matplotlib.pyplot as plt # plt 用于显示图片
import matplotlib.image as mpimg # mpimg 用于读取图片
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')
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 appendimages(im1, im2):
"""返回将两幅图像并排拼接成的一幅新图像"""
# 选取具有最少行数的图像,然后填充足够的空行
rows1 = im1.shape[0]
rows2 = im2.shape[0]
if rows1 < rows2:
im1 = concatenate((im1, zeros((rows2 - rows1, im1.shape[1]))), axis=0)
elif rows1 > rows2:
im2 = concatenate((im2, zeros((rows1 - rows2, im2.shape[1]))), axis=0)
return concatenate((im1, im2), axis=1)
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')
# 获取project2_data文件夹下的图片文件名(包括后缀名)
filelist = get_imlist('../data/field/')
# 输入的图片
im1f = 'c3.jpg'
im1 = array(Image.open(im1f))
process_image(im1f, 'out_sift_1.txt')
l1, d1 = read_features_from_file('out_sift_1.txt')
i = 0
num = [0] * 30 # 存放匹配值
for infile in filelist: # 对文件夹下的每张图片进行如下操作
im2 = array(Image.open(infile))
process_image(infile, 'out_sift_2.txt')
l2, d2 = read_features_from_file('out_sift_2.txt')
matches = match_twosided(d1, d2)
num[i] = len(matches.nonzero()[0])
i = i + 1
print '{} matches'.format(num[i - 1]) # 输出匹配值
i = 1
figure()
while i < 4: # 循环三次,输出匹配最多的三张图片
index = num.index(max(num))
print index, filelist[index]
lena = mpimg.imread(filelist[index]) # 读取当前匹配最大值的图片
# 此时 lena 就已经是一个 np.array 了,可以对它进行任意处理
# lena.shape # (512, 512, 3)
subplot(1, 3, i)
plt.imshow(lena) # 显示图片
plt.axis('off') # 不显示坐标轴
num[index] = 0 # 将当前最大值清零
i = i + 1
show()
原理介绍:用前面用到的SIFT描述子进行匹配,将两两进行特征匹配后的匹配数保存在matchscores中。
# -*- 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\\')
""" 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 = 'D:/Alike/python_dw/Code_a/admin_code/data/field' # set this to the path where you downloaded the panoramio images
path = 'D:/Alike/python_dw/Code_a/admin_code/data/field/' # 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('pic3.png')
RANSAC通过反复选择数据中的一组随机子集,来达成目标。在OpenCV中滤除误匹配对,采用RANSAC算法寻找一个最佳单应性矩阵H,矩阵大小为3×3。RANSAC目的是找到最优的参数矩阵使得满足该矩阵的数据点个数最多,通常令h3×3=1来归一化矩阵。由于单应性矩阵有8个未知参数,至少需要8个线性方程求解,对应到点位置信息上,一组点对可以列出两个方程,则至少包含4组匹配点对。
s [ x ′ y ′ 1 ] = [ h 11 h 12 h 13 h 21 h 22 h 23 h 31 h 32 h 33 ] [ x y 1 ] s\begin{bmatrix} x'\\ y'\\ 1 \end{bmatrix} =\begin{bmatrix} h_{11} & h_{12} & h_{13}\\ h_{21} & h_{22} & h_{23} \\ h_{31} & h_{32} & h_{33} \end{bmatrix} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} s⎣⎡x′y′1⎦⎤=⎣⎡h11h21h31h12h22h32h13h23h33⎦⎤⎣⎡xy1⎦⎤ 其中(x,y)表示目标图像角点位置,(x’,y’)为场景图像角点位置,s为尺度参数。
RANSAC算法从匹配数据集中随机抽出4个样本并保证这4个样本之间不共线,计算出单应性矩阵,然后利用这个模型测试所有数据,并计算满足这个模型数据点的个数与投影误差(即代价函数),若此模型为最优模型,则对应的代价函数最小。
∑ i = 1 n ( x i ′ h 11 x 1 + h 12 y 1 + h 13 h 31 x 1 + h 32 y 1 + h 33 ) 2 + ( y i ′ h 21 x 1 + h 22 y 1 + h 23 h 31 x 1 + h 32 y 1 + h 33 ) 2 \sum_{i=1}^{n} (x_{i}'\frac{h_{11}x_{1}+h_{12}y_{1}+h_{13}}{h_{31}x_{1}+h_{32}y_{1}+h_{33}})^{2} +(y_{i}'\frac{h_{21}x_{1}+h_{22}y_{1}+h_{23}}{h_{31}x_{1}+h_{32}y_{1}+h_{33}})^{2} i=1∑n(xi′h31x1+h32y1+h33h11x1+h12y1+h13)2+(yi′h31x1+h32y1+h33h21x1+h22y1+h23)2
1.随机选择四对匹配特征
2.根据DLT计算单应矩阵 H (唯一解)
3.对所有匹配点,计算映射误差ε=||pi’, Hpi||
4.根据误差阈值,确定inliers(例如3-5像素)
5.针对最大inliers集合,重新计算单应矩阵H
代码说明:
compute_fundamental
函数用八点法实现, x1、x2为匹配点集合,8点法传入的x1,x2分别为对应的8个匹配点;再用compute_fundamental_normalized
函数将匹配点进行归一化处理。randSeed
用于利用这4对匹配点,计算基础矩阵。ransac
为ransac算法实现,计算其余的点对到其对应对极线的距离dp ,如果dp≤d则该点为内点,否则为外点。记下符合该条件的内点的个数为num迭代k次,或者某次得到内点的数目num占有的比例大于等于95%,则停止。选择num最大的基础矩阵作为最终的结果。保存最优的结果。# -*- 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.")
# normalize image coordinates
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 = '../data/data4/1.jpg'
im2 = '../data/data4/2.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()#清除所有窗口
原图:
控制台输出:
分析:
观察景深丰富的场景,在整个建筑群中,匹配出较多的特征点,可以看出经过RANSAC算法后没有明显的错误点对剔除,SIFT特征匹配检测出315对匹配点,RANSAC算法剔除后有312对,变化不大。由于画面中下部分匹配特征点对较为密集,不便于区分,这里主要观察处于较高水平的几栋建筑物。
如下图红色椭圆圈出部分,图a中的紫色匹配线在图b中没有出现,我们可以看出a中的紫色线连接的两点明显不是匹配特征点,说明SIFI特征匹配出现了错配,而经过RANSAC算法剔除后,可以删除错配。
但是,同样发现原本图a中红色椭圆圈出部分检测出5对正确匹配,可图b中只剩下4对,所以RANSAC算法也可能使正确匹配特征同步被删除掉。
再观察蓝色椭圆内的匹配点连线,发现是一对错配,可经过RANSAC算法后也仍然存在,误差不可避免,但总体来说,已经达到了非常理想的效果。
原图:
控制台输出:
分析: 观察景深单一的场景,对比使用RANSAC算法剔除错配前后的两幅结果图,可以发现前者匹配点连线杂乱,存在较多对错配,比如建筑物上的特征点错配到草坪上。经RANSAC算法后,发现这时匹配点连线条数相对于之前少了很多,原先检测出84对匹配特征,现在只剩26对,部分正确匹配特征被删除;但是可以发现原本的错配几乎全部删除,最终结果匹配准确率高,体现了RANSAC算法的鲁棒性。
同一物体在不同景深场景的匹配
原图:
控制台输出:
分析:这组实验观察同一物体在不同景深场景的匹配效果,主要是取尚大楼近景与远景的图像做对比。观察到由于景深不同,尚大楼的边缘轮廓检测出的正确匹配特征点数较多,但SIFT特征匹配在建筑物的中部出现了错配现象,中间部分的匹配点连线较为杂乱。经RANSAC算法筛选后,剔除掉193-86=107对匹配特征,虽然仍然存在错配,但原先的错配已经被删去较多,总体效果不错。
解决:安装vlfeat,具体步骤为——
1.下载0.9.20版本的vlfeat.
2.把vIfeat文件夹 下win64中的sift.exe和v.dIl这两个文件复制到项目的文件夹中.
3.修改Anaconda文件夹下的PCV文件夹里面的localdescriptors文件夹中的sift.py文件,使用记事本打开,修改其中的cmmd内的路径为:cmmd =str(r"D:\PythonWork\SIFT\sift.exe "+ imagename+”-- output=" + resultname+" "+params)
(路径是你项目文件夹中的sift.exe的路径)然后要记得在括号内加r! !不然会出错! !
然后就能够运行了。如果在运行过程中提示关于print的错误,记得根据错误提醒的文件夹,去修改相应的print语法,3.5的python的print用法是需要加括号。
解决:首先注意安装pydot过程——
(找了很多种方法,很多网址上的描述都不一样,我自己是这么做的:)
pip install graphviz
②pip install pydot
③pip install pydot-ng
import os
os.environ['PATH'] = os.environ['PATH'] + (';d:\\Alike\\python_dw\\graphviz_dw\\bin\\')
③注意:pydot的Node节点添加图片时,图片的路径需要为绝对路径,且分隔符为/。
解决:经查阅资料,发现是opencv版本不对,需要opencv3.x的版本,默认安装的版本为4.x。
在命令行中执行,到Scripts目录下:
1.卸载已有opencv:①pip uninstall opencv-python
②pip uninstall opencv-contrib-python
(有多少卸多少)
2.安装3.x版本的opencv:pip install opencv-contrib-python==3.2.0.7 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
安装完成后问题解决。