c# 联合halcon 基于相关性 模板匹配_Python-OpenCV 17. 图像匹配算法

本系列文章是学习《机器学习实践指南 案例应用分析 第2版》的笔记。

一、定义

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

1. 灰度匹配(模板匹配)

灰度匹配的基本思想:以统计的观点将图像看成是二维信号,采用统计相关的方法寻找信号间的相关匹配。利用两个信号的相关函数,评价它们的相似性以确定同名点。
灰度匹配通过利用某种相似性度量,如相关函数、协方差函数、差平方和、差绝对值和等测度极值,判定两幅图像中的对应关系。
最经典的灰度匹配法是归一化的灰度匹配 法,其基本原理是逐像素的把一个以一定大小的实时图像窗口的灰度矩阵,与参考图像的所有可能的窗口灰度阵列,按某种相似性度量方法进行搜索比较的匹配方法,从理论上说就是采用图像相关技术。
利用灰度信息匹配方法的主要缺陷是计算量太大,因为使用场合一般都有一定的速度要求,所以这些方法很少被使用。现在已经提出了一些相关的快速算法,如幅度排序相关算法,FFT相关算法和分层搜索的序列判断算法等。
基于灰度匹配的算法有:MAD、SAD、SSD、MSD、NCC、SSDA、SATD、LBD算法等。

2. 特征匹配

特征匹配是指通过分别提取两个或多个图像的特征(点、线、面等特征),对特征进行参数描述,然后运用所描述的参数来进行匹配的一种算法。
基于特征的匹配所处理的图像一般包含的特征有颜色特征、纹理特征、形状特征、空间位置特征等。
特征匹配首先对图像进行预处理来提取其高层次的特征,然后建立两幅图像之间特征的匹配对应关系,通常使用的特征基元有点特征、边缘特征和区域特征。 特征匹配需要用到许多诸如矩阵的运算、梯度的求解、还有傅立叶变换和泰勒展开等数学运算。
常用的特征提取与匹配方法有:统计方法、几何法、模型法、信号处理法、边界特征法、傅氏形状描述法、几何参数法、形状不变矩法等。

3. 比较

特征匹配与灰度匹配的区别:灰度匹配是基于像素的,特征匹配则是基于区域的,特征匹配在考虑像素灰度的同时还应考虑诸如空间整体特征、空间关系等因素。

——以上内容摘自百度百科

二、模板匹配

1. 几种常见的模板匹配算法:

c# 联合halcon 基于相关性 模板匹配_Python-OpenCV 17. 图像匹配算法_第1张图片
  1. TM_SQDIFF是平方差匹配;TM_SQDIFF_NORMED是标准平方差匹配。利用平方差来进行匹配,最好匹配为0.匹配越差,匹配值越大。
  2. TM_CCORR是相关性匹配;TM_CCORR_NORMED是标准相关性匹配。采用模板和图像间的乘法操作,数越大表示匹配程度较高, 0表示最坏的匹配效果。
  3. TM_CCOEFF是相关性系数匹配;TM_CCOEFF_NORMED是标准相关性系数匹配。将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列)。

原始图片:

source.jpg

c# 联合halcon 基于相关性 模板匹配_Python-OpenCV 17. 图像匹配算法_第2张图片

target.jpg

c# 联合halcon 基于相关性 模板匹配_Python-OpenCV 17. 图像匹配算法_第3张图片

原型:matchTemplate(image, templ, method[, result[, mask]]) -> result

  • image参数表示待搜索源图像,必须是8位整数或32位浮点。
  • templ参数表示模板图像,必须不大于源图像并具有相同的数据类型。
  • method参数表示计算匹配程度的方法。
  • result参数表示匹配结果图像,必须是单通道32位浮点。如果image的尺寸为W x H,templ的尺寸为w x h,则result的尺寸为(W-w+1)x(H-h+1)。

2. 单目标匹配

#opencv模板匹配----单目标匹配import cv2#读取目标图片target = cv2.imread("source.jpg")#读取模板图片template = cv2.imread("target.jpg")#获得模板图片的高宽尺寸theight, twidth = template.shape[:2]#执行模板匹配,采用的匹配方式cv2.TM_SQDIFF_NORMEDresult = 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_locstrmin_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()

效果:

