视觉SLAM学习【6】—–基于python的SIFT和ORB特征点提取及匹配的对比探索

177
0
2021年1月19日 09时22分

视觉SLAM学习【6】—–基于python的SIFT和ORB特征点提取及匹配的对比探索目录

 

  • 一、python终端安装需要的图像处理库
    • 1、打开终端,安装opencv-python
    • 2、如果之前安装其他版本操作步骤
    • 3、准备图片数据
  • 二、SIFT特征提取及匹配
    • 1、导入需要的python库
    • 2、导入图片
    • 3、构建仿射图
    • 4、将img转换为RGB格式,避免色差
    • 5、SIFT特征提取及提取时间计算
    • 6、SIFT特征匹配
  • 三、ORB特征提取及匹配
    • 1、导入图片
    • 2、构建仿射图
    • 3、将img转换为RGB格式,避免色差
    • 4、ORB特征提取及提取时间计算
    • 5、ORB特征匹配
  • 四、SIFT及ORB特征提取及匹配分析
    • 1、提取时间分析
    • 2、提取特征点分析

 

在进行嵌入式开发的过程中,对于图像特征点的提取及匹配一直是一个重点问题,之前我们通过C++进行对应的orb特征点的匹配提取,本次博客,林君学长将带大家了解如何通过python实现SIFT和ORB两钟方法的特征点提取,理解sift 和orb在尺度缩放、旋转、仿射图上面的特征不变性,并进行两种提取方法的速度比较,一起来看吧!

一、python终端安装需要的图像处理库

 

1、打开终端,安装opencv-python

 

1)、安装opencv-python库

 

pip install --user opencv-python==3.4.2.16

 

在这里插入图片描述

2)、安装opencv-contrib-python库

 

pip install --user opencv-contrib-python==3.4.2.16

 

在这里插入图片描述

 

由于林君学长已经下载,上面出现的界面是下载好了的

 

2、如果之前安装其他版本操作步骤

 

由于sift的特征提取及匹配需要用的opencv-python版本需要的是低版本,而之前我们默认安装的是最新版本的opencv-python,所以我们需要卸载后重新安装,具体步骤如下所示:

 

1)、卸载opencv-contrib-python及opencv-python库

 

pip uninstall opencv-contrib-python
pip uninstall opencv-python

 

2)、重新安装opencv-contrib-python及opencv-python库

 

pip install --user opencv-python==3.4.2.16
pip install --user opencv-contrib-python==3.4.2.16

 

3、准备图片数据

 

1)、需要选择一张原图

 

在这里插入图片描述

 

2)、对原图进行旋转

 

在这里插入图片描述

 

3)、对原图进行缩略

 

在这里插入图片描述

 

4)、原图变换为仿射图

 

对于仿射图的变换,林君学长后面会给出代码,这里给出仿射图的结果展示:

 

在这里插入图片描述

 

以上的图片制作比较简单,可以用windows自带的画图板进行修改得到,这里就不讲解制作过程了!

 

在一切准备妥当之后,我们就可以开始特征点提取和匹配了哦!

二、SIFT特征提取及匹配

 

1、导入需要的python库

 

import numpy as np
import cv2
from matplotlib import pyplot as plt
import time
%matplotlib inline

 

以上导入库的功能相对简单,林君学长这里就不给出具体介绍了

 

2、导入图片

 

读取原图、旋转图、缩略图

 

img1 = cv2.imread('D:/image/1.jpg')#读取原图片
img2 = cv2.imread('D:/image/2.jpg')#读取旋转图片
img3 = cv2.imread('D:/image/3.jpg')#读取缩放图片

 

3、构建仿射图

 

#构建放射图
img = cv2.imread('D:/image/1.jpg')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
rows, cols, ch = img.shape
pts1 = np.float32([[0, 0], [cols - 1, 0], [0, rows - 1]])
pts2 = np.float32([[cols * 0.2, rows * 0.1], [cols * 0.9, rows * 0.2], [cols * 0.1, rows * 0.9]])
M = cv2.getAffineTransform(pts1, pts2)
dst = cv2.warpAffine(img, M, (cols, rows))

 

放射图主要通过代码生成,以上dst就为仿射图,显示可通过传递dst参数便可以显示

 

4、将img转换为RGB格式,避免色差

 

