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

目录
  • 背景
  • 一、Harris角点
  • 二、Shi-Tomasi角点检测
  • 三、SIFT关键点
  • 四、SIFT描述子
  • 五、SURF
  • 六、ORB
  • 七、暴力特征匹配(BF)
  • 八、FLANN特征匹配
  • 九、图像查找
  • 总结

背景

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

特征点应用的一些场景:

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

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

拼图游戏:游戏领域

一、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:
    # 获得源和目标点的数组
    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(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特征点检测与匹配的资料请关注我们其它相关文章!

(0)

相关推荐

  • C#中OpenCvSharp 通过特征点匹配图片的方法

    现在的手游基本都是重复操作,一个动作要等好久,结束之后继续另一个动作.很麻烦,所以动起了自己写一个游戏辅助的心思. 这个辅助本身没什么难度,就是通过不断的截图,然后从这个截图中找出预先截好的能代表相应动作的按钮或者触发条件的小图. 找到之后获取该子区域的左上角坐标,然后通过windows API调用鼠标或者键盘做操作就行了. 这里面最难的也就是找图了,因为要精准找图,而且最好能适应不同的分辨率下找图,所以在模板匹配的基础上,就有了SIFT和SURF的特征点找图方式. 在写的过程中查找资料,大都是

  • python 3利用Dlib 19.7实现摄像头人脸检测特征点标定

    Python 3 利用 Dlib 19.7 实现摄像头人脸检测特征点标定 0.引言 利用python开发,借助Dlib库捕获摄像头中的人脸,进行实时特征点标定: 图1 工程效果示例(gif) 图2 工程效果示例(静态图片) (实现比较简单,代码量也比较少,适合入门或者兴趣学习.) 1.开发环境 python: 3.6.3 dlib: 19.7 OpenCv, numpy import dlib # 人脸识别的库dlib import numpy as np # 数据处理的库numpy impor

  • python3利用Dlib19.7实现人脸68个特征点标定

    0.引言 利用Dlib官方训练好的模型"shape_predictor_68_face_landmarks.dat"进行68点标定,利用OpenCv进行图像化处理,在人脸上画出68个点,并标明序号: 实现的68个特征点标定功能如下图所示: 图1 人脸68个特征点的标定 1.开发环境 python:3.6.3 dlib:19.7 OpenCv, numpy 需要调用的库: import dlib #人脸识别的库dlib import numpy as np #数据处理的库numpy im

  • Python OpenCV特征检测之特征匹配方式详解

    目录 前言  一.暴力匹配器 二.FLANN匹配器 前言  获得图像的关键点后,可通过计算得到关键点的描述符.关键点描述符可用于图像的特征匹配.通常,在计算图A是否包含图B的特征区域时,将图A称做训练图像,将图B称为查询图像.图A的关键点描述符称为训练描述符,图B的关键点描述符称为查询描述符. 一.暴力匹配器 暴力匹配器使用描述符进行特征比较.在比较时,暴力匹配器首先在查询描述符中取一个关键点的描述符,将其与训练描述符中的所有关键点描述符进行比较,每次比较后会给出一个距离值,距离最小的值对应最佳

  • Python OpenCV学习之特征点检测与匹配详解

    目录 背景 一.Harris角点 二.Shi-Tomasi角点检测 三.SIFT关键点 四.SIFT描述子 五.SURF 六.ORB 七.暴力特征匹配(BF) 八.FLANN特征匹配 九.图像查找 总结 背景 提取图像的特征点是图像领域中的关键任务,不管在传统还是在深度学习的领域中,特征代表着图像的信息,对于分类.检测任务都是至关重要的: 特征点应用的一些场景: 图像搜索:以图搜图(电商.教育领域) 图像拼接:全景拍摄(关联图像拼接) 拼图游戏:游戏领域 一.Harris角点 哈里斯角点检测主要

  • C++ OpenCV学习之图像金字塔与图像融合详解

    目录 1金字塔 2什么是图像金字塔? 3图像金字塔有什么用? 4OpenCV实战图像金字塔 1 金字塔 平时你听到.见到的金字塔是什么样的? 这样? 还是这样? 实际上除了这些,还有图像金字塔   图像金字塔有什么用?为什么要称作图像金字塔?本文带你研究这些问题. 2 什么是图像金字塔? 正如生物视觉系统会处理分层次的尺寸一样,计算机视觉系统实现多分辨率图像处理的基础是图像金字塔. 考虑这样一个场景:输入系统一幅图像来检测人脸.由于事先并不知道人脸在这张图片中可能的尺寸,所以需要根据输入生成一个

  • Python中提取人脸特征的三种方法详解

    目录 1.直接使用dlib 2.使用深度学习方法查找人脸,dlib提取特征 3.使用insightface提取人脸特征 安装InsightFace 提取特征 1.直接使用dlib 安装dlib方法: Win10安装dlib GPU过程详解 思路: 1.使用dlib.get_frontal_face_detector()方法检测人脸的位置. 2.使用 dlib.shape_predictor()方法得到人脸的关键点. 3.使用dlib.face_recognition_model_v1()方法提取

  • Python深度学习之图像标签标注软件labelme详解

    前言 labelme是一个非常好用的免费的标注软件,博主看了很多其他的博客,有的直接是翻译稿,有的不全面.对于新手入门还是有点困难.因此,本文的主要是详细介绍labelme该如何使用. 一.labelme是什么? labelme是图形图像注释工具,它是用Python编写的,并将Qt用于其图形界面.说直白点,它是有界面的, 像软件一样,可以交互,但是它又是由命令行启动的,比软件的使用稍微麻烦点.其界面如下图: 它的功能很多,包括: 对图像进行多边形,矩形,圆形,多段线,线段,点形式的标注(可用于目

  • Python深度学习实战PyQt5布局管理项目示例详解

    目录 1. 从绝对定位到布局管理 1.1 什么是布局管理 1.2 Qt 中的布局管理方法 2. 水平布局(Horizontal Layout) 3. 垂直布局(Vertical Layout) 4. 栅格布局(Grid Layout) 5. 表格布局(Form Layout) 6. 嵌套布局 7. 容器布局 布局管理就是管理图形窗口中各个部件的位置和排列.图形窗口中的大量部件也需要通过布局管理,对部件进行整理分组.排列定位,才能使界面整齐有序.美观大方. 1. 从绝对定位到布局管理 1.1 什么

  • OpenCV学习之图像的分割与修复详解

    目录 背景 一.分水岭法 二.GrabCut法 三.MeanShift法 四.MOG前景背景分离法 五.拓展方法 六.图像修复 总结 背景 图像分割本质就是将前景目标从背景中分离出来.在当前的实际项目中,应用传统分割的并不多,大多是采用深度学习的方法以达到更好的效果:当然,了解传统的方法对于分割的整体认知具有很大帮助,本篇将介绍些传统分割的一些算法: 一.分水岭法 原理图如下: 利用二值图像的梯度关系,设置一定边界,给定不同颜色实现分割: 实现步骤: 标记背景 —— 标记前景 —— 标记未知区域

  • Python语法学习之进程的创建与常用方法详解

    目录 进程的创建模块 - multiprocessing 创建进程函数 - Process 进程的常用方法 start 函数 join 函数 kill 函数 与 is_alive 函数 进程的相关问题 该章节我们来学习一下在 Python 中去创建并使用多进程的方法,通过学习该章节,我们将可以通过创建多个进程来帮助我们提高脚本执行的效率.可以认为缩短脚本执行的时间,就是提高执行我们脚本的效率.接下来让我们都看一下今天的章节知识点都有哪些? 进程的创建模块 - multiprocessing 创建

  • Python语法学习之进程池与进程锁详解

    目录 进程池 什么是进程池 进程池的创建模块 - multiprocessing 创建进程池函数 - Pool 进程池的常用方法 apply_async 函数演示案例 close 函数与 join 函数 演示 进程锁 进程锁的概念 进程锁的加锁与解锁 NICE!大家好,在上一章节,我们学习了 multiprocessing 模块 的关于进程的创建与进场常用的方法的相关知识. 通过在一个主进程下创建多个子进程可以帮助我们加速程序的运行,并且提高工作效率.不过上一章节文末我们也说过进程的问题,由于每

  • Python语法学习之线程的创建与常用方法详解

    目录 线程的创建与使用 线程的创建 -threading 线程对象的常用方法 线程演示案例 线程的问题 线程的创建与使用 在Python中有很多的多线程模块,其中 threading 模块就是比较常用的.下面就来看一下如何利用 threading 创建线程以及它的常用方法. 线程的创建 -threading 函数名 介绍 举例 Thread 创建线程 Thread(target, args) Thread 的动能介绍:通过调用 threading 模块的 Thread 类来实例化一个线程对象:它

  • Python+OpenCV实现鼠标画瞄准星的方法详解

    目录 函数说明 cv2.circle() cv2.line() 简单的例子 利用鼠标回调函数画瞄准星 所谓瞄准星指的是一个圆圈加一个圆圈内的十字线,就像玩射击游戏狙击枪开镜的样子一样.这里并不是直接在图上画一个瞄准星,而是让这个瞄准星跟着鼠标走.在图像标注任务中,可以利用瞄准星进行一些辅助,特别是回归类的任务,使用该功能可以使得关键点的标注更加精准. 关于鼠标回调函数的说明可以参考:opencv-python的鼠标交互操作 函数说明 import cv2后,可以分别help(cv2.circle

随机推荐