• FLANN - Fast Library for Approximate Nearest Neighbors FLANN is a library for performing fast approximate nearest neighbor searches in high dimensional spaces. It contains a collection of algorithms ...
• 使用佩奇图像对Brute-force匹配器及Flann匹配器进行说明。


文章目录
1 测试图像1.1 peiqi.png1.2 peiqi_in_img.png
2 Brute-force2.1 使用Orb描述符2.2 使用SIFT描述器
3 Flann

1 测试图像
1.1 peiqi.png

1.2 peiqi_in_img.png

2 Brute-force
暴力匹配使用第一组中一个特征的描述符，并使用一些距离计算将其与第二组中的所有其他特征进行匹配，并返回最近的一个。
2.1 使用Orb描述符
import numpy as np
import cv2 as cv

def test(target_path, match_path):
orb = cv.ORB_create()
kp_target, des_target = orb.detectAndCompute(img_target, None)
kp_match, des_match = orb.detectAndCompute(img_match, None)
bf = cv.BFMatcher(cv.NORM_HAMMING, crossCheck=True)
matches = bf.match(des_target, des_target)
matches = sorted(matches, key=lambda x: x.distance)
img_draw = cv.drawMatches(img_target, kp_target, img_match, kp_match, matches[:10], None,
flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
img_draw = cv.resize(img_draw, None, fx=0.5, fy=0.5)
cv.imshow("", img_draw)
cv.waitKey()

if __name__ == '__main__':
test("peiqi.png", "peiqi_in_img.png")

输出如下：
2.2 使用SIFT描述器
import numpy as np
import cv2 as cv

def test(target_path, match_path):
sift = cv.SIFT_create()
kp_target, des_target = sift.detectAndCompute(img_target, None)
kp_match, des_match = sift.detectAndCompute(img_match, None)
bf = cv.BFMatcher()
matches = bf.knnMatch(des_target, des_match, k=2)
good = []
for m, n in matches:
if m.distance < 0.75 * n.distance:
good.append([m])
img_draw = cv.drawMatchesKnn(img_target, kp_target, img_match, kp_match, good, None,
flags=cv.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
img_draw = cv.resize(img_draw, None, fx=0.5, fy=0.5)
cv.imshow("", img_draw)
cv.waitKey()

if __name__ == '__main__':
test("peiqi.png", "peiqi_in_img.png")

输出如下：
3 Flann
对于大型数据集，Flann的速度快于Brute-force：
import cv2 as cv

def test(target_path, match_path):
sift = cv.SIFT_create()
kp_target, des_target = sift.detectAndCompute(img_target, None)
kp_match, des_match = sift.detectAndCompute(img_match, None)
idx_params = dict(algorithm=1, trees=5)
search_params = dict(checks=50)  # search_params = {}
flann = cv.FlannBasedMatcher(idx_params, search_params)
matches = flann.knnMatch(des_target, des_match, k=2)
matches_mask = [[0, 0] for i in range(len(matches))]
for i, (m, n) in enumerate(matches):
if m.distance < 0.7 * n.distance:
draw_params = dict(matchColor=(0, 255, 0),
singlePointColor=(255, 0, 0),
flags=cv.DrawMatchesFlags_DEFAULT)
img_draw = cv.drawMatchesKnn(img_target, kp_target, img_match, kp_match, matches, None, **draw_params)
img_draw = cv.resize(img_draw, None, fx=0.5, fy=0.5)
cv.imshow("", img_draw)
cv.waitKey()

if __name__ == '__main__':
test("peiqi.png", "peiqi_in_img.png")

输出如下：

参考文献 【1】Opencv中文文档。
展开全文
• 四、FLANN匹配 相对暴力匹配BFMatcher来讲，FLANN匹配算法比较准确、快速和使用方便。FLANN具有一种内部机制，可以根据数据本身选择最合适的算法来处理数据集。值得注意的是，FLANN匹配器只能使用SURF和SIFT算法来...


文章目录
一、单应性矩阵二、FLANN匹配2.1 FLANN介绍2.2 FLANN的单应性匹配2.3 FLANN特征保存与匹配保存图片的特征数据加载图片的特征数据，对需要匹配的数据集进行匹配图片模板与批量寻找

一、单应性矩阵
OpenCV在通过特征描述子完成描述子匹配之后，会得到一些关键点对，我们会把这些关键点对分别添加到两个vector对象中，作为输入参数，调用单应性矩阵发现函数来发现一个变换矩阵H，函数 findHomography 就完成了这样的功能，有了变换矩阵H之后，我们就可以根据输入图像四点坐标，从场景图像上得到特征匹配图像的四点坐标。 调用单应性矩阵发现函数 findHomography
Mat cv::findHomography       (
InputArray  srcPoints,              //特征点集合，一般是来自目标图像
InputArray  dstPoints,              //特征点集合，一般是来自场景图像
int   method = 0,                   //配准方法，支持有四种方法
/*
0 – 使用所有的点，比如最小二乘
RANSAC – 基于随机样本一致性
LMEDS – 最小中值
RHO –基于渐近样本一致性
*/
double ransacReprojThreshold = 3,
const int  maxIters = 2000,         //最大迭代次数，当使用RANSAC方法
const double confidence = 0.995     //置信参数，默认为0.995
)

最小二乘方法在描述子匹配输出的点对质量很好，理想情况下是图像没有噪声污染与像素迁移与光线恒定，但是实际情况下图像特别容易受到光线、噪声导致像素迁移，从而产生额外的多余描述子匹配，这些点对可以分为outlier跟inlier两类。
RANSAC（Random Sample Consensus）可以很好的过滤掉outlier点对，使用合法的点对得到最终的变换矩阵H，基本思想是，它会从给定的数据中随机选取一部分进行模型参数计算，然后使用全部点对进行计算结果评价，不断迭代，直到选取的数据计算出来的错误是最小，比如低于0.5%即可。 注意有时候RANSAC方法不会收敛，导致图像对齐或者配准失败，原因在于RANSAC是一种全随机的数据选取方式，完全没有考虑到数据质量不同。

算法流程步骤如下：

1 选择求解模型要求的最少要求的随机点对
2 根据选择随机点对求解/拟合模型得到参数
3 根据模型参数，对所有点对做评估，分为outlier跟inlier
4 如果所有inlier的数目超过预定义的阈值，则使用所有inlier重新评估模型参数，停止迭代
5 如果不符合条件则继续1~4循环。

PROSAC(Progressive Sampling Consensus)（RANSAC算法的改进算法）即渐近样本一致性，该方法采用半随机方法，对所有点对进行质量评价计算Q值，然后根据Q值降序排列，每次只在高质量点对中经验模型假设与验证，这样就大大降低了计算量，在RANSAC无法收敛的情况下，PROSAC依然可以取得良好的结果。OpenCV中的RHO方法就是基于PROSAC估算。
LMEDS最小中值方法拟合，该方法可以看成是最小二乘法的改进，原因在于计算机视觉的输入数据是图像，一般都是各自噪声，这种情况下最小二乘往往无法正确拟合数据，所以采用最小中值方法可以更好实现拟合，排除outlier数据。但是它是对高斯噪声敏感算法。

它的最主要步骤描述如下：

1 随机选取很多个子集从整个数据集中
2 根据各个子集数据计算参数模型
3 使用计算出来的参数对整个数据集计算中值平方残差
4 最终最小残差所对应的参数即为拟合参数。

二、FLANN匹配
在上篇文章中介绍了暴力匹配BFMatcher，相对暴力匹配BFMatcher来讲，FLANN匹配算法比较准确、快速和使用方便。FLANN具有一种内部机制，可以根据数据本身选择最合适的算法来处理数据集。值得注意的是，FLANN匹配器只能使用SURF和SIFT算法来检测角点。
2.1 FLANN介绍
FLANN (Fast_Library_for_Approximate_Nearest_Neighbors)快速最近邻搜索包。 它是一个对大数据集和高维特征进行最近邻搜索的算法的集合,而且这些算法都已经被优化过了。在面对大数据集时它的效果要好于 BFMatcher。
indexparams = dict(algorithm =FLANN_INDEX_KDTREE, trees = 5)  searchparams = dict(checks = 100) 指定递归遍历的次数checks 。值越高结果越准确, 但是消耗的时间也越多。
首先我们定义一个需要查询的图像，在其中找到一些特征点(关键点)，然后再在另一幅图像中也找到了一些特征点，最后对这两幅图像之间的特征点进行匹配。
整个匹配过程如下：
使用 calib3d 模块中的 cv2.findHomography() 函数。如果将这两幅图像中的特征点集传给这个函数,他就会找到这个对象的透视图变换。然后就可以使用函数cv2.perspectiveTransform() 找到这个对象了。至少要 4 个正确的点才能找到这种变换。  在匹配过程可能会有一些错误，而这些错误会影响最终结果。为了解决这个问题,算法使用 RANSAC 和 LEAST_MEDIAN(可以通过参数来设定)。 好的匹配提供的正确的估计被称为 inliers，剩下的被称为outliers。cv2.findHomography() 返回一个掩模,这个掩模确定了 inlier 和outlier 点。
用比值判别法（ratio test）删除离群点： 检测出的匹配点可能有一些是错误正例（false positives）。 以为这里使用过的kNN匹配的k值为2（在训练集中找两个点），第一个匹配的是最近邻，第二个匹配的是次近邻。直觉上，一个正确的匹配会更接近第一个邻居。 换句话说，一个不正确的匹配，两个邻居的距离是相似的。因此，我们可以通过查看二者距离的不同来评判距匹配程度的好坏。比值检测认为第一个匹配和第二个匹配的比值小于一个给定的值（一般是0.5），这里是0.7。
FLANN实现方式如下：
import cv2
from matplotlib import pyplot as plt

def FLANN():

# 使用SIFT 或 SURF 检测角点
sift = cv2.xfeatures2d.SIFT_create()
kp1, des1 = sift.detectAndCompute(queryImage,None)
kp2, des2 = sift.detectAndCompute(trainingImage,None)

# 设置FLANN匹配器参数，定义FLANN匹配器，使用 KNN 算法实现匹配
indexParams = dict(algorithm=0, trees=5)
searchParams = dict(checks=50)

flann = cv2.FlannBasedMatcher(indexParams,searchParams)
matches = flann.knnMatch(des1,des2,k=2)

matchesMask = [[0,0] for i in range(len(matches))]

# 去除错误匹配
for i,(m,n) in enumerate(matches):
if m.distance < 0.7*n.distance:

# 将图像显示
# singlePointColor是勾画关键点
drawParams = dict(matchColor = (0,255,0),
singlePointColor = (255,0,0),
flags = 0)
resultImage = cv2.drawMatchesKnn(queryImage,kp1,trainingImage,kp2,matches[:50],None,**drawParams)
return resultImage

if __name__ == '__main__':
resultImage = FLANN()
plt.imshow(resultImage)
plt.show()
# 分别测试了两张图，后一张图限定绘制连接线。


2.2 FLANN的单应性匹配
单应性是一个条件，该条件表面当两幅图像中的一副出像投影畸变时，他们还能匹配。 实现代码如下：
import cv2
import numpy as np
from matplotlib import pyplot as plt

def FLANN_MIN_MATCH_COUNT():
MIN_MATCH_COUNT = 10

sift = cv2.xfeatures2d.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

index_params = dict(algorithm = 1, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1,des2,k=2)

good = []
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)

# 单应性
if len(good)>MIN_MATCH_COUNT:
# 改变数组的表现形式，不改变数据内容，数据内容是每个关键点的坐标位置
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
# findHomography 函数是计算变换矩阵
# 参数cv2.RANSAC是使用RANSAC算法寻找一个最佳单应性矩阵H，即返回值M
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)