#使用cv2.imread()接口读图像,读进来的是BGR格式以及[0~255]。所以要将img转换为RGB格式,不然后面显示会有色差
img1 = cv2.cvtColor(img1,cv2.COLOR_BGR2RGB)
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) #灰度处理图像
img2 = cv2.cvtColor(img2,cv2.COLOR_BGR2RGB)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
img3 = cv2.cvtColor(img3,cv2.COLOR_BGR2RGB)
gray3 = cv2.cvtColor(img3, cv2.COLOR_BGR2GRAY)
img4 = cv2.cvtColor(dst,cv2.COLOR_BGR2RGB)
gray4 = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)

 

5、SIFT特征提取及提取时间计算

 

1)、SIFT对四张图片的特征提取及提取时间计算

 

#sift 特征提取
a=time.time()
sift1 = cv2.xfeatures2d.SIFT_create()
kp1, des1 = sift1.detectAndCompute(img1,None)
kp2, des2 = sift1.detectAndCompute(img2,None)
kp3, des3 = sift1.detectAndCompute(img3,None)
kp4, des4 = sift1.detectAndCompute(img4,None)
b=time.time()
print("sift提取时间为:",b-a)

 

在这里插入图片描述

 

2)、SIFT对于原图片的特征提取展示

 

img11 = cv2.drawKeypoints(img1,kp1,img1,color=(255,0,255))
plt.figure(num=1,figsize=(16,16))
plt.imshow(img11)
plt.title('Left:yuan---Right:yuan')
plt.axis('off')
plt.show()

 

在这里插入图片描述

 

3)、SIFT对于旋转图片的特征提取展示

 

img12 = cv2.drawKeypoints(img2,kp2,img2,color=(255,0,255))
plt.figure(num=1,figsize=(16,16))
plt.imshow(img12)
plt.title('Left:yuan---Right:xuanzhuan')
plt.axis('off')
plt.show()

 

在这里插入图片描述

 

4)、SIFT对于缩略图的特征提取展示

 

img13 = cv2.drawKeypoints(img3,kp3,img3,color=(255,0,255))
plt.figure(num=1,figsize=(16,16))
plt.imshow(img13)
plt.title('Left:yuan---Right:suolue')
plt.axis('off')
plt.show()

 

在这里插入图片描述

 

5)、SIFT对于仿射图的特征提取展示

 

img14 = cv2.drawKeypoints(img4,kp4,img4,color=(255,0,255))
plt.figure(num=1,figsize=(16,16))
plt.imshow(img14)
plt.title('Left:yuan---Right:fangshe')
plt.axis('off')
plt.show()

 

在这里插入图片描述

6、SIFT特征匹配

 

1)、FLANN 参数设计

 

# FLANN 参数设计
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params,search_params)

 

2)、SIFT对于原图片与原图片的特征匹配

 

#原图与原图的匹配连线效果图展示
matches = flann.knnMatch(des1,des1,k=2)
matchesMask = [[0,0] for i in range(len(matches))]
good = []
for m,n in matches:
    if m.distance < 0.7*n.distance:
        good.append([m])
img41 = cv2.drawMatchesKnn(img1,kp1,img1,kp1,good,None,flags=2)
plt.figure(num=1,figsize=(16,16))
plt.imshow(img41)
plt.title('Left:yuan---Right:yuan')
plt.axis('off')
plt.show()

 

在这里插入图片描述

 

3)、SIFT对于原图片与旋转图片的特征匹配

 

#原图与旋转图的匹配连线效果图展示
matches = flann.knnMatch(des1,des2,k=2)
matchesMask = [[0,0] for i in range(len(matches))]
good = []
for m,n in matches:
    if m.distance < 0.7*n.distance:
        good.append([m])
img42 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2)
plt.figure(num=1,figsize=(16,16))
plt.imshow(img42)
plt.title('Left:yuan---Right:xuanzhuan')
plt.axis('off')
plt.show()

 

在这里插入图片描述

 

4)、SIFT对于原图片与缩略图的特征匹配

 

#原图与缩略图的匹配连线效果图展示
matches = flann.knnMatch(des1,des3,k=2)
matchesMask = [[0,0] for i in range(len(matches))]
good = []
for m,n in matches:
    if m.distance < 0.7*n.distance:
        good.append([m])
img43 = cv2.drawMatchesKnn(img1,kp1,img3,kp3,good,None,flags=2)
plt.figure(num=1,figsize=(16,16))
plt.imshow(img43)
plt.title('Left:yuan---Right:suolue')
plt.axis('off')
plt.show()

 

在这里插入图片描述

 

5)、SIFT对于原图片与仿射图的特征匹配

 

