OpenCV可以检测图像的主要特征,然后提取这些特征、使其成为图像描述符,这类似于人的眼睛和大脑。这些图像特征可作为图像搜索的数据库。此外,人们可以利用这些关键点将图像拼接起来,组成一个更大的图像,比如将许多图像放在一块,然后形成一个360度全景图像。
这里我们将学习使用OpenCV来检测图像特征,并利用这些特征进行图像匹配和搜索。我们会选取一些图像,并通过单应性,检测这些图像是否在另一张图像中。
一 特征检测算法
有许多用于特征检测和提取的算法,我们将会对其中大部分进行介绍。OpenCV最常使用的特征检测和提取算法有:
- Harris:该算法用于检测角点;
- SIFT:该算法用于检测斑点;
- SURF:该算法用于检测角点;
- FAST:该算法用于检测角点;
- BRIEF:该算法用于检测斑点;
- ORB:该算法代表带方向的FAST算法与具有旋转不变性的BRIEF算法;
通过以下方法进行特征匹配:
- 暴力(Brute-Force)匹配法;
- 基于FLANN匹配法;
可以采用单应性进行空间验证。
二 特征定义
那么,究竟什么是特征呢?为什么一副图像的某个特定区域可以作为一个特征,而其他区域不能呢?粗略的讲,特征就是有意义的图像区域,该区域具有独特特征和易于识别性。因此角点及高密度区域都是很好的特征,而大量重复的模式或低密度区域(例如图像中的蓝色天空)则不是很好的特征。边缘可以将图像分为两个区域,因此也可以看做好的特征。斑点是与周围有很大差别的像素区域,也是有意义的特征。
大多数特征检测算法都会涉及图像的角点、边和斑点的识别,也有一些涉及脊向的概念,可以认为脊向是细长物体的对称轴,例如识别图像中的一条路。
由于某些算法在识别和提取某类型特征的时候有较好的效果,所以知道输入图像是什么很重要,这样做有利于选择最合适的OpenCV工具包。
三 Harris检测角点特征
在这之前其实我们已经接触过角点检测了,在相机标定的时候,我们就利用到了角点检测。不过那时候没有深入的去研究。在这里,我们将会深入原理取学习角点检测。
下面我们从使用cornerHarris()函数讲起。
cornerHarris(src, blockSize, ksize,k[,dst[,borderType]]);
- 参数详解:
- image:输入图像;
- blockSize:就是扫描时候窗口的大小。
- ksize:cornerHarris函数会使用Sobel算子,该参数定义了Sobel算子的中孔。简单来说,该函数定义了角点检测的敏感度,其值必须介于3~31之间的奇数。
- k:harris 检测器的自由参数;
- borderType:像素插值方法;
函数 cornerHarris 对输入图像进行 Harris 边界检测。保存到输出图像中。输入图像中的角点在输出图像中由局部最大值表示。
# -*- coding: utf-8 -*- """ Created on Mon Aug 20 20:17:34 2018 @author: lenovo """ ‘‘‘ Harris角点检测 ‘‘‘ import cv2 import numpy as np img = cv2.imread(‘./image/cali.bmp‘) img = cv2.resize(img,dsize=(600,400)) gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) gray = np.float32(gray) #角点检测 第三个参数为角点检测的敏感度,其值必须介于3~31之间的奇数 dst = cv2.cornerHarris(gray,3,23,0.04) print(dst.shape) #(400, 600) img[dst>0.01*dst.max()] = [0,0,255] cv2.imshow(‘‘,img) cv2.waitKey(0) cv2.destroyAllWindows()
运行结果如下:
如果我们把第三个参数改为3:,可以看到:
四 Harris检测原理
上面我们已经通过实例演示了Harris检测的效果,相信你对Harris角点检测已经有了初步的认识。这里我将带你深入了解Harris角点检测的原理。
我们先来看一幅图片,了解一下什么是角点?
上图中E,F中的角我们通常称作角点(corner points),他们具有以下特征:
- 轮廓之间的交点;
- 对于同一场景,即使视角发生变化,通常具备稳定性质的特征;
- 该点附近区域的像素点无论在梯度方向上还是其梯度幅值上有着较大变化;
harris特征角最早在paper A Combined Corner and Edge Detector中被Chris Harris & Mike Stephens提出。
Harris角点检测的基本思想:算法基本思想是使用一个固定窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后两种情况,窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有着较大灰度变化,那么我们可以认为该窗口中存在角点。
1、灰度变化描述
当窗口发生$[u,v]$移动时,那么滑动前与滑动后对应的窗口中的像素点灰度变化描述如下:
$$E(u,v)=\sum\limits_{x,y}w(x,y)[I(x+u,y+v)-I(x,y)]^2$$
参数解释:
- $[u,v]$是窗口的偏移量;
- $(x,y)$是窗口所对应的像素坐标位置,窗口有多大,就有多少个位置;
- $w(x,y)$是窗口函数,最简单情形就是窗口内的所有像素所对应的$w$权重系数均为1.但有时候,我们会将$w(x,y)$函数设置为以窗口中心为原点的二元正太分布。如果窗口中心点是角点时,移动前与移动后,该点在灰度变化贡献最大;而离窗口中心(角点)较远的点,这些点的灰度变化几近平缓,这些点的权重系数,可以设定小值,以示该点对灰度变化贡献较小,那么我们自然而然想到使用二元高斯函数来表示窗口函数;
我们的窗口函数通常有如下两种形式:
根据上述表达式,当窗口在平潭区域上移动,可以想象得到,灰度不会发生什么变换。$E(u,v)=0$;如果窗口处在纹理比较丰富的区域上滑动,那么灰度变化会很大。算法最终思想就是计算灰度发生较大变化时所对应的位置,当然这个较大是指任意方向上的滑动,并非单指某个方向。
2、$E(u,v)$化简
首先需要了解泰勒公式,任何一个函数表达式,均可有泰勒公式进行展开,以逼近原函数,我们可以对下面函数进行一阶展开(如果对泰勒公式忘记了,可以翻翻本科所学的高等数学)。
$$f(x+u,y+v)≈f(x,y)+uf_x(x,y)+vf_y(x,y)$$
那么
$$\sum\limits_{x,y}w(x,y)[I(x+u,y+v)-I(x,y)]^2$$
$$≈\sum\limits_{x,y}w(x,y)[I(x,y)+uI_x+vI_y-I(x,y)]^2$$
$$=\sum\limits_{x,y}w(x,y)[u^2I_x^2+2uvI_xI_y+v^2I_y^2]$$
$$=\sum\limits_{x,y}w(x,y)\begin{bmatrix}u & v\end{bmatrix}\begin{bmatrix} I_x^2 & I_xIy \\ I_xI_y & I_y^2\end{bmatrix}\begin{bmatrix}u \\ v\end{bmatrix}$$
$$=\begin{bmatrix}u & v\end{bmatrix}(\sum\limits_{x,y}w(x,y)\begin{bmatrix} I_x^2 & I_xIy \\ I_xI_y & I_y^2\end{bmatrix})\begin{bmatrix}u \\ v\end{bmatrix}$$
所以$E(u,v)$表达式可以更新为:
$$E(u,v)=\begin{bmatrix}u & v\end{bmatrix}M\begin{bmatrix}u \\ v\end{bmatrix}$$
其中:$M=\sum\limits_{x,y}w(x,y)\begin{bmatrix} I_x^2 & I_xIy \\ I_xI_y & I_y^2\end{bmatrix}$,$I_x$,$I_y$分别为窗口内像素点$(x,y)$在$x$方向上和$y$方向上的梯度值。
3、矩阵$M$的关键性
难道我们是直接求上述的$E(u,v)$值来判断角点吗?Harris角点检测并没有这样做,而是通过对窗口内的每个像素的$x$方向上的梯度与$y$方向上的梯度进行统计分析。这里以$I_x$和$I_y$为坐标轴,因此每个像素的梯度坐标可以表示成$(I_x,I_y)$。针对平坦区域,边缘区域以及角点区域三种情形进行分析:
下图是对这三种情况窗口中的对应像素的梯度分布进行绘制:
如果使用椭圆进行数据集表示,则绘制图示如下:
参考文献:
OpenCV教程(43) harris角的检测(1)
Harris角点检测原理详解
原文地址:https://www.cnblogs.com/zyly/p/9508131.html