c# 联合halcon 基于相关性 模板匹配_Python-OpenCV 17. 图像匹配算法_第4张图片

3. 多目标匹配

#opencv模板匹配----多目标匹配import cv2import numpy#读取目标图片target = cv2.imread("source.jpg")#读取模板图片template = cv2.imread("target.jpg")#获得模板图片的高宽尺寸theight, twidth = template.shape[:2]#执行模板匹配,采用的匹配方式cv2.TM_SQDIFF_NORMEDresult = 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_locstrmin_val = str(min_val)#初始化位置参数temp_loc = min_locother_loc = min_locnumOfloc = 1#第一次筛选----规定匹配阈值,将满足阈值的从result中提取出来#对于cv2.TM_SQDIFF及cv2.TM_SQDIFF_NORMED方法设置匹配阈值为0.01threshold = 0.01loc = numpy.where(result

三、差分矩阵进行图像匹配

1. 差分矩阵求和

差分矩阵=图像A矩阵数据−图像B矩阵数据
差分算法的核心在于差分矩阵,实质为差异矩阵。
算法过程是:
首先,计算两个图像的矩阵数据之间差异分析图像的相似性;然后,设置一个阈值进行比较,如果差分矩阵的所有元素之和在阈值以内,则表示这两张图像是相似的,且描述了同一物体。

# - * - coding: utf-8 - * -# 简单定位图像import cv2import numpy as npprint('loading')def showpiclocation(img,findimg): # 定位图像 w = img.shape[1] h = img.shape[0] fw = findimg.shape[1] fh = findimg.shape[0] findpt = None for now_h in range(0,h-fh): for now_w in range(0, w-fw): comp_tz = img[now_h:now_h+fh,now_w:now_w+fw,:]-findimg if np.sum(comp_tz) <1: findpt = now_w,now_h print('.',) if findpt != None: print('fw is %d' % fw) cv2.rectangle(img, findpt, (findpt[0]+fw, findpt[1]+fh),(255,0,0)) return imgfn = 'source.jpg'fn1 = 'target.jpg'myimg = cv2.imread(fn)myimg1 = cv2.imread(fn1)myimgf = showpiclocation(myimg,myimg1)cv2.namedWindow('img')cv2.imshow('img',myimgf)cv2.waitKey()cv2.destroyAllWindows()

原图:

c# 联合halcon 基于相关性 模板匹配_Python-OpenCV 17. 图像匹配算法_第5张图片


查找:

c# 联合halcon 基于相关性 模板匹配_Python-OpenCV 17. 图像匹配算法_第6张图片

结果:

c# 联合halcon 基于相关性 模板匹配_Python-OpenCV 17. 图像匹配算法_第7张图片

2. 差分矩阵均值

当数字图像质量较差时,则需要计算差分矩阵的均值,并为均值设一个适当的阈值。

差分矩阵的阈值一般为10~200,阈值越大,能容忍的噪声点越多。如果阈值超过200,最好使用欧氏距离算法。

# - * - coding: utf-8 - * -# 少量噪声定位图像import cv2import numpy as npprint('loading...')def showpiclocation(img,findimg): # 定位图像 w = img.shape[1] h = img.shape[0] fw = findimg.shape[1] fh = findimg.shape[0] findpt = None for now_h in range(0,h-fh): for now_w in range(0,w-fw): comp_tz = img[now_h:now_h+fh,now_w:now_w+fw,:]-findimg if abs(np.mean(comp_tz))<20: //差分矩阵的阈值 findpt=now_w,now_h print('ok') print ('.') if findpt != None: cv2.rectangle(img,findpt,(findpt[0]+fw, findpt[1]+fh),(0,0,255)) return imgdef addnoise(img): coutn = 5000 for k in range(0,coutn): xi = int(np.random.uniform(0,img.shape[1])) xj = int(np.random.uniform(0,img.shape[0])) img[xj,xi,0] = 255*np.random.rand() img[xj,xi,1] = 255*np.random.rand() img[xj,xi,2] = 255*np.random.rand()fn = 'source.jpg'fn1 = 'target.jpg'myimg = cv2.imread(fn)myimg1 = cv2.imread(fn1)addnoise(myimg)myimgf = showpiclocation(myimg,myimg1)cv2.namedWindow('img')cv2.imshow('img',myimgf)cv2.waitKey()cv2.destroyAllWindows()