#原图与放射图的匹配结果显示
matches = flann.knnMatch(des1,des4,k=2)
matchesMask = [[0,0] for i in range(len(matches))]
good = []
for m,n in matches:
    if m.distance < 0.7*n.distance:
        good.append([m])
img44 = cv2.drawMatchesKnn(img1,kp1,img4,kp4,good,None,flags=2)
plt.figure(num=1,figsize=(16,16))
plt.imshow(img44)
plt.title('Left:yuan---Right:fangshe')
plt.axis('off')
plt.show()

 

在这里插入图片描述

以上就是SIFT的体征提取及匹配啦,可以看到,SIFT的特征点提取的还是非常多的,接下来我们看那一下ORB特征点的提取及匹配并做一定的对比

三、ORB特征提取及匹配

 

1、导入图片

 

img10 = cv2.imread('D:/image/1.jpg')#读取原图片
img20 = cv2.imread('D:/image/2.jpg')#读取旋转图片
img30 = cv2.imread('D:/image/3.jpg')#读取缩放图片

 

2、构建仿射图

 

通过原图片构建缩略图

 

#构建放射图
img = cv2.imread('D:/image/1.jpg')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
rows, cols, ch = img.shape
pts1 = np.float32([[0, 0], [cols - 1, 0], [0, rows - 1]])
pts2 = np.float32([[cols * 0.2, rows * 0.1], [cols * 0.9, rows * 0.2], [cols * 0.1, rows * 0.9]])
M = cv2.getAffineTransform(pts1, pts2)
dst = cv2.warpAffine(img, M, (cols, rows))

 

其中dst即为我们需要的仿射图

 

3、将img转换为RGB格式,避免色差

 

#使用cv2.imread()接口读图像,读进来的是BGR格式以及[0~255]。所以要将img转换为RGB格式,不然后面显示会有色差
img1 = cv2.cvtColor(img10,cv2.COLOR_BGR2RGB)
gray1 = cv2.cvtColor(img10, cv2.COLOR_BGR2GRAY) #灰度处理图像
img2 = cv2.cvtColor(img20,cv2.COLOR_BGR2RGB)
gray2 = cv2.cvtColor(img20, cv2.COLOR_BGR2GRAY)
img3 = cv2.cvtColor(img30,cv2.COLOR_BGR2RGB)
gray3 = cv2.cvtColor(img30, cv2.COLOR_BGR2GRAY)
img4 = cv2.cvtColor(dst,cv2.COLOR_BGR2RGB)
gray4 = cv2.cvtColor(dst,cv2.COLOR_BGR2GRAY)

 

4、ORB特征提取及提取时间计算

 

1)、ORB特征提取及提取时间计算

 

#ORB 特征提取
a=time.time()
sift2 = cv2.ORB_create()
kp1, des1 = sift2.detectAndCompute(img1,None)
kp2, des2 = sift2.detectAndCompute(img2,None)
kp3, des3 = sift2.detectAndCompute(img3,None)
kp4, des4 = sift2.detectAndCompute(img4,None)
b=time.time()
print("ORB提取时间为:",b-a)

 

在这里插入图片描述

 

2)、ORB对于原图片的特征提取

 

img11 = cv2.drawKeypoints(img1,kp1,img1,color=(255,0,255))
plt.figure(num=1,figsize=(16,16))
plt.imshow(img11)
plt.title('Left:yuan---Right:yuan')
plt.axis('off')
plt.show()

 

在这里插入图片描述

 

3)、ORB对于旋转图片的特征提取

 

img12 = cv2.drawKeypoints(img2,kp2,img2,color=(255,0,255))
plt.figure(num=1,figsize=(16,16))
plt.imshow(img12)
plt.title('Left:yuan---Right:xuanzhuan')
plt.axis('off')
plt.show()

 

在这里插入图片描述

 

4)、ORB对于缩略图的特征提取

 

img13 = cv2.drawKeypoints(img3,kp3,img3,color=(255,0,255))
plt.figure(num=1,figsize=(16,16))
plt.imshow(img13)
plt.title('Left:yuan---Right:suolue')
plt.axis('off')
plt.show()

 

在这里插入图片描述

 

5)、ORB对于仿射图的特征提取

 

img14 = cv2.drawKeypoints(img4,kp4,img4,color=(255,0,255))
plt.figure(num=1,figsize=(16,16))
plt.imshow(img14)
plt.title('Left:yuan---Right:fangshe')
plt.axis('off')
plt.show()

 

在这里插入图片描述

