视觉

视觉方向实践-用sift算法特征提取并完成匹配

简易的前端制作

用Qt写一个简单的界面

将ui转化为py

先安装pyqt5

1
pip install pyqt5

用Qt做完ui后,将ui文件转换为py文件

1
pyuic5 -o xxx.py xxx.ui

获得py 文件后 ,在main 文件中写以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import sys
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QObject

from vision_ui import *#引用ui界面

if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)

#初始化一个窗口
widgets = QtWidgets.QMainWindow()
#初始化写好的ui
ui = Ui_MainWindow()
#将ui赋值给窗口
ui.setupUi(widgets)
widgets.show()
sys.exit(app.exec_())

关于槽函数

和qt里面的槽函数 用法基本相同

1
2
3
4
5
6
self.pushButton_SelectPic.clicked.connect(self.ClickOn_SelectPic)

def ClickOn_SelectPic(self):
self.sift.imgname1="".join(QtWidgets.QFileDialog.getOpenFileNames(
None,"选取文件","./", "All Files (*);;Image(*.jpg *.png)"
)[0])

需要引用库

1
from PyQt5 import QtCore, QtGui, QtWidgets

vision_ui.py 的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
import sift

class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1004, 660)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton_SelectPic = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_SelectPic.setGeometry(QtCore.QRect(30, 390, 121, 23))
self.pushButton_SelectPic.setObjectName("pushButton_SelectPic")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(20, 20, 450, 361))
self.textEdit.setObjectName("textEdit")
self.textEdit_2 = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit_2.setGeometry(QtCore.QRect(520, 20, 450, 361))
self.textEdit_2.setObjectName("textEdit_2")
self.pushButton_Sift = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_Sift.setGeometry(QtCore.QRect(30, 420, 121, 23))
self.pushButton_Sift.setObjectName("pushButton_Sift")
self.pushButton_SelectDirectory = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_SelectDirectory.setGeometry(QtCore.QRect(30, 450, 121, 23))
self.pushButton_SelectDirectory.setObjectName("pushButton_SelectDirectory")
self.pushButton_matching = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_matching.setGeometry(QtCore.QRect(30, 480, 121, 23))
self.pushButton_matching.setObjectName("pushButton_matching")
self.label_match = QtWidgets.QLabel(self.centralwidget)
self.label_match.setGeometry(QtCore.QRect(40, 550, 61, 16))
self.label_match.setObjectName("label_match")
self.label_matchtime = QtWidgets.QLabel(self.centralwidget)
self.label_matchtime.setGeometry(QtCore.QRect(100, 550, 81, 16))
self.label_matchtime.setObjectName("label_matchtime")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1004, 23))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)

self.sift=sift.Sift_AI()

self.retranslateUi(MainWindow)

self.pushButton_SelectPic.clicked.connect(self.ClickOn_SelectPic)
self.pushButton_Sift.clicked.connect(self.ClickOn_Sift)
self.pushButton_SelectDirectory.clicked.connect(self.ClickOn_SelectDirectory)
self.pushButton_matching.clicked.connect(self.ClickOn_Matching)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def ClickOn_SelectPic(self):
self.sift.imgname1="".join(QtWidgets.QFileDialog.getOpenFileNames(
None,"选取文件","./", "All Files (*);;Image(*.jpg *.png)"
)[0])
self.textEdit.append("<img src=%s>"%(self.sift.imgname1))
def ClickOn_Sift(self):
self.sift.Sift_feature_transform()
def ClickOn_SelectDirectory(self):
self.sift.DirPath="".join(QtWidgets.QFileDialog.getExistingDirectory(
None,"选取文件夹","./"
))+"/"
print(self.sift.DirPath)
def ClickOn_Matching(self):
self.sift.all_pic=[]
self.sift.get_all_pic(self.sift.DirPath,self.sift.all_pic)
print(self.sift.all_pic)
comparisonImageList=self.sift.sift_fun(self.sift.all_pic)
for i in range(1,4):
cv2.imshow("%d"%i,comparisonImageList[i][0])
self.textEdit_2.append("<img src=%s>"%comparisonImageList[i][2])

def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton_SelectPic.setText(_translate("MainWindow", "选择图片"))
self.pushButton_Sift.setText(_translate("MainWindow", "sift提取特征"))
self.pushButton_SelectDirectory.setText(_translate("MainWindow", "选择待匹配图像目录"))
self.pushButton_matching.setText(_translate("MainWindow", "匹配"))
self.label_match.setText(_translate("MainWindow", "匹配时间:"))
self.label_matchtime.setText(_translate("MainWindow", ""))

