值越接近1,匹配程度越高

发布时间:2025-06-24 19:36:10  作者:北方职教升学中心  阅读量:043


2.1单目标匹配

单目标匹配只获取一个结果,即匹配程度最高的那一个

matchTemplate()方法计算的结果是一个二维数组,OpenCV提供了minMaxLoc()方法用于解析这个二维数组中的最大值、 

2.单模板匹配

单模板匹配是指匹配过程中只用到一个模板场景,在原始图像中可能只有一个和模板相似的图像,也可能有多个,如果只获取匹配程度最高的那一个,这种操作就叫单目标匹配,如果同时获取匹配程度较高的结果,这种操作就叫多目标匹配。最佳匹配是在结果矩阵中的最大值处找到的。结果矩阵中的每个元素都表示模板在原图中对应位置的匹配程度,具体取决于所选的比较方法。这使得比较不同大小的图像或模板时更为方便。互相关值越大,匹配程度越高。高度和通道数results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED) # 按照标准相关系数匹配for y in range(len(results)): # 遍历结果数组的行 for x in range(len(results[y])): # 遍历结果数组的列 if results[y][x] > 0.99: # 如果相关系数大于0.99则认为匹配成功 # 在最佳匹配结果位置绘制红色方框 cv2.rectangle(img, (x, y), (x + width, y + height), (0, 0, 255), 2)cv2.imshow("img", img) # 显示匹配的结果cv2.waitKey() cv2.destroyAllWindows()

操作效果图像:

 

2.2.2多目标匹配实例(统计一条快轨线路的站台总数)

操作用图像:

背景图像:

模板图像:

操作代码示例:

import cv2image = cv2.imread(r"C:\Users\cgs\Desktop\pictures\image.png")  # 读取原始图像templ = cv2.imread(r"C:\Users\cgs\Desktop\pictures\templ.png")  # 读取模板图像height, width, c = templ.shape  # 获取模板图像的高度、归一化后的值在-1(完全不相关)到1(完全相关)之间。
4.记录相似图像:如果相似度超过90%,则记录匹配的图像索引。 

操作效果:

2.2多目标匹配

多目标匹配需要将原始图像中所有与模板相似的图像都找出来。最小值坐标和最大值坐标minValue, maxValue, minLoc, maxLoc = cv2.minMaxLoc(results)resultPoint1 = minLoc # 将最小值坐标当做最佳匹配区域的左上角点坐标# 计算出最佳匹配区域的右下角点坐标resultPoint2 = (resultPoint1[0] + width, resultPoint1[1] + height)# 在最佳匹配区域位置绘制蓝色方框,线宽为2像素cv2.rectangle(img, resultPoint1, resultPoint2, 255, 0, 0)cv2.imshow("img", img) # 显示匹配的结果cv2.waitKey() cv2.destroyAllWindows()

操作效果图像

 

2.1.2 选择最佳的匹配结果

操作用图像

模板图像:

背景图像1:

、相关系数是归一化的协方差,其值在-1(负相关)到1(正相关)之间。(4)

6.归一化系数匹配(cv2.TM_CCOEFF_NORMED)

      与系数匹配类似,但结果会被进一步归一化到0(完全不相关)到1(完全相关)的范围内。
5.输出结果:最后,输出所有找到的相同图像的文件名列表。(0)

2.归一化平方差匹配(cv2.TM_SQDIFF_NORMED)

      与平方差匹配类似,但结果会被归一化到0(完全不匹配)到1(完美匹配)的范围内。最大值、因此,最佳匹配是在结果矩阵中的最小值处找到的。

temp1:模板图像,其尺寸不得大于原始图像

method:匹配的方法,详情见下表

mask:可选参数。

3.1 同时匹配多个模板

操作用图像:

背景图像:

模板图像:

操作代码示例:

import cv2def myMatchTemplate(img, templ):  # 自定义方法:获取模板匹配成功后所有红框位置的坐标    width, height, c = templ.shape  # 获取模板图像的宽度、

背景图像2:

操作代码示例:

import cv2image = []  # 存储原始图像的列表# 向image列表添加原始图像221image.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\10(3).png"))# 向image列表添加原始图像222image.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\10(4).png"))templ = cv2.imread(r"C:\Users\cgs\Desktop\pictures\10(5).png")  # 读取模板图像index = -1  # 初始化车位编号列表的索引为-1min = 1for i in range(0, len(image)):  # 循环匹配image列表中的原始图像    # 按照标准平方差方式匹配    results = cv2.matchTemplate(image[i], templ, cv2.TM_SQDIFF_NORMED)    # 获得最佳匹配结果的索引    if min > any(results[0]):        index = icv2.imshow("result", image[index])  # 显示最佳匹配结果cv2.waitKey()  cv2.destroyAllWindows()  

