Python计算机视觉之特征提取与图像匹配

目录

Python计算机视觉之特征提取与图像匹配

一、特征提取

1.1 定义

特征提取是计算机视觉和图像处理中的一个概念。它指的是使用计算机提取图像信息,决定图像中的每一个点是否属于该图像的一个特征。 特征提取的结果是把图像上的点分为不同的 子集,这些子集往往属于 孤立的点连续的曲线或者 连续的区域

那么,什么样的点才能称之为特征呢?

至今为止特征并没有绝对精确的定义。特征的精确定义往往由问题或者应用类型决定。特征是一个数字图像中”有趣”(ROI)的部分,它是许多计算机图像分析算法的起点。一个算法是否成功往往由它使用和定义的特征决定。因此特征提取最重要的一个特性是” 可重复性“:同一场景的不同图像所提取的特征应该是相同的。

常用的图像特征有 颜色特征纹理特征形状特征空间关系特征

1.2 边缘

边缘是组成两个图像区域之间边界(或边缘)的像素
一般一个边缘的形状可以是任意的,还可能包括交叉点。在实践中边缘一般被定义为图像中拥有 大的梯度的点组成的子集。一些常用的算法还会把梯度高的点联系起来构成一个更完善的边缘的描写。这些算法也可能对边缘提出一些限制。局部地看边缘是一维结构。

1.3 角

角是图像中 点似的特征,在局部它有 二维结构
早期的算法首先进行边缘检测,然后分析边缘的走向来寻找边缘突然转向即角。后来发展的算法不再需要边缘检测这个步骤,而是可以直接在图像梯度中寻找 高度曲率。后来发现这样有时可以在图像中本来没有角的地方发现具有同角一样的特征的区域。

1.4 区域

与角不同的是区域描写一个图像中的一个 区域性的结构,但是区域也可能仅由一个像素组成,因此许多区域检测也可以用来检测角。一个区域检测器检测图像中一个对于角检测器来说太平滑的区域,区域监测器可以被想象为把一张图像缩小,然后在缩小的图像上进行角检测。

1.5 脊

长条形的物体被称之为脊。在实践中脊可以被看作是 代表对称轴的一维曲线,此外局部针对于 每个脊像素有一个 脊宽度。从灰梯度图像中提取脊要比提取边缘、角和区域困难。
在空中摄影中往往使用脊检测来分辨道路,在医学图像中它被用来分辨血管。

二、图像匹配

2.1 定义

通过对影像内容、特征、结构、关系、纹理及灰度等的对应关系,相似性和一致性的分析,寻求相似影像目标的方法。

2.2 概述

图像匹配是指通过一定的匹配算法在两幅或多幅图像之间识别同名点,如二维图像匹配中通过比较目标区和搜索区中相同大小的窗口的相关系数,取搜索区中相关系数最大所对应的窗口中心点作为同名点。其实质是在 基元相似性的条件下,运用匹配准则的最佳搜索问题。

三、基于特征点的特征描述子

从不同的距离,不同的方向、角度,不同的光照条件下观察一个物体时,物体的大小,形状,敏感都会有所不同。但我们依然可以判断它是同一物体。
理想的 特征描述子应该具备这些性质。即,在大小、方向、明暗不同的图像中,同一特征点应具有足够相似的描述子,称之为描述子的可复现性。
接下来我们将分别通过 Harris角点检测算法SIFT特征检测算法来直观感受一下计算机是如何实现图像特征提取和图像匹配的。

四、Harris角点检测算法

4.1 概述

是一种基于图像灰度的方法通过计算点 的曲率和梯度来检测角点。

4.2 原理

如果在各个方向上移动窗口,窗口中的灰度值都会发生较大变化,那么认定在窗口遇到了角点;如果在一个方向发生变化,另一个方向不变,就可能是一条直线;如果各个方向移动,窗口内灰度值都没有发生变化,不存在角点。

Python计算机视觉之特征提取与图像匹配

; 4.3 数学表达

假设图像 像素点(x,y)的 灰度为 I(x,y),以像素点为中心的窗口沿 x 和 y 方向分别移动 u 和 v 的灰度强度变化的表达式为:

Python计算机视觉之特征提取与图像匹配
其中 E(u,v)是灰度变化,w(x,y) 是窗口函数,一般是高斯函数,所以可以把w(x,y)看做是高斯滤波器(注:高斯滤波就是对整幅图像进行加权平均的过程)。I(x,y)是图像灰度, I(x+u,y+v)是平移后的图像灰度。
受到泰勒公式的启发,在这里我们可以将 I(x+u,y+v)函数在(x,y)处泰勒展开,为了提高抗干扰的能力并且简化运算,我们取到了一阶导数部分,后面的无穷小量可以忽略,整理得到表达式如下:
Python计算机视觉之特征提取与图像匹配
将[ Ixu+Iyv ]展开后整理可以用矩阵表达为:
Python计算机视觉之特征提取与图像匹配
Python计算机视觉之特征提取与图像匹配
其中M是一个2X2的矩阵,称为像素点的自相关矩阵,可以由图像的导数求得。M=窗口函数*偏导矩阵,表达式为:
Python计算机视觉之特征提取与图像匹配