生产exe文件

在pycharm终端输入

1
pyinstaller -F -w main.py

sift 算法

sift算法特点

不变性:对旋转和尺度变化具有不变性;对三维视角变化和光照变化具有适应性;局部特征,在遮挡和场景杂乱时保持不变性;

辨别力强:特征之间相互区分的能力强,有利于匹配

数量较多:一般500*500的图像能提取约2000个特征点

流程

•构建尺度空间

•构造高斯差分尺度空间

•DoG尺度空间极值点检测

•特征点精确定位

•去除不稳定点

sift流程

sift.py的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import numpy as np
import cv2
from matplotlib import pyplot as plt
import numpy as np
import os
import math

import glob
class Sift_AI(object):
def __init__(self):
self.imgname1='D:/vision/PY/resources/test/A0C573/A0C573_20151103073308_3029240562.jpg'
self.imgname2='D:/vision/PY/resources/test/A0C573/A0C573_20151103074304_6595543738.jpg'
self.sift=cv2.SIFT_create()
self.time=0
self.DirPath='./'
self.all_pic=[]
self.des1=0
self.kp1=0
self.sampleImage=0
self.FLANN_INDEX_KDTREE = 0
#提取特征值
def Sift_feature_transform(self):
self.sampleImage= cv2.imread(self.imgname1)
gray1 = cv2.cvtColor(self.sampleImage, cv2.COLOR_BGR2GRAY) # 灰度处理图像

self.kp1, self.des1 = self.sift.detectAndCompute(self.sampleImage, None) # kp1是特征点 des是描述子

img_feature = cv2.drawKeypoints(self.sampleImage, self.kp1, self.sampleImage, color=(255, 0, 255)) # 画出特征点,并显示为红色圆圈
cv2.imshow("point",img_feature)
cv2.waitKey(0)

def getMatchNum(self,matches, ratio):
'''返回特征点匹配数量和匹配掩码'''
matchesMask = [[0, 0] for i in range(len(matches))]
matchNum = 0
for i, (m, n) in enumerate(matches):
if m.distance < ratio * n.distance: # 将距离比率小于ratio的匹配点删选出来
matchesMask[i] = [1, 0]
matchNum += 1
return (matchNum, matchesMask)

def get_all_pic(self,path,all_files=[]):
filelist1=sorted(os.listdir(path))
for file1 in filelist1:
if(not os.path.isdir(path+file1)):
if(file1.endswith(('.jpg','jpeg',".png"))):
all_files.append(path+file1)
else:
self.get_all_pic(path+file1+"/",all_files)
#用于匹配最合适的图像
def sift_fun(self,all_P=[]) :
comparisonImageList=[]
indexParams = dict(algorithm=self.FLANN_INDEX_KDTREE, trees=5)
searchParams = dict(checks=50)
flann = cv2.FlannBasedMatcher(indexParams, searchParams)
for p in all_P:
img = cv2.imread(p)
gray2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 灰度处理图像
kp2, des2 = self.sift.detectAndCompute(gray2, None) # des是描述子
matches= flann.knnMatch(self.des1,des2,k=2)#匹配特征点,为了删选匹配点,指定k为2,这样对样本图的每个特征点,返回两个匹配
(matchNum, matchesMask) = self.getMatchNum(matches, 0.9) #通过比率条件,计算出匹配程度
matchRatio = matchNum * 100 / len(matches)
drawParams = dict(matchColor=(0, 255, 0),
singlePointColor=(255, 0, 0),
matchesMask=matchesMask,
flags=0)
comparisonImage = cv2.drawMatchesKnn(self.sampleImage, self.kp1, img, kp2, matches, None, **drawParams)
comparisonImageList.append((comparisonImage, matchRatio,p)) # 记录下结果
comparisonImageList.sort(key=lambda x: x[1], reverse=True)
return comparisonImageList

Surf算法

生成码本

K-means聚类算法流程(调用sklearn库的KMeans方法):

随机初始化 K 个聚类中心

重复下述2个步骤直至算法收敛

对应每个特征,根据距离关系赋值给某个中心/类别

对每个类别,根据其对应的特征集重新计算聚类中心

得到的聚类中心就是视觉词典


视觉
http://example.com/2023/03/03/shi-jue/
作者
CynicCat
发布于
2023年3月3日
许可协议