OpenCV(图像处理)-基于Python-特征检测-特征点匹配

简介: 1.图像特征图像特征就是指有意义的图像区域,具有独特性,易于识别性,比如角点、斑点以及高密度区。而为什么角点具有重要的特征呢?看下图:

59e7237481d6460bbc5b9a8281a0c546.png1.图像特征

图像特征就是指有意义的图像区域,具有独特性,易于识别性,比如角点、斑点以及高密度区。而为什么角点具有重要的特征呢?

看下图:


14a267effa4d4cd4a301ef23b330936e.png

观察ABD三张图片,我们不容易得知图像的位置,而CEF三张图我们特别容易找到它们在原图中对应的位置,这是因为ABD比较平滑,我们不易找出他们的特点,而CEF三张图有很明显的轮廓特征,有很多边缘特征即角点,因此一幅图像中的角点非常重要。

想让计算机具有识别图片的功能,首先要让他们学会提取图片的特征,提取图像的角点。


角点的特征

在特征中最重要的是角点

是灰度梯度最大值所对应的像素

两条线的交点

极值点(一阶导数最大值但是二阶导数为0)

2. 哈里斯检测

原理:

844a97be82c84373ad70780c1b8ed3ab.png

图1方块上下左右移动都没有变化,说明图1不是角点;图2上下没有变化,左右移动有变化,说明图2是边缘;图3上下左右移动都有变化,说明图3是角点。


42439ba1747743f6a53af6db597fb51a.png

cornerHarris()

dst = cv2.cornerHarris(img, blockSize, ksize, k)

img :需要检测的图像,最好为灰度图

blockSize:检测窗口的大小,一般取2

ksiez:Sobel卷积核,一般取3

k:权重系数,经验值,一般取0.02~0.04之间

返回值:dst不是图像,是点的集合

缺点:k是个经验值需要自己调节