4.4 代码实现

4.4.1 特征提取


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)

    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

    candidate_values = [harrisim[c[0], c[1]] for c in coords]

    index = argsort(candidate_values)

    allowed_locations = zeros(harrisim.shape)
    allowed_locations[min_dist:-min_dist, min_dist:-min_dist] = 1

    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)

注意:示例代码运行有bug,RuntimeWarning: invalid value encountered in divide
return Wdet/Wtr
运行截图

Python计算机视觉之特征提取与图像匹配

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')

运行截图

Python计算机视觉之特征提取与图像匹配

五、SIFT特征检测算法

5.1 概述

尺度不变特征转换即SIFT (Scale-invariant feature transform)是一种计算机视觉的算法。它用来侦测与描述影像中的局部性特征,它在空间尺度中寻找 极值点,并提取出其位置、尺度、 旋转不变量

SIFT算法的实质是 在不同的尺度空间上查找关键点(特征点),并计算出关键点的方向。SIFT所查找到的关键点是一些十分突出,不会因光照,仿射变换和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等。

5.2 原理

在不同的尺度空间上查找关键点,并计算出关键点的方向。

Python计算机视觉之特征提取与图像匹配

; 5.3 数学表达

L(x, y, σ) ,定义为原始图像 I(x, y)与一个可变尺度的2维高斯函数G(x, y, σ) 卷积运算。

Python计算机视觉之特征提取与图像匹配
_表示_卷积运算,(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_twosided(d1, d2)
print('{} matches'.format(len(matches.nonzero()[0])))

figure()
gray()
sift.plot_matches(im1, im2, l1, l2, matches, show_below=True)
show()

运行截图

Python计算机视觉之特征提取与图像匹配
Python计算机视觉之特征提取与图像匹配

opencv+python实现图像匹配—-模板匹配、特征点匹配

模板匹配与特征匹配

模板匹配:模板匹配是一种最原始、最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识别对象物,这就是一个匹配问题。它是图像处理中最基本、最常用的匹配方法。模板匹配具有自身的 局限性,主要表现在它 只能_进行 _平行移动,若原图像中的匹配目标发生旋转或大小变化,该算法无效。
特征匹配:所谓 特征匹配(FBM),就是指将从影像中提取的特征作为共轭实体,而将所提特征属性或描述参数(实际上是特征的特征,也可以认为是影像的特征)作为匹配实体,通过计算匹配实体之间的相似性测度以实现 共轭实体配准的影像匹配方法。在匹配目标发生旋转或大小变化时,该算法依旧有效。

python的版本及依赖的库的安装


pip install numpy==1.15.3
pip install matplotlib==3.0.1
pip install opencv-python==3.4.2.16
pip install opencv-contrib-python==3.4.2.16

opencv+python模板匹配1

匹配材料

目标图片:target.jpg

Python计算机视觉之特征提取与图像匹配
模板图片:template.jpg
Python计算机视觉之特征提取与图像匹配

; 模板匹配Template Matching—-单目标匹配


import cv2

target = cv2.imread("target.jpg")

template = cv2.imread("template.jpg")

theight, twidth = template.shape[:2]

result = cv2.matchTemplate(target,template,cv2.TM_SQDIFF_NORMED)

cv2.normalize( result, result, 0, 1, cv2.NORM_MINMAX, -1 )

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

strmin_val = str(min_val)

cv2.rectangle(target,min_loc,(min_loc[0]+twidth,min_loc[1]+theight),(0,0,225),2)

cv2.imshow("MatchResult----MatchingValue="+strmin_val,target)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果: 代码没跑通,需要调试!

Python计算机视觉之特征提取与图像匹配
可以看到显示的min_val的值为0.0,说明完全匹配。

模板匹配Template Matching—-多目标匹配

目标图片:target.jpg

Python计算机视觉之特征提取与图像匹配

import cv2
import numpy

target = cv2.imread("target.jpg")

template = cv2.imread("template.jpg")

theight, twidth = template.shape[:2]

result = cv2.matchTemplate(target,template,cv2.TM_SQDIFF_NORMED)

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

cv2.rectangle(target,min_loc,(min_loc[0]+twidth,min_loc[1]+theight),(0,0,225),2)

strmin_val = str(min_val)

temp_loc = min_loc
other_loc = min_loc
numOfloc = 1

threshold = 0.01
loc = numpy.where(result<threshold)

for other_loc in zip(*loc[::-1]):

    if (temp_loc[0]+5<other_loc[0])or(temp_loc[1]+5<other_loc[1]):
        numOfloc = numOfloc + 1
        temp_loc = other_loc
        cv2.rectangle(target,other_loc,(other_loc[0]+twidth,other_loc[1]+theight),(0,0,225),2)
str_numOfloc = str(numOfloc)

strText = "MatchResult----MatchingValue="+strmin_val+"----NumberOfPosition="+str_numOfloc
cv2.imshow(strText,target)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果:未测试

Python计算机视觉之特征提取与图像匹配

opencv+python特征匹配2

匹配材料

目标图片:target.jpg

Python计算机视觉之特征提取与图像匹配
模板图片:template_adjst.jpg
Python计算机视觉之特征提取与图像匹配

; BFMatching描述特征点–运行结果不精确


import cv2
from matplotlib import pyplot as plt

template=cv2.imread("template_adjust.jpg",0)
target=cv2.imread("target.jpg",0)
orb=cv2.ORB_create()
kp1,des1=orb.detectAndCompute(template,None)
kp2,des2=orb.detectAndCompute(target,None)
bf = cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck=True)
mathces=bf.match(des1,des2)
mathces=sorted(mathces,key=lambda x:x.distance)
result= cv2.drawMatches(template,kp1,target,kp2,mathces[:40],None,flags=2)
plt.imshow(result),plt.show()