5、ORB特征匹配

 

1)、ORB对于原图片与原图片的特征匹配

 

#原图与原图的匹配连线效果图展示
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True) # orb的normType应该使用NORM_HAMMING
matches = bf.match(des1, des1)
matches = sorted(matches, key=lambda x: x.distance)
knnMatches = bf.knnMatch(des1, des1, k = 1) # drawMatchesKnn
for m in matches:
    for n in matches:
        if(m != n and m.distance >= n.distance*0.75):
            matches.remove(m)
            break
img = cv2.drawMatches(img1, kp1, img1, kp1, matches[:50], img1, flags=2)
plt.figure(num=1,figsize=(16,16))
plt.imshow(img)
plt.title('Left:yuan---Right:yuan')
plt.axis('off')
plt.show()

 

在这里插入图片描述

 

2)、ORB对于原图片与旋转图片的特征匹配

 

#原图与旋转图的匹配连线效果图展示
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True) # orb的normType应该使用NORM_HAMMING
matches = bf.match(des1, des2)
matches = sorted(matches, key=lambda x: x.distance)
knnMatches = bf.knnMatch(des1, des2, k = 1) # drawMatchesKnn
for m in matches:
    for n in matches:
        if(m != n and m.distance >= n.distance*0.75):
            matches.remove(m)
            break
img = cv2.drawMatches(img1, kp1, img2, kp2, matches[:50], img2, flags=2)
plt.figure(num=1,figsize=(16,16))
plt.imshow(img)
plt.title('Left:yuan---Right:xuanzhuan')
plt.axis('off')
plt.show()

 

在这里插入图片描述

 

3)、ORB对于原图片与缩略图的特征匹配

 

#原图与缩略图的匹配连线效果图展示
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True) # orb的normType应该使用NORM_HAMMING
matches = bf.match(des1, des3)
matches = sorted(matches, key=lambda x: x.distance)
knnMatches = bf.knnMatch(des1, des3, k = 1) # drawMatchesKnn
for m in matches:
    for n in matches:
        if(m != n and m.distance >= n.distance*0.75):
            matches.remove(m)
            break
img = cv2.drawMatches(img1, kp1, img3, kp3, matches[:50], img3, flags=2)
plt.figure(num=1,figsize=(16,16))
plt.imshow(img)
plt.title('Left:yuan---Right:suolue')
plt.axis('off')
plt.show()

 

在这里插入图片描述

 

4)、ORB对于原图片与射图的特征匹配

 

#原图与仿射图的匹配连线效果图展示
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck = True) # orb的normType应该使用NORM_HAMMING
matches = bf.match(des1, des4)
matches = sorted(matches, key=lambda x: x.distance)
knnMatches = bf.knnMatch(des1, des4, k = 1) # drawMatchesKnn
for m in matches:
    for n in matches:
        if(m != n and m.distance >= n.distance*0.75):
            matches.remove(m)
            break
img = cv2.drawMatches(img1, kp1, img4, kp4, matches[:50], img4, flags=2)
plt.figure(num=1,figsize=(16,16))
plt.imshow(img)
plt.title('Left:yuan---Right:fangshe')
plt.axis('off')
plt.show()

 

在这里插入图片描述

四、SIFT及ORB特征提取及匹配分析

 

1、提取时间分析

 

两种方法的提取时间如下所示:

 

1)、SIFT提取时间

在这里插入图片描述

 

2)、ORB提取时间

在这里插入图片描述

 

从提取时间上来看ORB的提取时间很短,大约是SIFT提取方法的十分之一,这也是ORB特征提取方法的优越性,同时,ORB在尺度缩放、旋转、仿射上的特征点不变,具有不变性

2、提取特征点分析

 

1)、SIFT提取点提取

 

在这里插入图片描述

 

2)、ORB提取点提取

 

在这里插入图片描述

 

从特征点提取特征来看,SIFT提取的特征点非常多,趋近于实物,准确性非常高,这也是SIFT提取方法的优越性,同时,SIFT在尺度缩放、旋转、仿射上的特征点不变,具有不变性!

 

以上就是本次博客的全部内容啦,希望小伙伴们对本次博客的阅读可以帮助大家理解python中,如何进行sfit及orb特征点提取及匹配,了解在尺度缩放、旋转、仿射上的特征点不变原则!

 


遇到问题的小伙伴记得评论区留言,林君学长看到会为大家解答的,这个学长不太冷!

陈一月的又一天编程岁月^ _ ^

发表评论

后才能评论