操作效果图像:

2.1.3 查找重复图像

操作代码示例:

import cv2import osimport sysPIC_PATH = "C:\\Users\\cgs\\Desktop\\pictures"  # 照片文件夹地址width, height = 100, 100  # 缩放比例pic_file = os.listdir(PIC_PATH)  # 所有照片文件列表same_pic_index = []  # 相同图像的索引列表imgs = []  # 缩放后的图像对象列表has_same = set()  # 相同图像的集合count = len(pic_file)  # 照片数量if count == 0:  # 如果照片数量为零    print("没有图像")    sys.exit(0)  # 停止程序for file_name in pic_file:  # 遍历照片文件    pic_name = os.path.join(PIC_PATH, file_name)  # 拼接完整文件名    img = cv2.imread(pic_name)  # 创建文件的图像    if img is None:        print(f"Error: {pic_name} not found or unable to load.")        continue    img = cv2.resize(img, (width, height))  # 缩放成统一大小    imgs.append(img)  # 按文件顺序保存图像对象for i in range(count):  # 遍历所有图像文件    if i in has_same:  # 如果此图像已经找到相同的图像        continue  # 跳过    templ = imgs[i]  # 取出模板图像    same = [i]  # 与templ内容相同的图像索引列表    for j in range(i + 1, count):  # 从templ的下一个位置开始遍历        if j in has_same:  # 如果此图像已经找到相同的图像            continue  # 跳过        pic = imgs[j]  # 取出对照图像        results = cv2.matchTemplate(pic, templ, cv2.TM_CCOEFF_NORMED)  # 比较两图像相似度        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(results)        if max_val > 0.9:  # 如果相似度大于90%,认为是同一张照片            same.append(j)  # 记录对照图像的索引            has_same.add(i)  # 模板图像已找到相同图像            has_same.add(j)  # 对照图像已找到相同图像    if len(same) > 1:  # 如果模板图像找到了至少一张与自己相同的图像        same_pic_index.append(same)  # 记录相同图像的索引for same_list in same_pic_index:  # 遍历所有相同图像的索引    text = "相同的照片:"    for same in same_list:        text += str(pic_file[same]) + ", "  # 拼接文件名    text = text.rstrip(", ")  # 去掉最后的逗号和空格    print(text)

代码的工作流如下:

1.读取图像:从指定文件夹读取所有图像文件,并将它们存储在列表中。(3)

5.系数匹配(cv2.TM_CCOEFF)

       此方法通过计算模板与图像区域之间的相关系数来进行匹配。(1)

3.相关匹配(cv2.TM_CCORR)

      此方法通过计算模板与图像区域之间的互相关来进行匹配。
2.图像缩放:将每张图像缩放到统一的尺寸,以便进行比较。最佳匹配同样是在结果矩阵中的最小值处找到的。最小值以及这两个值对应的坐标,其语法结构如下:

minValue,MaxValue, minLoc,maxLoc = cv2.minMaxLoc(src, mask)

参数说明:

src:matchTemplate()方法计算的出的数组

mask:可选参数,掩模

返回值说明:

minValue:数组的最小值

maxValue:数组的最大值

minLoc:最小值的坐标

maxLoc:最大值的坐标

2.1.1 标识出匹配成功的区域

操作用图像:原始图像

模板图片:

操作代码示例

import cv2img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\10(1).jpg")  # 读取原始图像templ = cv2.imread(r"C:\Users\cgs\Desktop\pictures\10(2).png")  # 读取模板图像width, height, c = templ.shape  # 获取模板图像的宽度、(2)

4.归一化相关匹配(cv2.TM_CCORR_NORMED)

       与相关匹配类似,但结果会被归一化。
3.模板匹配:逐一将每张图像作为模板,与后续图像进行相似度比较。

OpenCV提供了matchTemplate()方法来实现目标匹配,其语法结构如下:

result = matchTemplate(iamge, temp1,method, mask)

参数说明:

iamge:原始图像,必须是单通道,8位或32位浮点图像。高度和通道数results = cv2.matchTemplate(img, templ, cv2.TM_SQDIFF_NORMED) # 按照标准平方差方式匹配# 获取匹配结果中的最小值、因此,最佳匹配是在结果矩阵中的最大值处找到的。因此,最佳匹配是在结果矩阵中的最大值处找到的。(5)

在模板匹配的过程中,模板会在原始图像中移动,并与重叠区域内的像素诸葛对比,最后将对比结果保存在模板左上角像素点索引位置对应的数组位置中。这种归一化使得比较结果更加直观和一致。具体来说,如果源图像的大小是(W, H),模板的大小是(w, h),则结果矩阵的大小将是(W-w+1, H-h+1)。掩模,只有cv2.TM_SQDIFF和cv2.TM_CCORR_NORMED支持此参数

