Python计算机视觉之特征提取与图像匹配
目录
一、特征提取
1.1 定义
1.2 边缘
1.3 角
1.4 区域
1.5 脊
二、图像匹配
2.1 定义
2.2 概述
三、基于特征点的特征描述子
四、Harris角点检测算法
4.1 概述
4.2 原理
4.3 数学表达
4.4 代码实现
五、SIFT特征检测算法
5.1 概述
5.2 原理
5.3 数学表达
5.4 代码实现
一、特征提取
1.1 定义
特征提取是计算机视觉和图像处理中的一个概念。它指的是使用计算机提取图像信息,决定图像中的每一个点是否属于该图像的一个特征。特征提取的结果是把图像上的点分为不同的子集,这些子集往往属于孤立的点、连续的曲线或者连续的区域。
那么,什么样的点才能称之为特征呢?
至今为止特征并没有绝对精确的定义。特征的精确定义往往由问题或者应用类型决定。特征是一个数字图像中“有趣”的部分,它是许多计算机图像分析算法的起点。一个算法是否成功往往由它使用和定义的特征决定。因此特征提取最重要的一个特性是“可重复性”:同一场景的不同图像所提取的特征应该是相同的。
常用的图像特征有颜色特征、纹理特征、形状特征和空间关系特征。
1.2 边缘
边缘是组成两个图像区域之间边界(或边缘)的像素。一般一个边缘的形状可以是任意的,还可能包括交叉点。在实践中边缘一般被定义为图像中拥有大的梯度的点组成的子集。一些常用的算法还会把梯度高的点联系起来构成一个更完善的边缘的描写。这些算法也可能对边缘提出一些限制。局部地看边缘是一维结构。
1.3 角
角是图像中点似的特征,在局部它有二维结构。早期的算法首先进行边缘检测,然后分析边缘的走向来寻找边缘突然转向即角。后来发展的算法不再需要边缘检测这个步骤,而是可以直接在图像梯度中寻找高度曲率。后来发现这样有时可以在图像中本来没有角的地方发现具有同角一样的特征的区域。
1.4 区域
与角不同的是区域描写一个图像中的一个区域性的结构,但是区域也可能仅由一个像素组成,因此许多区域检测也可以用来检测角。一个区域检测器检测图像中一个对于角检测器来说太平滑的区域,区域监测器可以被想象为把一张图像缩小,然后在缩小的图像上进行角检测。
1.5 脊
长条形的物体被称之为脊。在实践中脊可以被看作是代表对称轴的一维曲线,此外局部针对于每个脊像素有一个脊宽度。从灰梯度图像中提取脊要比提取边缘、角和区域困难。在空中摄影中往往使用脊检测来分辨道路,在医学图像中它被用来分辨血管。
二、图像匹配
2.1 定义
通过对影像内容、特征、结构、关系、纹理及灰度等的对应关系,相似性和一致性的分析,寻求相似影像目标的方法。
2.2 概述
图像匹配是指通过一定的匹配算法在两幅或多幅图像之间识别同名点,如二维图像匹配中通过比较目标区和搜索区中相同大小的窗口的相关系数,取搜索区中相关系数最大所对应的窗口中心点作为同名点。其实质是在基元相似性的条件下,运用匹配准则的最佳搜索问题。
三、基于特征点的特征描述子
接下来我们将分别通过Harris角点检测算法和SIFT特征检测算法来直观感受一下计算机是如何实现图像特征提取和图像匹配的。
四、Harris角点检测算法
4.1 概述
是一种基于图像灰度的方法通过计算点的曲率和梯度来检测角点。
4.2 原理
如果在各个方向上移动窗口,窗口中的灰度值都会发生较大变化,那么认定在窗口遇到了角点;如果在一个方向发生变化,另一个方向不变,就可能是一条直线;如果各个方向移动,窗口内灰度值都没有发生变化,不存在角点。
4.3 数学表达
假设图像像素点(x,y)的灰度为 I(x,y),以像素点为中心的窗口沿 x 和 y 方向分别移动 u 和 v 的灰度强度变化的表达式为:
其中 E(u,v)是灰度变化,w(x,y) 是窗口函数,一般是高斯函数,所以可以把w(x,y)看做是高斯滤波器。I(x,y)是图像灰度, I(x+u,y+v)是平移后的图像灰度。
受到泰勒公式的启发,在这里我们可以将 I(x+u,y+v)函数在(x,y)处泰勒展开,为了提高抗干扰的能力并且简化运算,我们取到了一阶导数部分,后面的无穷小量可以忽略,整理得到表达式如下:
将[ Ixu+Iyv ]展开后整理可以用矩阵表达为:
最后我们可以近似得到E(x,y)的表达式,将其化为二次型后得到:
其中M是一个2X2的矩阵,称为像素点的自相关矩阵,可以由图像的导数求得。M=窗口函数*偏导矩阵,表达式为:
4.4 代码实现
4.4.1 特征提取
# 局部图像描述子
# Harris角点检测
from pylab import *
from PIL import Image
from numpy import *
from scipy.ndimage import filters
def compute_harris_response(im, sigma=3):
"""在一幅灰度图像中,对每个像素计算Harris角点检测器响应函数"""
# 计算导数
imx = zeros(im.shape)
filters.gaussian_filter(im, (sigma, sigma), (0, 1), imx)
imy = zeros(im.shape)
filters.gaussian_filter(im, (sigma, sigma), (1, 0), imy)
# 计算Harris矩阵的分量
Wxx = filters.gaussian_filter(imx * imx, sigma)
Wxy = filters.gaussian_filter(imx * imy, sigma)
Wyy = filters.gaussian_filter(imy * imy, sigma)
# 计算特征值和迹
Wdet = Wxx * Wyy - Wxy ** 2
Wtr = Wxx + Wyy
return Wdet / Wtr
def get_harris_points(harrisim, min_dist=10, threshold=0.1):
"""从一幅Harris响应图像中返回角点。min_dist为分割角点和图像边界的最小像素数目"""
# 寻找高于阈值的候选角点
corner_threshold = harrisim.max() * threshold
harrisim_t = (harrisim > corner_threshold) * 1
# 得到候选点的坐标
coords = array(harrisim_t.nonzero()).T
# 以及它们的Harris响应值
candidate_values = [harrisim[c[0], c[1]] for c in coords]
# 对候选点按照Harris响应值进行排序
index = argsort(candidate_values)
# 将可行点的位置保存到数组中
allowed_locations = zeros(harrisim.shape)
allowed_locations[min_dist:-min_dist, min_dist:-min_dist] = 1
# 按照min_distance原则,选择最佳Harris点
filtered_coords = []
for i in index:
if allowed_locations[coords[i, 0], coords[i, 1]] == 1:
filtered_coords.append(coords[i])
allowed_locations[(coords[i, 0] - min_dist):(coords[i, 0] + min_dist),
(coords[i, 1] - min_dist):(coords[i, 1] + min_dist)] = 0
return filtered_coords
def plot_harris_points(image,filtered_coords):
"""绘制图像中检测到的角点"""
figure()
gray()
imshow(image)
plot([p[1] for p in filtered_coords],[p[0] for p in filtered_coords],'*')
axis('off')
show()
# 调用展示
im = array(Image.open('memorial_hall1.jpg').convert('L'))
harrisim = compute_harris_response(im)
filtered_coords = get_harris_points(harrisim,6, 0.05)
plot_harris_points(im, filtered_coords)
运行截图
4.4.2 图像匹配
from PIL import Image
from numpy import *
import harris
from pylab import *
wid=5
im1=array(Image.open('memorial_hall1.jpg').convert('L'))
im2=array(Image.open('memorial_hall2.jpg').convert('L'))
harrisim=harris.compute_harris_response(im1,5)
filtered_coords1=harris.get_harris_points(harrisim,wid+1,0.2)
d1=harris.get_descriptors(im1,filtered_coords1,wid)
harrisim=harris.compute_harris_response(im2,5)
filtered_coords2=harris.get_harris_points(harrisim,wid+1,0.2)
d2=harris.get_descriptors(im2,filtered_coords2,wid)
print ('starting matching')
运行截图
五、SIFT特征检测算法
5.1 概述
尺度不变特征转换即SIFT (Scale-invariant feature transform)是一种计算机视觉的算法。它用来侦测与描述影像中的局部性特征,它在空间尺度中寻找极值点,并提取出其位置、尺度、旋转不变量。
SIFT算法的实质是在不同的尺度空间上查找关键点(特征点),并计算出关键点的方向。SIFT所查找到的关键点是一些十分突出,不会因光照,仿射变换和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等。
5.2 原理
在不同的尺度空间上查找关键点,并计算出关键点的方向。
5.3 数学表达
L(x, y, σ) ,定义为原始图像 I(x, y)与一个可变尺度的2维高斯函数G(x, y, σ) 卷积运算。
*表示卷积运算,(x,y)代表图像的像素位置。是尺度空间因子,值越小表示图像被平滑的越少,相应的尺度也就越小。大尺度对应于图像的概貌特征,小尺度对应于图像的细节特征。
5.4 代码实现
from PIL import Image
from pylab import *
import sys
from PCV.localdescriptors import sift
if len(sys.argv) >= 3:
im1f, im2f = sys.argv[1], sys.argv[2]
else:
im1f = 'mansion1.jpg'
im2f = 'mansion2.jpg'
im1 = array(Image.open(im1f))
im2 = array(Image.open(im2f))
sift.process_image(im1f, 'out_sift_1.txt')
l1, d1 = sift.read_features_from_file('out_sift_1.txt')
figure()
gray()
subplot(121)
sift.plot_features(im1, l1, circle=False)
sift.process_image(im2f, 'out_sift_2.txt')
l2, d2 = sift.read_features_from_file('out_sift_2.txt')
subplot(122)
sift.plot_features(im2, l2, circle=False)
# matches = sift.match(d1, d2)
matches = sift.match_twosided(d1, d2)
print('{} matches'.format(len(matches.nonzero()[0])))
figure()
gray()
sift.plot_matches(im1, im2, l1, l2, matches, show_below=True)
show()
运行截图
来源:咸鱼不贤