import cv2
import numpy as np
# 读取图片,并转为灰度图
img = cv2.imread('./image/chess.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Harris角点检测
dst = cv2.cornerHarris(gray, 2, 3, 0.02)
# 表示img中dst值大于0.01*dst.max()的像素点索引出来,然后将这些像素点的值赋为 [0,0,255]。
img[dst > 0.01*dst.max()] = [0, 0, 255]
cv2.imshow('img', img)
cv2.waitKey(0)


c20014f7a5a34658a186eedf9b64296b.png

3.Shi-Tomasi角点检测

Shi-Tomasi是Harris角点检测的改进,因为Harris角点检测的稳定性与k有关,而k是个经验值,与人的主观因素有关。Shi-Tomasi避免了这个问题。

goodFeaturesToTrack()

dst = cv2.goodFeaturesToTrack(img, maxCorners, qualityLevel, minDistance)

img:需要检测的图像,最好为灰度图

maxCorners:角点的最大数量,值为0表示无限制

qualityLevel:小于1.0的正数,一般在0.01-1.0之间

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

mask:感兴趣的区域,不填默认全部图像

blockSize:检测窗口大小

useHarrisDetector:是否使用Harris算法,True/False

k:默认是0.04

import cv2
import numpy as np
# 读取图片,并转为灰度图
img = cv2.imread('./image/chess.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Harris角点检测
# dst = cv2.cornerHarris(gray, 2, 3, 0.02)
maxCorners = 100
ql = 0.01
minDistance = 10
# ShiTomasi角点检测
corners = cv2.goodFeaturesToTrack(gray, maxCorners, ql, minDistance)
# corners为float32类型,需要转化为整型
corners = np.int0(corners)
# 表示img中dst值大于0.01*dst.max()的像素点索引出来,然后将这些像素点的值赋为 [0,0,255]。
# img[dst > 0.01*dst.max()] = [0, 0, 255]
for i in corners:
    x, y = i.ravel() # 将迭代的数组,转化成一维的
    cv2.circle(img, (x, y), 3, (0, 0, 255), -1)
cv2.imshow('img', img)
cv2.waitKey(0)


ac586659110e43b99eeb5062f7440f88.png

4.Scale-Invariant Feature Transform(SIFT)

该算法是与缩放无关的特征检测,比如说,以前是角点,但是在图放大或缩小后,由于图片比例的变化,原来是角,放大之后,可能就不是角;原来是角,缩小之后可能就是角。而该算法正好解决了这个问题。


7b9e6f0fd5e44325816da2b4023cbbef.png

SIFT能够计算关键点和描述子,关键点:位置、大小和方向;关键点描述子:记录了关键点周围对其有贡献的像素点的一组向量值,其不受仿射变换、光照变换的影响。

SIFT语法

首先创建SIFT对象

进行检测,kp =sift.detect(img,…)

绘制关键点,drawKeypoints(gray, kp, img)

从灰度图gray中检测的,关键点kp,在原图img中画

创建SIFT对象

sift = cv2.xfeatures2d.SIFT_create(什么也不写)

kp = sift.detect(img, mask)

img:是检测图片,尽量用灰度图

mask:掩码,指明对图中哪部分进行检测,一般填None(全图)

import cv2
import numpy as np
# 读取图片,并转为灰度图
img = cv2.imread('./image/chess.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建sift对象
sift = cv2.xfeatures2d.SIFT_create()
# 关键点检测
kp = sift.detect(gray, None)
# 使用关键点画图
cv2.drawKeypoints(gray, kp, img)
cv2.imshow('img', img)
cv2.waitKey(0)


bd749ca90e444bb49b2e317b76fb9eea.png

此接口一下能算出关键点和描述子

kp, des = sift.detectAndCompute(img, mask)

img:是检测图片,尽量用灰度图

mask:掩码,指明对图中哪部分进行检测,一般填None(全图)

import cv2
import numpy as np
# 读取图片,并转为灰度图
img = cv2.imread('./image/chess.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建sift对象
sift = cv2.xfeatures2d.SIFT_create()
# kp = sift.detect(gray, None)
kp, des = sift.detectAndCompute(gray, None)
cv2.drawKeypoints(gray, kp, img)
cv2.imshow('img', img)
cv2.waitKey(0)


59e7237481d6460bbc5b9a8281a0c546.png

SIFT缺点:速度慢

5.SURF

由于SIFT速度较慢,因此又产生了SURF算法,该算法速度优于SIFT。

  • 首先创建SURF对象

进行检测,kp, des =surf.detectAndCompute(img, mask)

绘制关键点,drawKeypoints(gray, kp, img)

从灰度图gray中检测的,关键点kp,在原图img中画

创建surf对象

surf = cv2. xfeatures2d.SURF_create()

kp, des = surf.detectAndCompute(img, mask)

img:是检测图片,尽量用灰度图

mask:掩码,指明对图中哪部分进行检测,一般填None(全图)

kp:检测出的关键字

des:是描述子,用来特征匹配使用的

import cv2
import numpy as np
# 读取图片,并转为灰度图
img = cv2.imread('./image/chess.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# # 创建sift对象
# sift = cv2.xfeatures2d.SIFT_create()
# 创建surf对象
surf = cv2.xfeatures2d.SURF_create()
# 计算关键点和描述子
kp, des = surf.detectAndCompute(gray, None)
cv2.drawKeypoints(gray, kp, img)
cv2.imshow('img', img)
cv2.waitKey(0)

注意:此算法由于付费的缘由,需要使用3.4.2.17版本的opencv库

6.ORB(Oriented FAST and Rotated BRIEF)

其中FAST用于特征检测,BRIEF是对已检测到的特征点进行描述,它加快了特征描述符的建立速度,同时也极大降低了特征匹配的时间。

ORB的优势在于:速度快,可用于实时监测;免费。


先建立ORB对象

orb = cv2.ORB_create()

计算特征点与描述子

kp, des = orb.detectAndCompute(img, mask)

使用kp画出特征点

cv2.drawKeypoints(gray, kp, img)


img:是检测图片,尽量用灰度图

mask:掩码,指明对图中哪部分进行检测,一般填None(全图)

import cv2
import numpy as np
# 读取图片,并转为灰度图
img = cv2.imread('./image/chess.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 创建orb对象
orb = cv2.ORB_create()
# 对ORB进行检测
kp, des = orb.detectAndCompute(gray, None)
cv2.drawKeypoints(gray, kp, img)
cv2.imshow('img', img)
cv2.waitKey(0)

ab2164f0c66b4c6b99f4b8fccdc74403.png

检测出的特征点越来越少,因此在提升检测速度的同时,精度也在丢失。


7.特征匹配

根据特征点的描述子进行匹配,特征匹配方法有:


BF(Brute-Force),暴力特征匹配方法

FLANN 最快临近区特征匹配方法

7.1 暴力特征匹配

它使用第一组中的每个特征点的描述子与第二组中的所有特征点的描述子进行匹配,计算他们之间的差距,然后将最接近的一个匹配返回


创建匹配器,bf = cv2.BFMatcher(normType, crossCheck)

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

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

创建匹配器

bf = cv2.BFMatcher(normType, crossCheck)

normType:NORM_L1(SIFT),NORM_L2(SURF), HAMMING1(ORB)

crossCheck:是否进行交叉匹配,默认为false

描述子进行匹配

match = bf.match(dst1, dst2)

dst1:要搜索的图的描述子

dst2:从库里能匹配的描述子

画相同的地方

img3 = cv2.drawMatchers(img1, kp1, img2, kp2, match, None)

img1, kp1:要搜索的图,和特征点

img2, kp2:从库里匹配的图和特征点

match:匹配好的描述子

import cv2
import numpy as np
# 读取图片,并转为灰度图
img1 = cv2.imread('./image/opencv_search.png')
img2 = cv2.imread('./image/opencv_orig.png')
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 创建orb对象
orb = cv2.ORB_create()
# 对ORB进行检测
kp1, dst1 = orb.detectAndCompute(gray1, None)
kp2, dst2 = orb.detectAndCompute(gray2, None)
# 创建匹配器
bf = cv2.BFMatcher(cv2.NORM_HAMMING)
# 描述子进行匹配
match = bf.match(dst1, dst2)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, match, None)
cv2.imshow('img3', img3)

6d677a85ffc14468b05a3a154eadf927.png

7.2 FLANN

  • 进行批量特征匹配时,FLANN速度更快
  • 由于它使用的是临近近似值,所以精度较差

创建匹配器

flann = cv2.FlannBasedMatcher()

进行特征匹配

match = flann.match()

绘制匹配点img3 = cv2.drawMatches()

import cv2
import numpy as np
# 读取图片,并转为灰度图
img1 = cv2.imread('./image/opencv_search.png')
img2 = cv2.imread('./image/opencv_orig.png')
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 创建orb对象
orb = cv2.ORB_create()
# 对ORB进行检测
kp1, dst1 = orb.detectAndCompute(gray1, None)
kp2, dst2 = orb.detectAndCompute(gray2, None)
# 判断描述子的数据类型,若不符合,则进行数据替换
if dst1.dtype != 'float32':
    dst1 = dst1.astype('float32')
if dst2.dtype != 'float32':
    dst2 = dst2.astype('float32')
# 创建匹配器(FLANN)
flann = cv2.FlannBasedMatcher()
# 描述子进行匹配计算
matches = flann.match(dst1, dst2)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches, None)
cv2.imshow('img3', img3)


cf359fdd4d3f45efaa546c0d21bf0089.png 

目录
相关文章
|
2月前
|
算法 计算机视觉
基于qt的opencv实时图像处理框架FastCvLearn实战
本文介绍了一个基于Qt的OpenCV实时图像处理框架FastCvLearn,通过手撕代码的方式详细讲解了如何实现实时人脸马赛克等功能,并提供了结果展示和基础知识回顾。
109 7
基于qt的opencv实时图像处理框架FastCvLearn实战
|
1月前
|
机器学习/深度学习 TensorFlow 算法框架/工具
使用Python实现深度学习模型:智能质量检测与控制
使用Python实现深度学习模型:智能质量检测与控制 【10月更文挑战第8天】
175 62
使用Python实现深度学习模型:智能质量检测与控制
|
18天前
|
机器学习/深度学习 PyTorch TensorFlow
使用Python实现智能食品质量检测的深度学习模型
使用Python实现智能食品质量检测的深度学习模型
69 1
|
1月前
|
计算机视觉 Python
python利用pyqt5和opencv打开电脑摄像头并进行拍照
本项目使用Python的PyQt5和OpenCV库实现了一个简单的摄像头应用。用户可以通过界面按钮打开或关闭摄像头,并实时预览视频流。点击“拍照”按钮可以捕捉当前画面并保存为图片文件。该应用适用于简单的图像采集和处理任务。
103 0
python利用pyqt5和opencv打开电脑摄像头并进行拍照
|
1月前
|
机器学习/深度学习 算法 计算机视觉
【Python篇】Python + OpenCV 全面实战:解锁图像处理与视觉智能的核心技能
【Python篇】Python + OpenCV 全面实战:解锁图像处理与视觉智能的核心技能
71 2
|
2月前
|
Docker Python 容器
python检测docker compose文件是否正确
python检测docker compose文件是否正确
|
2月前
|
机器学习/深度学习 计算机视觉 Python
opencv环境搭建-python
本文介绍了如何在Python环境中安装OpenCV库及其相关扩展库,包括numpy和matplotlib,并提供了基础的图像读取和显示代码示例,同时强调了使用Python虚拟环境的重要性和基本操作。
|
1月前
|
运维 安全 网络协议
Python 网络编程:端口检测与IP解析
本文介绍了使用Python进行网络编程的两个重要技能:检查端口状态和根据IP地址解析主机名。通过`socket`库实现端口扫描和主机名解析的功能,并提供了详细的示例代码。文章最后还展示了如何整合这两部分代码,实现一个简单的命令行端口扫描器,适用于网络故障排查和安全审计。
|
1月前
|
数据处理 Python
Python读取大文件的“坑“与内存占用检测
Python读取大文件的“坑“与内存占用检测
49 0
|
1月前
|
安全 Java Python
基于python-django的Java网站全站漏洞检测系统
基于python-django的Java网站全站漏洞检测系统
34 0
下一篇
无影云桌面