opencv+python图像匹配——模版匹配、特征点匹配

最近在做图像检测上的项目,需要进行图像匹配的相关内容,查阅了opencv的匹配方法,整理了模版匹配和特征点匹配的内容,并总结成博客。

模版匹配与特征点匹配

  • 模板匹配
    模版匹配是一种最原始、最基本的识别方法。简单来说,模板匹配就是用一幅已知的模板图片在目标图片上 依次滑动(类似于滑窗法),每次滑动都计算模板与模板下方的目标子图的 相似度
    但模板匹配具有一定的局限性,也是我在实际操作时发现的。局限性主要表现在 模版图片只能在目标图标上进行平行移动,若原图像中的匹配目标发生旋转或大小变化,该算法无效。也就是说,如果模版图片和目标子图上的方向、大小不一致,则无法匹配成功。
  • 特征点匹配
    特征匹配(FBM),也称为角点匹配,就是指将从影像中提取的特征作为共轭实体,而将所提特征属性或描述参数(实际上是特征的特征)作为匹配实体,通过计算匹配实体之间的相似性测度以实现共轭实体配准的影像匹配方法。即指 寻找两幅图像之间的特征像素点的对应关系,从而确定图像的位置关系。
    在匹配目标发生旋转或大小变化时,该算法依旧有效。

模版匹配

模板匹配就是用一幅已知的模板图片在目标图片上 依次滑动(类似于滑窗法),每次滑动都计算模板与模板下方的目标子图的 相似度

如果是单个目标的匹配,只需要取相似度最大值所在的位置就可以得到匹配位置。

如果要匹配多个目标,设定一个合理的阈值,只要相似度大于阈值则认为是匹配的目标。


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

matchTemplate提供了六种 模版匹配方法

  • cv2.TM_SQDIFF(差值平方和匹配):该方法计算模板与某个子图的对应像素的差值平方和。因此最佳的匹配结果在结果为0处,越相似值越小,值越大匹配结果越差。
  • cv2.TM_SQDIFF_NORMED(标准化差值平方和匹配):该方法使用归一化的平方差进行匹配,最佳匹配也在结果为0处。
  • cv2.TM_CCORR(相关匹配法):该方法使用源图像与模板图像的卷积结果进行匹配,因此,最佳匹配位置在值最大处,值越小匹配结果越差。
  • cv2.TM_CCORR_NORMED(归一化相关匹配):归一化的相关性匹配方法,去除了亮度线性变化对相似度计算的影响。可以保证图像和模板同时变量或变暗k倍时结果不变。与相关性匹配方法类似,最佳匹配位置也是在值最大处,越相似值越大。
  • cv2.TM_CCOEFF(相关性系数匹配方法):该方法使用源图像与其均值的差、模板与其均值的差二者之间的相关性进行匹配,最佳匹配结果在值等于1处,最差匹配结果在值等于-1处,值等于0直接表示二者不相关。
  • cv2.TM_CCOEFF_NORMED(归一化的相关性系数匹配方法):把图像和模板都减去了各自的平均值,再各自除以各自的方差,保证图像和模板分别改变光照不影响计算结果,计算出的相关系数限制在-1到1之间,1 表示完全相同,-1 表示两幅图像的亮度正好相反,0 表示没有线性关系。负值表示效果不好,正值表示匹配效果好。

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

FLANN特征点匹配

对图片提取SIFT特征并利用FLANN方法判别图像的相似度并可视化。

基于FLANN的匹配器(FLANN based Matcher)的特征匹配。FLANN库全称是Fast Library for Approximate Nearest Neighbors,它是目前最完整的(近似)最近邻开源库。不但实现了一系列查找算法,还包含了一种自动选取最快算法的机制。

  • 使用SIFT特征提取关键点;
  • 计算SIFT特征描述子;
  • 使用FLANN匹配器进行描述子向量匹配。

SIFT的大概流程描述:
在图中选择出一些比较有特色的点,并把他们编码成特征向量,现在要做两个图的特征点匹配,所以要用SIFT对两个图分别做特征点选择,并且每个特征点编码成相同维度的特征向量,比如都是长度为512的向量。两个图上的特征点数量是不一样的,比如第一个图有3个特征点,第二个图有5个特征点,要做特征点匹配的话,计算第一个图中3个点跟第二个图里的5个点两两之间的距离,这个距离一般就是向量的欧式距离。特征点匹配中,就是要找两个图中比较相似的特征点,特征点的特征向量越相近,说明这两个点附近的情况就越相似。

ratio test 筛选的思想:
首先找到图一中某一个特征点在图二中的最相似点和次相似点,然后把最相近点的距离跟次相近点的距离相除,获得一个 ratio,这个值从直观上理解就是,最相近点比次相近点 更加相似的程度。ratio越小,就表示相近点比次相近点要更加相似很多,相反ratio越大,就表示相近点比次相近点都是一般相似。ratio test就是用ratio值去筛选,它认为: ratio小于一个特定的阈值,这对特征点匹配才会被接受,否则就筛选掉。因为ratio小的特征点对,说明最相近点比其它匹配点(次相近点在这里就代表了其它所有的特征点)都要明显很多,说明这一对匹配是非常有特色的,是可以保留的,保留了基本不会错,因为没有其它干扰因素;ratio比较大的时候,就说明这对匹配是存疑的,把最相近点换成次相近点的相似度也差不多,所以无法断定这一对特征点有没有匹配错,那么就把其筛选掉。Lowe推荐ratio的阈值为0.8。

我这边是有五个类的模版图,在目标图中进行特征匹配,判断属于哪一个类。我的思路则是依次进行特征匹配,比较最后特征点对点多少,从而判断更接近哪一类别。

import cv2
import os
from matplotlib import pyplot as plt

def FLANN():

    targetPath = 'target.jpg'
    trainingImage = cv2.imread(targetPath, flags=0)

    templatePath = 'templatePath/'
    icons = os.listdir(templatePath)
    iconMatch= dict({'name': '未识别', 'value': 0})
    for icon in icons:
        queryImage = cv2.imread(templatePath + icon, 0)

        sift = cv2.SIFT_create()
        kp1, des1 = sift.detectAndCompute(queryImage, None)
        kp2, des2 = sift.detectAndCompute(trainingImage, None)

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

        matchesMask = [[0,0] for i in range(len(matches))]
        matchNumber = 0

        for i,(m,n) in enumerate(matches):
            if m.distance < 0.7 * n.distance:
                matchesMask[i] = [1,0]
                matchNumber = matchNumber+1

        drawParams = dict(matchColor = (0,255,0), matchesMask = matchesMask[:50], flags = 0)
        resultImage = cv2.drawMatchesKnn(queryImage,kp1,trainingImage,kp2,matches[:50],None,**drawParams)

        if matchNumber > iconMatch['value']:
            iconMatch['name'] = icon.split('_')[0]
            iconMatch['value'] = matchNumber

    return resultImage, iconMatch

if __name__ == '__main__':
    resultImage, res = FLANN()
    plt.imshow(resultImage)
    plt.show()

Original: https://blog.csdn.net/qq_42368281/article/details/121865115
Author: 看星星的月儿
Title: opencv+python图像匹配——模版匹配、特征点匹配

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

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

(0)

大家都在看

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