四、欧氏距离匹配

1. 强噪声图像匹配

在强噪声时,欧氏距离匹配方法相对于差分矩阵的方法会有更好的效果。

# -*- coding: utf-8 -*-import cv2import numpy as npdef get_EuclideanDistance(x, y): myx = np.array(x) myy = np.array(y) return np.sqrt(np.sum((myx - myy)*(myx - myy)))def findpic(img,findimg , h,fh,w,fw): minds=1e8 mincb_h=0 mincb_w=8 for now_h in range(0,h-fh): for now_w in range(0,w-fw): my_img = img[now_h:now_h+fh,now_w:now_w+fw,:] my_findimg = findimg dis = get_EuclideanDistance(my_img , my_findimg) if dis < minds: mincb_h=now_h mincb_w=now_w minds = dis print('.',) findpt = mincb_w,mincb_h cv2.rectangle(img, findpt, (findpt[0]+fw,findpt[1]+fh),(0,0,255)) return imgdef showpiclocation(img,findimg): #定位图像 w = img.shape[1] h= img.shape[0] fw = findimg.shape[1] fh = findimg.shape[0] return findpic(img,findimg,h,fh,w,fw)def addnoise(img): coutn = 500000 for k in range(0,coutn): xi = int(np.random.uniform(0,img.shape[1])) xj = int(np.random.uniform(0,img.shape[0])) img[xj,xi,0] = 255 * np.random.rand() img[xj,xi,1] = 255 * np.random.rand() img[xj,xi,2] = 255 * np.random.rand()fn = 'source.jpg'fn1 = 'target.jpg'myimg = cv2.imread(fn)myimg1 = cv2.imread(fn1)addnoise(myimg)myimg = showpiclocation(myimg, myimg1)cv2.namedWindow('img')cv2.imshow('img',myimg)cv2.waitKey()cv2.destroyAllWindows()
c# 联合halcon 基于相关性 模板匹配_Python-OpenCV 17. 图像匹配算法_第8张图片

2. 变形图像匹配

代码同上,可以自行将图形变形,查看匹配效果。

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

#基于FLANN的匹配器(FLANN based Matcher)定位图片import numpy as npimport cv2from matplotlib import pyplot as plt MIN_MATCH_COUNT = 10 #设置最低特征点匹配数量为10template = cv2.imread('source.jpg',0) # queryImagetarget = cv2.imread('target.jpg',0) # trainImage# Initiate SIFT detector创建sift检测器sift = cv2.xfeatures2d.SIFT_create()# find the keypoints and descriptors with SIFTkp1, des1 = sift.detectAndCompute(template,None)kp2, des2 = sift.detectAndCompute(target,None)#创建设置FLANN匹配FLANN_INDEX_KDTREE = 0index_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 = Nonedraw_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()cv2.imshow('result',result)cv2.waitKey(0)cv2.destroyWindows()

原图:

c# 联合halcon 基于相关性 模板匹配_Python-OpenCV 17. 图像匹配算法_第9张图片

查找:

c# 联合halcon 基于相关性 模板匹配_Python-OpenCV 17. 图像匹配算法_第10张图片

查找结果:

c# 联合halcon 基于相关性 模板匹配_Python-OpenCV 17. 图像匹配算法_第11张图片

六、opencv的函数minMaxLoc

在给定的矩阵中寻找最大和最小值,并给出它们的位置。 该功能不适用于多通道阵列。 如果您需要在所有通道中查找最小或最大元素,要先将阵列重新解释为单通道。

函数minMaxLoc原型为:minMaxLoc(src[, mask]) -> minVal, maxVal, minLoc, maxLoc

  • src参数表示输入单通道图像。
  • mask参数表示用于选择子数组的可选掩码。
  • minVal参数表示返回的最小值,如果不需要,则使用NULL。
  • maxVal参数表示返回的最大值,如果不需要,则使用NULL。
  • minLoc参数表示返回的最小位置的指针(在2D情况下); 如果不需要,则使用NULL。
  • maxLoc参数表示返回的最大位置的指针(在2D情况下); 如果不需要,则使用NULL。

你可能感兴趣的:(c#,联合halcon,基于相关性,模板匹配,c#图像用内存法实现浮雕处理,双向最大匹配算法python)