liuwenliang的个人博客分享 http://blog.sciencenet.cn/u/liuwenliang

博文

[转载]opencv+python实现图像匹配----模板匹配、特征点匹配

已有 5936 次阅读 2022-9-29 17:29 |个人分类:深度学习|系统分类:科研笔记|文章来源:转载

转自:https://blog.csdn.net/zhuisui_woxin/article/details/84400439

文章目录

模板匹配与特征匹配

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

opencv+python模板匹配[^1]

匹配材料

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

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

opencv+python特征匹配[^2]

匹配材料

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

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

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

参考资料

模板匹配与特征匹配

模板匹配:模板匹配是一种最原始、最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识别对象物,这就是一个匹配问题。它是图像处理中最基本、最常用的匹配方法。模板匹配具有自身的局限性,主要表现在它只能进行平行移动,若原图像中的匹配目标发生旋转或大小变化,该算法无效。

特征匹配:所谓特征匹配(FBM),就是指将从影像中提取的特征作为共轭实体,而将所提特征属性或描述参数(实际上是特征的特征,也可以认为是影像的特征)作为匹配实体,通过计算匹配实体之间的相似性测度以实现共轭实体配准的影像匹配方法。在匹配目标发生旋转或大小变化时,该算法依旧有效。

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

#版本python 3.7.1

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

1

2

3

4

5

opencv+python模板匹配1

匹配材料

目标图片:target.jpg


模板图片:template.jpg


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

#opencv模板匹配----单目标匹配

import cv2

#读取目标图片

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

#读取模板图片

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

#获得模板图片的高宽尺寸

theight, twidth = template.shape[:2]

#执行模板匹配,采用的匹配方式cv2.TM_SQDIFF_NORMED

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

#归一化处理

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

#寻找矩阵(一维数组当做向量,用Mat定义)中的最大值和最小值的匹配结果及其位置

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

#匹配值转换为字符串

#对于cv2.TM_SQDIFF及cv2.TM_SQDIFF_NORMED方法min_val越趋近与0匹配度越好,匹配位置取min_loc

#对于其他方法max_val越趋近于1匹配度越好,匹配位置取max_loc

strmin_val = str(min_val)

#绘制矩形边框,将匹配区域标注出来

#min_loc:矩形定点

#(min_loc[0]+twidth,min_loc[1]+theight):矩形的宽高

#(0,0,225):矩形的边框颜色;2:矩形边框宽度

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

运行结果:


可以看到显示的min_val的值为0.0,说明完全匹配。


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

目标图片:target.jpg


#opencv模板匹配----多目标匹配

import cv2

import numpy

#读取目标图片

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

#读取模板图片

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

#获得模板图片的高宽尺寸

theight, twidth = template.shape[:2]

#执行模板匹配,采用的匹配方式cv2.TM_SQDIFF_NORMED

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

#归一化处理

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

#寻找矩阵(一维数组当做向量,用Mat定义)中的最大值和最小值的匹配结果及其位置

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

#绘制矩形边框,将匹配区域标注出来

#min_loc:矩形定点

#(min_loc[0]+twidth,min_loc[1]+theight):矩形的宽高

#(0,0,225):矩形的边框颜色;2:矩形边框宽度

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

#匹配值转换为字符串

#对于cv2.TM_SQDIFF及cv2.TM_SQDIFF_NORMED方法min_val越趋近与0匹配度越好,匹配位置取min_loc

#对于其他方法max_val越趋近于1匹配度越好,匹配位置取max_loc

strmin_val = str(min_val)

#初始化位置参数

temp_loc = min_loc

other_loc = min_loc

numOfloc = 1

#第一次筛选----规定匹配阈值,将满足阈值的从result中提取出来

#对于cv2.TM_SQDIFF及cv2.TM_SQDIFF_NORMED方法设置匹配阈值为0.01

threshold = 0.01

loc = numpy.where(result<threshold)

#遍历提取出来的位置

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

    #第二次筛选----将位置偏移小于5个像素的结果舍去

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

运行结果:



opencv+python特征匹配2

匹配材料

目标图片:target.jpg



模板图片:template_adjst.jpg



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

#opencv----特征匹配----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()#建立orb特征检测器

kp1,des1=orb.detectAndCompute(template,None)#计算template中的特征点和描述符

kp2,des2=orb.detectAndCompute(target,None) #计算target中的

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() #matplotlib描绘出来

1

2

3

4

5

6

7

8

9

10

11

12

13

14

基于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()#创建sift检测器

kp1, des1 = sift.detectAndCompute(queryImage,None)

kp2, des2 = sift.detectAndCompute(trainingImage,None)

#设置Flannde参数

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: #舍弃小于0.5的匹配结果

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

运行结果:



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

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

import numpy as np

import cv2

from matplotlib import pyplot as plt

 

MIN_MATCH_COUNT = 10 #设置最低特征点匹配数量为10

template = cv2.imread('template_adjust.jpg',0) # queryImage

target = cv2.imread('target.jpg',0) # trainImage

# Initiate SIFT detector创建sift检测器

sift = cv2.xfeatures2d.SIFT_create()

# find the keypoints and descriptors with SIFT

kp1, des1 = sift.detectAndCompute(template,None)

kp2, des2 = sift.detectAndCompute(target,None)

#创建设置FLANN匹配

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)

# store all the good matches as per Lowe's ratio test.

good = []

#舍弃大于0.7的匹配

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)

    #计算变换矩阵和MASK

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

运行结果:



参考资料

1.opencv英文版文档大全

2.opencv中文网、论坛

3.opencv的版本不对可能出现的一个错误


模板匹配英文版教程–opencv–version:3.4.2

模板匹配中文版教程–opencv–version:2.3.2 ↩︎


FLANN特征点匹配英文版教程–opencv–version:3.4.2

FLANN特征点匹配中文版教程–opencv–version:2.3.2 ↩︎

————————————————

版权声明:本文为CSDN博主「Demon_Hunter」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/zhuisui_woxin/article/details/84400439




https://blog.sciencenet.cn/blog-3409972-1357363.html

上一篇:[转载]python flask https协议使用方法
下一篇:USGS Landsat和哨兵2A数据下载
收藏 IP: 210.72.26.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-12-2 19:53

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部