h,w = img1.shape
# pts是图像img1的四个顶点
pts = np.float32([[0,0],[0,h-1],[w-1,h-1],[w-1,0]]).reshape(-1,1,2)
dst = cv2.perspectiveTransform(pts,M)        # 计算变换后的四个顶点坐标位置

# 根据四个顶点坐标位置在img2图像画出变换后的边框
img2 = cv2.polylines(img2,[np.int32(dst)],True,(255,0,0),3, cv2.LINE_AA)

else:
print("Not enough matches are found - %d/%d") % (len(good),MIN_MATCH_COUNT)

draw_params = dict(matchColor = (0,255,0),
singlePointColor = None,
flags = 2)
img3 = cv2.drawMatches(img1,kp1,img2,kp2,good[:100],None,**draw_params)
return img3
if __name__ == '__main__':
img3 = FLANN_MIN_MATCH_COUNT()
plt.imshow(img3, 'gray')
plt.show()

又测试了一组照片如下：
2.3 FLANN特征保存与匹配
在实际中，我们根据一张图片在众多的图片中查找匹配率最高的图片。如果按照上面的例子，也可以实现，但每次匹配时都需要重新检测图片的特征数据，这样会导致程序运行效率。 因此，我们可以将图片的特征数据进行保存，每次匹配时，只需读取特征数据进行匹配即可。 实现代码如下：
保存图片的特征数据
import cv2
import numpy as np
import os