基于FLANN的匹配器(FLANN based Matcher)描述特征点


'''
基于FLANN的匹配器(FLANN based Matcher)
1.FLANN代表近似最近邻居的快速库。它代表一组经过优化的算法,用于大数据集中的快速最近邻搜索以及高维特征。
2.对于大型数据集,它的工作速度比BFMatcher快。
3.需要传递两个字典来指定要使用的算法及其相关参数等
对于SIFT或SURF等算法,可以用以下方法:
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
对于ORB,可以使用以下参数:
index_params= dict(algorithm = FLANN_INDEX_LSH,
                   table_number = 6, # 12   这个参数是searchParam,指定了索引中的树应该递归遍历的次数。值越高精度越高
                   key_size = 12,     # 20
                   multi_probe_level = 1) #2
'''
import cv2 as cv
from matplotlib import pyplot as plt
queryImage=cv.imread("template_adjust.jpg",0)
trainingImage=cv.imread("target.jpg",0)
sift=cv.xfeatures2d.SIFT_create()
kp1, des1 = sift.detectAndCompute(queryImage,None)
kp2, des2 = sift.detectAndCompute(trainingImage,None)

FLANN_INDEX_KDTREE=0
indexParams=dict(algorithm=FLANN_INDEX_KDTREE,trees=5)
searchParams= dict(checks=50)
flann=cv.FlannBasedMatcher(indexParams,searchParams)
matches=flann.knnMatch(des1,des2,k=2)

matchesMask=[[0,0] for i in range (len(matches))]
for i, (m,n) in enumerate(matches):
    if m.distance< 0.5*n.distance:
        matchesMask[i]=[1,0]
drawParams=dict(matchColor=(0,0,255),singlePointColor=(255,0,0),matchesMask=matchesMask,flags=0)
resultimage=cv.drawMatchesKnn(queryImage,kp1,trainingImage,kp2,matches,None,**drawParams)
plt.imshow(resultimage,),plt.show()

Python计算机视觉之特征提取与图像匹配

基于FLANN的匹配器(FLANN based Matcher)定位图片


import numpy as np
import cv2
from matplotlib import pyplot as plt

MIN_MATCH_COUNT = 10
template = cv2.imread('template_adjust.jpg',0)
target = cv2.imread('target.jpg',0)

sift = cv2.xfeatures2d.SIFT_create()

kp1, des1 = sift.detectAndCompute(template,None)
kp2, des2 = sift.detectAndCompute(target,None)

FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1,des2,k=2)

good = []

for m,n in matches:
    if m.distance < 0.7*n.distance:
        good.append(m)
if len(good)>MIN_MATCH_COUNT:

    src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
    dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)

    M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
    matchesMask = mask.ravel().tolist()
    h,w = template.shape

    pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
    dst = cv2.perspectiveTransform(pts,M)
    cv2.polylines(target,[np.int32(dst)],True,0,2, cv2.LINE_AA)
else:
    print( "Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT))
    matchesMask = None
draw_params = dict(matchColor=(0,255,0),
                   singlePointColor=None,
                   matchesMask=matchesMask,
                   flags=2)
result = cv2.drawMatches(template,kp1,target,kp2,good,None,**draw_params)
plt.imshow(result, 'gray')
plt.show()

运行结果:

Python计算机视觉之特征提取与图像匹配

参考资料

  1. opencv英文版文档大全
  2. opencv中文网、论坛
  3. opencv的版本不对可能出现的一个错误

Original: https://blog.csdn.net/wu_zhiyuan/article/details/126028766
Author: wu_zhiyuan
Title: Python计算机视觉之特征提取与图像匹配

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/632315/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球