返回值说明:

函数返回的结果result是一个矩阵,其大小取决于源图像和模板的相对大小。最佳匹配同样是在结果矩阵中的最大值处找到的。

1.模板匹配方法

模板是指被查找的目标图像,查找模板出现在原始图像中哪个位置的过程就叫模板匹配。

1.平方差匹配(cv2.TM_SQDIFF)

      此方法通过计算模板与图像区域之间的平方差来进行匹配。

2.2.1 标识出所有匹配成功的区域

 操作用图像:

背景图像:

 

模板图像:

操作代码示例:

import cv2img = cv2.imread(r"C:\Users\cgs\Desktop\pictures\1(52).jpg")  # 读取原始图像templ = cv2.imread(r"C:\Users\cgs\Desktop\pictures\1 (2).png")  # 读取模板图像width, height, c = templ.shape  # 获取模板图像的宽度、平方差越小,匹配程度越高。值越接近1,匹配程度越高。高度和通道数    results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED)  # 按照标准相关系数匹配    loc = list()  # 红框的坐标列表    for i in range(len(results)):  # 遍历结果数组的行        for j in range(len(results[i])):  # 遍历结果数组的列            if results[i][j] > 0.99:  # 如果相关系数大于0.99则认为匹配成功                # 在列表中添加匹配成功的红框对角线两点坐标                loc.append((j, i, j + width, i + height))    return locimg = cv2.imread(r"C:\Users\cgs\Desktop\pictures\background2.jpg")  # 读取原始图像templs = list()  # 模板列表templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\template.png"))  # 添加模板1templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\template2.png"))  # 添加模板2templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\template3.png"))  # 添加模板3loc = list()  # 所有模板匹配成功位置的红框坐标列表for t in templs:  # 遍历所有模板    loc += myMatchTemplate(img, t)  # 记录该模板匹配得出的for i in loc:  # 遍历所有红框的坐标    cv2.rectangle(img, (i[0], i[1]), (i[2], i[3]), (0, 0, 255), 2)  # 在图片中绘制红框cv2.imshow("img", img)  # 显示匹配的结果cv2.waitKey()cv2.destroyAllWindows()  


操作效果图像:

3.2 多模板匹配实例

操作用图像

模板图像:

背景图像:

操作代码示例:

import cv2image = cv2.imread(r"C:\Users\cgs\Desktop\pictures\image.png")  # 读取原始图像templs = []  # 模板列表templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\car1.png"))  # 添加模板图像1templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\car2.png"))  # 添加模板图像2templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\car3.png"))  # 添加模板图像3templs.append(cv2.imread(r"C:\Users\cgs\Desktop\pictures\car4.png"))  # 添加模板图像3for car in templs:  # 遍历所有模板图像    # 按照标准相关系数匹配    results = cv2.matchTemplate(image, car, cv2.TM_CCOEFF_NORMED)    for i in range(len(results)):  # 遍历结果数组的行        for j in range(len(results[i])):  # 遍历结果数组的列            # print(results[i][j])            if results[i][j] > 0.99:  # 如果相关系数大于0.99则认为匹配成功                if 0 < j <= 140:                    print("车位编号:", 1)                elif j <= 330:                    print("车位编号:", 2)                elif j <= 500:                    print("车位编号:", 3)                else:                    print("车位编号:", 4)                break

操作效果图像:

那么关于模板匹配的内容就到这里了欢迎大家继续关注!!!

这使得比较更加灵活,特别是当模板和图像之间的亮度差异很大时。宽度和通道数results = cv2.matchTemplate(image, templ, cv2.TM_CCOEFF_NORMED) # 按照标准相关系数匹配station_Num = 0 # 初始化快轨的站台个数为0for y in range(len(results)): # 遍历结果数组的行 for x in range(len(results[y])): # 遍历结果数组的列 if results[y][x] > 0.99: # 如果相关系数大于0.99则认为匹配成功 # 在最佳匹配结果位置绘制矩形边框 cv2.rectangle(image, (x, y), (x + width, y + height), (0, 0, 255), 2) station_Num += 1 # 快轨的站台个数加1cv2.putText(image, "the numbers of stations: " + str(station_Num), (0, 30), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (255, 0, 0), 2) # 在原始图像绘制快轨站台的总数cv2.imshow("result", image) # 显示匹配的结果cv2.waitKey() cv2.destroyAllWindows()


操作效果图像:

3.多模板匹配

对每一个模板都要做一次“单模板多目标匹配”。