def get_img(input_path):
image_paths = []
for (dirs, dirnames, filenames) in os.walk(input_path):
for img_file in filenames:
ext = ['.jpg','.png','.jpeg','.tif']
if img_file.endswith(tuple(ext)):
image_paths.append(dirs+'/'+img_file)
return image_paths

def save_descriptor(sift,image_path):
if image_path.endswith("npy"):
return
keypoints, descriptors = sift.detectAndCompute(img, None)

# 设置文件名并将特征数据保存到npy文件
descriptor_file = image_path.replace(image_path.split('.')[-1], ".npy")
np.save(descriptor_file, descriptors)

if __name__=='__main__':
input_path = 'D:\\python_script\\hhhh'
image_paths = get_img(input_path)
sift = cv2.xfeatures2d.SIFT_create()
for image_path in image_paths:
save_descriptor(sift, image_path)
print('done!')


加载图片的特征数据，对需要匹配的数据集进行匹配
import numpy as np
import cv2,os

def Get_npy(input_path):
descriptors = []
for (dirs, dirnames, filenames) in os.walk(input_path):
for img_file in filenames:
if img_file.endswith('npy'):
descriptors.append(dirs+'/'+img_file)
return descriptors

def SIFT_FLANN():
sift = cv2.xfeatures2d.SIFT_create()
index_params = dict(algorithm=0, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
return sift,flann

def Detect_Matches(sift,flann,query,descriptors):
query_kp, query_ds = sift.detectAndCompute(query, None)
potential_culprits = {}
for desc in descriptors:
# 将图像query与特征数据文件的数据进行匹配

# 清除错误匹配
good = []
for m, n in matches:
if m.distance < 0.7 * n.distance:
good.append(m)

# 输出每张图片与目标图片的匹配特征数目
print("img is %s ! matching rate is (%d)" % (desc, len(good)))
potential_culprits[desc] = len(good)

# 获取最多匹配数目的图片
max_matches = None
potential_suspect = None
for culprit, matches in potential_culprits.items():
if max_matches == None or matches > max_matches:
max_matches = matches
potential_suspect = culprit
print("potential suspect is %s" % potential_suspect.replace("npy", "").upper())

if __name__ == '__main__':
input_path = 'D:\\python_script\\hhhh'
descriptors = Get_npy(input_path)                # 获取特征数据文件
sift, flann = SIFT_FLANN()                       # 使用SIFT算法检查图像的关键点和描述符，创建FLANN匹配器
Detect_Matches(sift, flann, query, descriptors)  # 检测并匹配

图片模板与批量寻找
当然你也可以对需要寻找的图片制作几个通用模板，方便批量寻找图片（该算法有个很大的缺点，请自行体会）。
import cv2
import os,shutil,csv

def get_img(ImgNpy_path):
image_paths = []
for (dir, dirnames, filenames) in os.walk(ImgNpy_path):
for img_file in filenames:
ext = ['.jpg','.png','.jpeg','.tif']
if img_file.endswith(tuple(ext)):
image_paths.append(dir+'/'+img_file)
return image_paths

def SIFT_FLANN():
sift = cv2.xfeatures2d.SIFT_create()
index_params = dict(algorithm=0, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
return sift,flann

def Detect_Matches(sift,flann,query,des1):
query_kp, des2 = sift.detectAndCompute(query, None)
matches = flann.knnMatch(des1, des2, k=2)
good_matches = []
for m,n in matches:
if m.distance < 0.7*n.distance:
good_matches.append(m)

points = len(good_matches)
percent = round((len(good_matches)/len(matches)),3)*100
if 60>percent>30:
percent += percent*(1 - percent*0.01)
return points ,percent

def main(Moban_path,Sou_Imgpath,Target_path):
Moban_paths = get_img(Moban_path)                # 获取模板文件
Sou_paths = get_img(Sou_Imgpath)                 # 获取待搜寻的图片
sift, flann = SIFT_FLANN()                       # 创建FLANN匹配器（使用SIFT算法检查图像的关键点和描述符）
Contrast_csv = []
for moban_img in Moban_paths:                    # 制作特征
_, des1 = sift.detectAndCompute(img, None)
for image_path in Sou_paths:
try:
points,percent = Detect_Matches(sift, flann, query, des1)     # 检测并匹配
Contrast_csv.append((moban_img, image_path, points, str(percent)+'%'))
if percent>=50:
shutil.copy(image_path,Target_path)
print("Img:{}\t Similarity_degree:{}%".format(image_path,percent))
else:
print('This image is not need!')
except:
return Contrast_csv

def save_csv(csv_path,Contrast_csv):
with open(csv_path, 'w', newline='') as csv_file:
csv_writer = csv.writer(csv_file)
csv_writer.writerow(('模板图','被检测的图片','匹配特征点', '相似度百分比'))
csv_writer.writerows(Contrast_csv)

if __name__ == '__main__':
Moban_path = 'D:\\python_script\\hhhh'                  # 被查寻的图片模板
Sou_Imgpath = 'D:\\python_script\\eeee'                 # 需要筛选的图片目录
Target_path = 'D:\\python_script\\jjjj'                 # 筛选之后存放图片的目录
csv_path = 'D:\\python_script\\iiii\\Contrast_04.csv'   # 匹配信息保存

Contrast_csv = main(Moban_path,Sou_Imgpath,Target_path) # 检测特征
save_csv(csv_path, Contrast_csv)
print('done!')

参考与鸣谢 https://blog.csdn.net/jinxueliu31/article/details/37768995 https://blog.csdn.net/GAN_player/article/details/78285771
展开全文
• Brute Force匹配（暴力匹配）和FLANN匹配区别
Brute Force匹配和FLANN匹配是OpenCV二维特征点匹配常见的两种办法，分别对应BFMatcher（BruteForceMatcher）和FlannBasedMatcher。

二者的区别在于BFMatcher总是尝试所有可能的匹配，从而使得它总能够找到最佳匹配，这也是Brute Force（暴力法）的原始含义。而FlannBasedMatcher中FLANN的含义是Fast Library forApproximate Nearest Neighbors，从字面意思可知它是一种近似法，算法更快但是找到的是最近邻近似匹配，所以当我们需要找到一个相对好的匹配但是不需要最佳匹配的时候往往使用FlannBasedMatcher。当然也可以通过调整FlannBasedMatcher的参数来提高匹配的精度或者提高算法速度，但是相应地算法速度或者算法精度会受到影响


展开全文
• OpenCV SURF FLANN匹配的实例OpenCV SURF FLANN匹配的实例 OpenCV SURF FLANN匹配的实例 #include <iostream> #include "opencv2/core.hpp" #ifdef HAVE_OPENCV_XFEATURES2D #include "opencv2/highgui.hpp" #...


OpenCV SURF FLANN匹配的实例

OpenCV SURF FLANN匹配的实例

OpenCV SURF FLANN匹配的实例
#include <iostream>
#include "opencv2/core.hpp"
#ifdef HAVE_OPENCV_XFEATURES2D
#include "opencv2/highgui.hpp"
#include "opencv2/features2d.hpp
展开全文
• OpenCV SURF FLANN匹配单应性的实例OpenCV SURF FLANN匹配单应性的实例 OpenCV SURF FLANN匹配单应性的实例 #include <iostream> #include "opencv2/core.hpp" #ifdef HAVE_OPENCV_XFEATURES2D #include ...
• 基于FLANN匹配算法定位零件 import numpy as np import cv2.cv2 as cv2 from matplotlib import pyplot as plt MIN_MATCH_COUNT=10 template=cv2.imread('sam1.jpg',0) target=cv2.imread('666.jpg',0) import ...
• 关于透视变换 cv2.warpPerspective 详情请查看： https://blog.csdn.net/dcrmg/article/details/80273818 ...关于FLANN匹配 详情请查看：https://blog.csdn.net/wsp_1138886114/a...
• 使用 OpenCV 中的蛮力(Brute-Force)匹配FLANN 匹配。 1：Brute-Force 匹配的基础 蛮力匹配器是很简单的。首先在第一幅图像中选取一个关键点然后依次与第二幅图像的每个关键点进行(描述符)距离测试,最后返回距离...
•   FLANN是快速最近邻搜索包（Fast_Library_for_Approximate_Nearest_Neighbors）的...  使用FLANN匹配，我们需要传入两个字典作为参数。这两个用来确定要使用的算法和其他相关参数等。 FLANN是一个单独的算法...
• FLANN是快速最近邻搜索包（Fast_Library_for_Approximate_Nearest_Neighbors）的简称。...使用FLANN匹配，我们需要传入两个字典作为参数。这两个用来确定要使用的算法和其他相关参数等。第一个是indexParams。配置我...
• 最近看图像匹配的内容，特地比较了暴力匹配和基于FLANN匹配方法，按照理论上讲，FLANN更快一些，但是程序结果显示暴力匹配的方法更快，由于我只用了两幅图像，可能是实验样本太少的缘故吧，代码如下： #include<...
• ## FLANN匹配算法

千次阅读 2019-03-09 21:16:07
使用FLANN匹配，我们需要传入两个字典作为参数。这两个用来确定要使用的算法和其他相关参数等。 一 算法的选择 第一个是indexParams。配置我们要使用的算法 1、 随机k-d树算法（The Randomized k-d ...
• 步骤：先用SURF描述子检测关键点，再利用FLANN匹配对关键点进行筛选匹配，最后利用透视变换将匹配后的对象画出来。 #include&lt;opencv2\opencv.hpp&gt; #include&lt;opencv2\xfeatures2d.hpp&gt;...
• 而FlannBasedMatcher中FLANN的含义是Fast Library forApproximate Nearest Neighbors，从字面意思可知它是一种近似法，算法更快但是找到的是最近邻近似匹配，所以当我们需要找到一个相对好的匹配但是不需要最佳匹配...
• opencv_python Stitcher拼接图像实例（SIFT/SURF检测特征点，BF/FLANN匹配特征点） SIFI/SURF检测特征点，BF/FLANN匹配特征点，stitch缝接图片，并进行视角变换。 先创建一个Stitcher类： import numpy as np import...
• 什么叫特征描述子/匹配 什么是特征描述子 图片具有特有特征 匹配 提取一份图像中的特征，去训练集图像库寻找，寻找贴合区域 一些用到的API介绍 函数api void cv::drawMatches( InputArray img1, const std::...
• FLANN库全称是Fast Library for Approximate Nearest Neighbors，它是目前最完整的（近似）最近邻开源库。不但实现了一系列查找算法，还包含了一种自动选取最快算法的机制。 关于算法详情查看：...
• 所以，我们今天介绍另外一种匹配方法—— （近似）最近邻快速搜索库（Fast Library for Approximate Nearest Neighbors，FLANN）。它是一个对大数据集和高维特征进行最近邻搜索的算法的集合，而且这些算法
• FLANN是快速最近邻搜索包（Fast_Library_for_Approximate_Nearest_Neighbors）的简称。它是一个对大数据集合高维特征进行最近邻搜索算法集合。在面对大数据集时，它的效果要好与BFMatcher。#include &lt;...
• FLANN库全称是Fast Library for Approximate Nearest Neighbors，它是目前最完整的（近似）最近邻开源库。不但实现了一系列查找算法，还包含了一种自动选取最快算法的机制。 OpenCV提供了 两种Matching方式 ：  ...

...