我的编程空间,编程开发者的网络收藏夹
学习永远不晚

PythonOpenCV学习之特征点检测与匹配详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

PythonOpenCV学习之特征点检测与匹配详解

背景

提取图像的特征点是图像领域中的关键任务,不管在传统还是在深度学习的领域中,特征代表着图像的信息,对于分类、检测任务都是至关重要的;

特征点应用的一些场景:

图像搜索:以图搜图(电商、教育领域)

图像拼接:全景拍摄(关联图像拼接)

拼图游戏:游戏领域

一、Harris角点

哈里斯角点检测主要有以下三种情况:

  • 光滑区域:无论向哪个方向移动,衡量系数不变;
  • 边缘区域:垂直边缘移动时,衡量系数变化强烈;
  • 角点区域:不管往哪个方向移动,衡量系数变化强烈;

函数原型:

cornerHarris(img,blockSize,ksize,k)

blockSize:检测窗口大小;

k:权重系数,一般取0.02~0.04之间;

代码案例:

img = cv2.imread('chess.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

dst = cv2.cornerHarris(gray, 2, 3, 0.04)

img[dst > 0.01*dst.max()] = (0, 0, 255)

cv2.imshow('harris', img)
cv2.waitKey(0)

二、Shi-Tomasi角点检测

说明:是Harris角点检测的改进,在Harris中需要知道k这个经验值,而在Shi-Tomasi不需要;

函数原型:

goodFeaturesToTrack(img,…)

maxCorners:角点的最大数量,值为0表示所有;

qualityLevel:角点的质量,一般在0.01~0.1之间(低于的过滤掉);

minDistance:角点之间最小欧式距离,忽略小于此距离的点;

mask:感兴趣区域;

useHarrisDetector:是否使用Harris算法(默认为false)

代码案例:

img = cv2.imread('chess.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

dst = cv2.goodFeaturesToTrack(gray, 1000, 0.01, 10)
dst = np.int0(dst)            # 实际上也是np.int64
for i in dst:
    x, y = i.ravel()         # 数组降维成一维数组(inplace的方式)
    cv2.circle(img, (x, y), 3, (0, 0, 255), -1)

cv2.imshow('harris', img)
cv2.waitKey(0)

本质上和Harris角点检测相同,效果会好一些,角点数量会多一些;

三、SIFT关键点

中文简译:与缩放无关的特征转换;

说明:Harris角点检测具有旋转不变性,也就是旋转图像并不会影响检测效果;但其并不具备缩放不变性,缩放大小会影响角点检测的效果;SIFT具备缩放不变性的性质;

实现步骤:

创建SIFT对象 —— 进行检测(sift.detect) —— 绘制关键点(drawKeypoints)

代码案例:

img = cv2.imread('chess.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray, None)      # 第二个参数为mask区域
cv2.drawKeypoints(gray, kp, img)

cv2.imshow('sift', img)
cv2.waitKey(0)

四、SIFT描述子

首先需要说明,关键点和描述子是两个概念;

关键点:位置、大小和方向;

关键点描述子:记录了关键点周围对其有贡献的像素点的一组向量值,其不受仿射变换,光照变换等影响;描述子的作用就是用于特征匹配;

同时计算关键点和描述子的函数(主要使用):

detectAndCompute(img,…)

代码案例:

img = cv2.imread('chess.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

sift = cv2.xfeatures2d.SIFT_create()
kp, dst = sift.detectAndCompute(gray, None)      # 第二个参数为mask区域

得到的dst即为描述子的信息;

五、SURF

中译:加速的鲁棒性特征检测;

说明:SIFT最大的缺点是速度慢,因此才会有SURF(速度快);

实现步骤与SIFT一致,代码如下:

surf = cv2.xfeatures2d.SURF_create()
kp, dst = surf.detectAndCompute(gray, None)      # 第二个参数为mask区域
cv2.drawKeypoints(gray, kp, img)

由于安装的opencv-contrib版本过高(有版权问题),已经不支持该功能了,在此就不作展示了;

六、ORB

说明:最大的优势就是做到实时检测,缺点就是缺失了很多信息(准确性下降);

主要是两个技术的结合:FAST(特征点实时检测)+ BRIEE(快速描述子建立,降低特征匹配时间)

使用步骤与之前的SIFT一致,代码如下:

img = cv2.imread('chess.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

orb = cv2.ORB_create()
kp, dst = orb.detectAndCompute(gray, None)      # 第二个参数为mask区域
cv2.drawKeypoints(gray, kp, img)

cv2.imshow('orb', img)
cv2.waitKey(0)

可以看出,相比于SIFT以及SURF关键点变少了,但是其速度有了很大提升;

七、暴力特征匹配(BF)

匹配原理:类似于穷举匹配机制,使用第一组中每个特征的描述子与第二组中的进行匹配,计算相似度,返回最接近的匹配项;

实现步骤:

创建匹配器:BFMatcher(normType,crossCheck)

进行特征匹配:bf.match(des1,des2)

绘制匹配点:cv2.drawMatches(img1,kp1,img2,kp2)

代码案例:

img1 = cv2.imread('opencv_search.png')
img2 = cv2.imread('opencv_orig.png')
g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

sift = cv2.SIFT_create()
kp1, dst1 = sift.detectAndCompute(g1, None)      # 第二个参数为mask区域
kp2, dst2 = sift.detectAndCompute(g2, None)      # 第二个参数为mask区域

bf = cv2.BFMatcher_create(cv2.NORM_L1)
match = bf.match(dst1, dst2)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, match, None)

cv2.imshow('result', img3)
cv2.waitKey(0)

从上图可看出,匹配的效果还是不错的,只有一个特征点匹配错误;

八、FLANN特征匹配

优点:在进行批量特征匹配时,FLANN速度更快;

缺点:由于使用的时邻近近似值,所有精度较差;

实现步骤与暴力匹配法一致,代码如下:

img1 = cv2.imread('opencv_search.png')
img2 = cv2.imread('opencv_orig.png')
g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

sift = cv2.SIFT_create()
kp1, dst1 = sift.detectAndCompute(g1, None)      # 第二个参数为mask区域
kp2, dst2 = sift.detectAndCompute(g2, None)      # 第二个参数为mask区域

index_params = dict(algorithm = 1, trees = 5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matchs = flann.knnMatch(dst1, dst2, k=2)

good = []
for i, (m, n) in enumerate(matchs):
    if m.distance < 0.7 * n.distance:
        good.append(m)
img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [good], None)

cv2.imshow('result', img3)
cv2.waitKey(0)

上图可以看出,匹配的特征点数量相比暴力匹配明显变少了,但速度会快很多;

九、图像查找

实现原理:特征匹配 + 单应性矩阵;

单应性矩阵原理介绍:

上图中表示从两个不同角度对原图的拍摄,其中H为单应性矩阵,可通过该矩阵将图像进行转换;

下面使用两个函数实现图像查找的功能:

findHomography():获得单应性矩阵;

perspectivveTransform():仿射变换函数;

代码实现如下:

img1 = cv2.imread('opencv_search.png')
img2 = cv2.imread('opencv_orig.png')
g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

sift = cv2.SIFT_create()
kp1, dst1 = sift.detectAndCompute(g1, None)      # 第二个参数为mask区域
kp2, dst2 = sift.detectAndCompute(g2, None)      # 第二个参数为mask区域

index_params = dict(algorithm = 1, trees = 5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matchs = flann.knnMatch(dst1, dst2, k=2)

good = []
for i, (m, n) in enumerate(matchs):
    if m.distance < 0.7 * n.distance:
        good.append(m)
if len(good) >= 4:
    # 获得源和目标点的数组
    class="lazy" data-srcPts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
    dstPts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
    
    # 获得单应性矩阵H
    H, _ = cv2.findHomography(class="lazy" data-srcPts, dstPts, cv2.RANSAC, 5.0)
    h, w = img1.shape[:2]
    pts = np.float32([[0,0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2)
    # 进行放射变换
    dst = cv2.perspectiveTransform(pts, H)
    
    # 绘制查找到的区域
    cv2.polylines(img2, [np.int32(dst)], True, (0,0,255))
else:
    print('good must more then 4.')
    exit()
    
img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [good], None)

cv2.imshow('result', img3)
cv2.waitKey(0)

总结

本篇主要介绍了特征点检测和匹配,其中重要的部分时SIFT算法以及FLANN算法;通过所学的知识,可以简单实现一个图像查找的功能,也就是找子图的功能。甚至可以目标识别的效果;当然这里需要的是完全一致的,不同于深度学习中的目标识别任务

以上就是Python OpenCV学习之特征点检测与匹配详解的详细内容,更多关于Python OpenCV特征点检测与匹配的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

PythonOpenCV学习之特征点检测与匹配详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python OpenCV中如何进行特征点检测与匹配

Python OpenCV中如何进行特征点检测与匹配,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。背景提取图像的特征点是图像领域中的关键任务,不管在传统还是在深度学习的领域
2023-06-26

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录