python opencv特征点检测和匹配教程_flann_index_kdtree_持久决心的博客-程序员宅基地

技术标签: 特征点检测和匹配  python  OpenCV  opencv  SITF  

导入相关的包

import cv2
import numpy as np
import random
import os
import matplotlib.pyplot as plt
from timeit import default_timer as timer

获取图片

# 从图像文件夹中获取所有的图像
imgDir = 'imgs/'
imgFiles = os.listdir(imgDir)

# 随机读取两张图片
imgs = random.sample(imgFiles, 2)
img1 = cv2.imread(os.path.join(imgDir, imgs[0]))
img2 = cv2.imread(os.path.join(imgDir, imgs[1]))

# 由于需要在plt下显示图像,需要将opencv中BGR的顺序改为RGB
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)

# 转换为灰度图
gray1 = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_RGB2GRAY)

plt.subplot(2,2,1)
plt.imshow(img1)

plt.subplot(2,2,2)
plt.imshow(img2)

plt.subplot(2,2,3)
plt.imshow(gray1, cmap='gray')

plt.subplot(2,2,4)
plt.imshow(gray2, cmap='gray')

plt.show()

output_3_0.png

计算特征点和描述子

# 初始化检测算子
sift = cv2.xfeatures2d_SIFT.create()

# 计算特征点和描述子
kps1, des1 = sift.detectAndCompute(gray1, None)
kps2, des2 = sift.detectAndCompute(gray2, None)

# 展示描述子
img1Show = cv2.drawKeypoints(gray1, kps1, img1)
img2Show = cv2.drawKeypoints(gray2, kps2, img2)

plt.subplot(1,2,1)
plt.imshow(img1Show)

plt.subplot(1,2,2)
plt.imshow(img2Show)

plt.show()

print(f'kps1[0]:\n{kps1[0]}')
print(f'des1[0]:\n{des1[0]}')

output_5_0.png

kps1[0]:
<KeyPoint 0x7f29c8455e70>
des1[0]:
[  0.   5.   7.   0.   0.   0.   0.   0.   1.   0.   0.   1.   2.   0.
   0.   0.   4.   0.   0.   0.   0.   0.   0.   1.   0.   0.   0.   0.
   0.   0.   0.   0.  37. 124.  98.   6.   2.   0.   0.   4.  64.  20.
   5.   9.  24.  12.   7.  12. 136.  53.  10.   1.   2.   2.   2.  34.
  26.  28.  25.   1.   3.   5.   4.   8. 136.  60.  22.   4.   1.   1.
   4.  96.  86.  10.   1.   6.  10.  53.  52.  65. 136. 136.  60.   2.
   1.  10.  16.  18.   8. 136. 136.   1.   1.   1.   4.   4. 136.   2.
   1.   6.   4.   0.   1. 107.  55.   4.   8.  61.  33.   8.   7.  54.
  24.  12.   9.   8.   1.  14. 113. 104.   1.  24.  20.   0.   0.  34.
  97.  11.]

使用BF暴力匹配

参考资料:https://docs.opencv.org/3.3.0/dc/dc3/tutorial_py_matcher.html

Basics of Brute-Force Matcher

Brute-Force Matcher将第一个集合的描述一个向量与第二个集合的所有向量进行匹配,计算出他们之间的“距离”。最后返回最近的一个。
首先使用cv2.BFMatcher()创建对象。该函数接受两个参数。第一个参数确定距离的计算方式。默认情况下是cv2.NORM_L2,这一方式适用于SIFT、SURF(cv2.NORM_L1也适用)。对于基于 binary string的方法,如ORB,BREIF,BRISK等等,cv2.NORM_HAMMING计算方式是适用的。如果 ORB 适用 WTA_K == 3 or 4, 则应该使用cv2.NORM_HAMMING2。
第二个参数是一个bool值,默认为false。如果设置为True,匹配结果返回的将是(i,j),即集合A的第i个描述向量对应B中第j个描述向量。

bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)

# 如果A中某个点与B中最近相近的2个点的距离区分度足够大,则是好的匹配
good = []
for m, n in matches:
    if m.distance < 0.75 * n.distance:
        good.append([m])

imgMatch = cv2.drawMatchesKnn(img1,kps1,img2,kps2,good,None,flags=2)

plt.imshow(imgMatch)
plt.show()

output_7_0.png

基于FLANN的匹配方法

FLANN指的是Fast Library for Approximate Nearest Neighbors。在大规模数据和高维数据中速度比BF算法快。
对于SIFT,SURF等算法,参数设置为:
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)

对于ORB,参数设置为:
FLANN_INDEX_LSH = 6
index_params= dict(algorithm = FLANN_INDEX_LSH,
table_number = 6, # 12
key_size = 12, # 20
multi_probe_level = 1) #2

FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)   # or pass empty dictionary

flann = cv2.FlannBasedMatcher(index_params,search_params)

matches = flann.knnMatch(des1,des2,k=2)
# Need to draw only good matches, so create a mask
matchesMask = [[0,0] for i in range(len(matches))]
# ratio test as per Lowe's paper
for i,(m,n) in enumerate(matches):
    if m.distance < 0.7*n.distance:
        matchesMask[i]=[1,0]

draw_params = dict(matchColor = (0,255,0),
                   singlePointColor = (255,0,0),
                   matchesMask = matchesMask,
                   flags = 0)

img3 = cv2.drawMatchesKnn(img1,kps1,img2,kps2,matches,None,**draw_params)
plt.imshow(img3)
plt.show()

output_9_0.png

使用RANSAC提出误匹配

TODO

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u013832707/article/details/96975203

智能推荐

HTML5日期输入类型(date)_html5 date-程序员宅基地

HTML5让Web程序员的工作变得异常简单,我们得到的不仅仅只有一个“日期”类型的input,还有一系列相关的日期、时间参数让我们自定义。我们虽然称之为“日期”类型,但这里的type实际上是可以为“date”、“week”、“month”、“time”、“datetime”和“datetime-local”。下面我将用实例加图文的方式向大家演示各种type的外观表现。1. 日期()_html5 date

执行jmeter_server.bat时出现‘findstr‘ 不是内部或外部命令,也不是可运行的程序或批处理文件_findstr' 不是内部或外部命令,也不是可运行的程序 winserver2008-程序员宅基地

打开cmd,执行命令findstr /?说明C:\Windows\System32\findstr.exe未生效,因安装极少数软件,导致path值被篡改检查环境变量里的path加上%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\如果还是不行,环境变量path中再加上C:\windows\system32亲测有效..._findstr' 不是内部或外部命令,也不是可运行的程序 winserver2008

linux c++操作mysql数据库_Linux下C++连MySQL数据库-程序员宅基地

1.查看本地有没有安装mysql,命令就是mysql,如果有这个命令就表示安装了mysql数据库软件。如果没有就自行安装。MySQL-server-4.0.16-0.i386.rpmMySQL-client-4.0.16-0.i386.rpm2.查看本地有没有安装mysql的开发包。命令是 `mysql_config--cflags --libs` 如果有安装就会有一串编译选项和连接库。如果没有就..._mysql lib linux c++

DispSync 分析-程序员宅基地

在SurfaceFlinger的构造方法中调用了DispSync的init方法对DispSync进行初始化,mPrimaryDispSync.init(hasSyncFramework, dispSyncPresentTimeOffset);调用流程图如下,DispSync的构造方法如下,DispSync::DispSync(const char* name) : mName(name),..._dispsync

ExtJS用Grid显示数据后如何自动选取第一条记录-程序员宅基地

用Grid显示数据后,如何让系统自动选取第一条记录呢?在显示Grid时由于其Store正在loading,没法在Grid选取第一条记录,因为还没有记录,所以应在其Store进行操作。查看Ext.data.Store的load()方法如下:load( [options] )Loads data into the Store via the configured proxy

随便推点

废弃原因-程序员宅基地

主要原因 as follows : 1、注册版wordPress连rar都不让上传,十分尴尬,劳动成果没有地方放。 2、WordPress不是专业程序员论坛,高手并不多,看的人就不用提了,少得可怜。 3、也应该换一个简单、朴素、功能强大(并不是WordPress功能不强)、较专业、环保的blog用下了。 4、特别喜欢之处在于,..._marquee被遗弃原因

arrayfire的工程创建例子_arrayfire如何编译-程序员宅基地

首先介绍如何操作以下内容:(推荐) 如果需要移动项目执行需要设定:1.设定AF_PATH 环境变量. 通常指定要连接的 ArrayFire headers和 libraries (libaf.lib, libafGFX.lib).2.添加 ArrayFire DLLs 到PATH 环境变量a.Win64: %AF_PATH%/examples/bin_x64b.Win32:_arrayfire如何编译

ListView动态更新item的例子-程序员宅基地

1.ListViewUpdate.java文件:[code="java"]package com.example;import java.util.Random;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.On...

Oracle字符集的设置_oracle数据库字符集怎么设置-程序员宅基地

文章目录一、字符集的概念1、字符编码(character encoding):2、字符集(Character set)3、国际编码(Unicode)4、汉字的编码5、汉字的编码选择6、编码的转换二、Oracle的字符集1、字符集和国家字符集2、支持中文的字符集3、NLS_LANG参数三、服务端的字符集1、查看服务端字符集2、修改服务端字符集四、客户端的字符集1、Linux环境2、Windows环境..._oracle数据库字符集怎么设置

python2和python3中TestSuite().addTest的区别-程序员宅基地

Python2中unittest.TestSuite().addTest()的参数是这样的:unittest.TestSuite().addTest(TestFun("test_nam"));其中TestFun是继承于TestCase的类,test_name是里面的测试函数。然后运行传list当参数: name_list=[TestFun("test_nam01"...

python实现概率统计_机器学习中的概率统计:Python语言描述-程序员宅基地

机器学习中的概率统计:Python语言描述作者:张雨萌 著出版日期:2020年12月文件大小:19.93M支持设备:¥50.00在线试读适用客户端:言商书局iPad/iPhone客户端:下载 Android客户端:下载PC客户端:下载更多详情:查看?对图书下载、阅读卡购买有疑问:立即进入帮助中心>>图书简介目录本书围绕机器学习算法中涉及的概率统计知识展开介绍,沿着概率思想、变量分布、参..._概率统计融合python