一、SIFT算法特征原理

SIFT即尺度不变特征转换,它用来检测图像的局部性特征,在空间尺度中寻找极值点,提取这点的位置、尺度、旋转不变量。这些关键点是一些十分突出,不会因光照和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等,所以与影像的大小和旋转无关,对光线、噪声、视角改变的容忍度也很高。

       SIFT特征检测有四步:

1.尺度空间的极值检测:搜索所有尺度空间上的图像,通过高斯微分函数来识别潜在的对尺度和选择不变的兴趣点。

2.特征点定位:在每个候选的位置上,通过一个拟合精细模型来确定位置尺度,关键点的选取依据他们的稳定程度。

3.特征方向赋值:基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向,后续的所有操作都是对于关键点的方向、尺度和位置进行变换,从而提供这些特征的不变性。

4.特征点描述:在每个特征点周围的邻域内,在选定的尺度上测量图像的局部梯度,这些梯度被变换成一种表示,这种表示允许比较大的局部形状的变形和光照变换。

 

二、SIFT特征匹配处理

  对两张图片进行SIFT特征匹配处理

    1.两张差异较大的集美大学尚大楼

      原图:

                   SIFT特征匹配处理           SIFT特征匹配处理

                                           图1                                                   图2

 

      SIFT特征匹配:

      SIFT特征匹配处理

                                                                     图3

 

    2. 两张差异较小的集美大学尚大楼

           原图:

       SIFT特征匹配处理  SIFT特征匹配处理

                               图4                                                       图5

 

 

      SIFT特征匹配:

      SIFT特征匹配处理

 代码:

 1 import io
 2 from PIL import Image, ImageTk
 3 import tkinter as tk
 4 
 5 import cv2
 6 import numpy as np
 7 MIN_MATCH_COUNT = 4
 8 
 9 img1 = cv2.imread("C:/Users/w/PycharmProjects/sift/picture/1.jpg")
10 img2 = cv2.imread("C:/Users/w/PycharmProjects/sift/picture/16.jpg")
11 g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
12 g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
13 sift = cv2.xfeatures2d.SIFT_create()
14 match = cv2.FlannBasedMatcher(dict(algorithm =2, trees =1), {})
15 kp1, de1 = sift.detectAndCompute(g1,None)
16 kp2, de2 = sift.detectAndCompute(g2,None)
17 m = match.knnMatch(de1, de2, 2)
18 m = sorted(m,key = lambda x:x[0].distance)
19 ok = [m1 for (m1, m2) in m if m1.distance < 0.7 * m2.distance]
20  med = cv2.drawMatches(img1, kp1, img2, kp2, ok, None)
21 
22 cv2.imwrite("C:/Users/w/PycharmProjects/sift/picture/b.jpg", med)
23 #
24 # cv2.imshow("0", med)
25 # cv2.waitKey()
26 # cv2.destroyAllWindows()
27 
28 
29 def resize(w, h, w_box, h_box, pil_image):
30     f1 = 1.0 * w_box / w  # 1.0 forces float division in Python2
31     f2 = 1.0 * h_box / h
32     factor = min([f1, f2])
33     width = int(w * factor)
34     height = int(h * factor)
35     return pil_image.resize((width, height), Image.ANTIALIAS)
36 
37 root = tk.Tk()
38 # size of image display box you want
39 # 期望图像显示的大小
40 w_box = 800
41 h_box = 1000
42 
43 # 以一个PIL图像对象打开
44 pil_image = Image.open(r'C:/Users/w/PycharmProjects/sift/picture/b.jpg')
45 
46 # get the size of the image
47 # 获取图像的原始大小
48 w, h = pil_image.size
49 
50 # resize the image so it retains its aspect ration
51 # but fits into the specified display box
52 # 缩放图像让它保持比例,同时限制在一个矩形框范围内
53 pil_image_resized = resize(w, h, w_box, h_box, pil_image)
54 
55 # convert PIL image object to Tkinter PhotoImage object
56 # 把PIL图像对象转变为Tkinter的PhotoImage对象
57 tk_image = ImageTk.PhotoImage(pil_image_resized)
58 
59 # put the image on a widget the size of the specified display box
60 # Label: 这个小工具,就是个显示框,小窗口,把图像大小显示到指定的显示框
61 label = tk.Label(root, image=tk_image, width=w_box, height=h_box)
62 # padx,pady是图像与窗口边缘的距离
63 label.pack(padx=5, pady=5)
64 root.mainloop()
SIFT Code

相关文章: