Python中使用金字塔的快速模板匹配 我试图在Python中实现以下C++代码: 如果你检查C++代码,你会看到这个循环: for (int i = 0; i < contours.size(); i++) { cv::Rect r = cv::boundingRect(contours[i]); cv::matchTemplate( ref(r + (tpl.size() - cv::Size(1,1))), tpl, res(r), CV_TM_CCORR_NORMED ); }

Python中使用金字塔的快速模板匹配 我试图在Python中实现以下C++代码: 如果你检查C++代码,你会看到这个循环: for (int i = 0; i < contours.size(); i++) { cv::Rect r = cv::boundingRect(contours[i]); cv::matchTemplate( ref(r + (tpl.size() - cv::Size(1,1))), tpl, res(r), CV_TM_CCORR_NORMED ); },python,opencv,template-matching,Python,Opencv,Template Matching,当我不断得到以下信息时,出现了一些问题:ValueError:无法将输入数组从shape(53,51)广播到shape(52,52) 这个数字(53,51)(52,52)可能会改变,因为我只是稍微修改了结果或当前图像中的坐标,但这不是正确的答案 这是我当前的代码: import cv2 as cv import numpy as np import argparse import os """ This script performs a fast template matching algo

当我不断得到以下信息时,出现了一些问题:ValueError:无法将输入数组从shape(53,51)广播到shape(52,52)

这个数字(53,51)(52,52)可能会改变,因为我只是稍微修改了结果或当前图像中的坐标,但这不是正确的答案

这是我当前的代码:

import cv2 as cv
import numpy as np
import argparse
import os

"""
This script performs a fast template matching algorithm using the OpenCV
function matchTemplate plus an approximation through pyramid construction to
improve it's performance on large images.
"""

def buildPyramid(image, max_level):

    results = [image]
    aux = image

    for i in range(0,max_level):
        aux = cv.pyrDown(aux)
        results = [aux] + results

    return results


def temp_match(input, template, max_level):

    results = []

    source_pyr = buildPyramid(input, max_level)
    template_pyr = buildPyramid(template, max_level)

    for lvl in range(0, int(max_level), 1):

        curr_image = source_pyr[lvl]
        curr_template = template_pyr[lvl]

        dX = curr_image.shape[1] + 1 - curr_template.shape[1]
        dY = curr_image.shape[0] + 1 - curr_template.shape[0]

        result = np.zeros([dX, dY])


        #On the first level performs regular template matching.
        if lvl == 0:
            result = cv.matchTemplate(curr_image, curr_template,
                                      cv.TM_CCORR_NORMED)

        #On every other level, perform pyramid transformation and template
        #matching on the predefined ROI areas, obtained using the result of the
        #previous level.
        else:
            mask = cv.pyrUp(r)

            mask8u = cv.inRange(mask, 0, 255)
            contours = cv.findContours(mask8u, cv.RETR_EXTERNAL,
                                       cv.CHAIN_APPROX_NONE)

            #Uses contours to define the region of interest and perform TM on
            #the areas.

            for i in range(0, np.size(contours)-1):
                x, y, w, h = cv.boundingRect(contours[i][0])
                tpl_X = curr_template.shape[1]
                tpl_Y = curr_template.shape[0]

                #result = cv.matchTemplate(curr_image, curr_template,
                #                          cv.TM_CCORR_NORMED)

                result[y:y+h, x:x+w] = cv.matchTemplate(
                                curr_image[y:y+h+tpl_Y, x:x+w+tpl_X],
                                curr_template, cv.TM_CCORR_NORMED)

        T, r = cv.threshold(result, 0.94, 1., cv.THRESH_TOZERO)
        cv.imshow("test", r)
        cv.waitKey()
        results.append(r)
    return results


def ftm_pyramid(input_file, template_file, max_level = 5):

    if file_exists(input_file) == False:
        raise IOError("Input file not found.")

    if file_exists(template_file) == False:
        raise IOError("Input file not found.")

    img = cv.imread(input_file)
    tpl = cv.imread(template_file)

    image = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    template = cv.cvtColor(tpl, cv.COLOR_BGR2GRAY)

    tm_results = temp_match(image, template, max_level)

    c = 0
    flag = False

    while flag == False and c < np.size(tm_results):
        current = tm_results[c]
        min_val, max_val, min_loc, max_loc = cv.minMaxLoc(current)
        if max_val > 0.9:
            cv.rectangle(img,
                        max_loc,
                        (max_loc[0] + template.shape[1],
                         max_loc[1] + template.shape[0]),
                        (0,0,255), 2)
        else:
            flag = True

        c = c+1

    cv.imshow("Result", img)
    cv.waitKey()
    return 0


# Auxiliary methods

def file_exists(input_file):
    """
    :param input_file: path to the input file
    :return: true or false wether the file exists or not.
    """
    if input_file == '':
        raise ValueError("The input file can't be ''.")
    if input_file == None:
        raise ValueError("The input file can't be a None object")

    return os.path.isfile(input_file)


if __name__ == '__main__':
    #CLI arguments
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--input", required="True",
                    help="Path to the input image.")
    ap.add_argument("-t", "--template", required="True",
                    help="Path to the template image.")
    ap.add_argument("-l", "--levels", help="Number of levels of the pyramid.")
    args = vars(ap.parse_args())

    #Loading values
    input_file = args["input"]
    template = args["template"]
    max_lvl = args["levels"]

    if max_lvl == None:
        max_lvl = 5

    ftm_pyramid(input_file, template, max_lvl)
将cv2作为cv导入
将numpy作为np导入
导入argparse
导入操作系统
"""
此脚本使用OpenCV执行快速模板匹配算法
函数matchTemplate加上通过金字塔构造的近似值
提高它在大图像上的性能。
"""
def buildPyramid(图像,最高级别):
结果=[图像]
aux=图像
对于范围内的i(0,最大水平):
aux=cv.pyrDown(aux)
结果=[aux]+结果
返回结果
def温度匹配(输入、模板、最高液位):
结果=[]
source\u pyr=buildPyramid(输入,最大级别)
模板\u pyr=buildPyramid(模板,最大级别)
对于范围内的lvl(0,整数(最大值),1):
curr\u image=source\u pyr[lvl]
curr\u template=template\u pyr[lvl]
dX=当前图像.shape[1]+1-当前模板.shape[1]
dY=当前图像.shape[0]+1-当前模板.shape[0]
结果=np.零([dX,dY])
#在第一级执行常规模板匹配。
如果lvl==0:
结果=cv.matchTemplate(当前图像、当前模板、,
cv.TM\U CCORR\U标准)
#在每一层上,执行金字塔变换和模板转换
#在预定义的ROI区域上进行匹配,使用
#上一级。
其他:
遮罩=cv.pyrUp(r)
mask8u=cv.inRange(mask,0255)
等高线=等高线(mask8u、等高线外部、,
等速链条(约无)
#使用等高线定义感兴趣的区域并对其执行TM
#这些地区。
对于范围内的i(0,np.尺寸(轮廓)-1):
x、 y,w,h=cv.boundingRect(等高线[i][0])
tpl_X=当前模板形状[1]
tpl_Y=当前模板形状[0]
#结果=cv.matchTemplate(当前图像、当前模板、,
#cv.TM\U CCORR\U标准)
结果[y:y+h,x:x+w]=cv.matchTemplate(
当前图像[y:y+h+tpl\U y,x:x+w+tpl\U x],
当前模板,cv.TM(标准)
T、 r=cv.阈值(结果,0.94,1,cv.阈值为零)
简历:imshow(“测试”,r)
cv.waitKey()
结果。追加(r)
返回结果
def ftm_金字塔(输入文件、模板文件、最大级别=5):
如果文件存在(输入文件)=False:
raise IOError(“未找到输入文件”)
如果文件_存在(模板_文件)==False:
raise IOError(“未找到输入文件”)
img=cv.imread(输入文件)
tpl=cv.imread(模板文件)
图像=cv.CVT颜色(img,cv.COLOR\u bgr2灰色)
模板=cv.CVT颜色(tpl、cv.COLOR\u BGR2GRAY)
tm_结果=临时匹配(图像、模板、最大级别)
c=0
flag=False
而flag==False和c0.9:
等速矩形(img,
马克斯·卢克,
(最大位置[0]+模板形状[1],
最大位置[1]+模板形状[0],
(0,0,255), 2)
其他:
flag=True
c=c+1
简历imshow(“结果”,img)
cv.waitKey()
返回0
#辅助方法
def文件_存在(输入文件):
"""
:param input_file:输入文件的路径
:return:true或false,无论文件是否存在。
"""
如果输入文件=='':
raise VALUERROR(“输入文件不能为“”))
如果输入文件==无:
raise VALUERROR(“输入文件不能是无对象”)
返回os.path.isfile(输入文件)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
#CLI参数
ap=argparse.ArgumentParser()
ap.add_参数(“-i”,“--input”,required=“True”,
help=“输入图像的路径。”)
ap.add_参数(“-t”,“--template”,required=“True”,
help=“模板图像的路径。”)
ap.add_参数(“-l”,“--levels”,help=“金字塔的层数”)
args=vars(ap.parse_args())
#加载值
输入文件=args[“输入”]
模板=参数[“模板”]
最大值=args[“级别”]
如果最大值=无:
最大值=5
ftm_金字塔(输入文件、模板、最大层)

任何帮助都将不胜感激

在图像金字塔中进行图像模板匹配,从粗到精,这是许多领域的基本思想

您的代码有问题,我在参考原始CPP代码和Python代码的同时重写了代码


这是
参考图像
模板图像

这是
结果

我的代码在这里,请随时进行测试。
我不明白这是怎么回事,当在等高线上循环时,你用一个小补丁的TM覆盖结果,而不是更新结果中的相同补丁。你有没有把代码和非金字塔TM放在一起?
import cv2 as cv
import numpy as np
import argparse
import os

"""
This script performs a fast template matching algorithm using the OpenCV
function matchTemplate plus an approximation through pyramid construction to
improve it's performance on large images.
"""

def buildPyramid(image, max_level):

    results = [image]
    aux = image

    for i in range(0,max_level):
        aux = cv.pyrDown(aux)
        results = [aux] + results

    return results


def temp_match(input, template, max_level):

    results = []

    source_pyr = buildPyramid(input, max_level)
    template_pyr = buildPyramid(template, max_level)

    for lvl in range(0, int(max_level), 1):

        curr_image = source_pyr[lvl]
        curr_template = template_pyr[lvl]

        dX = curr_image.shape[1] + 1 - curr_template.shape[1]
        dY = curr_image.shape[0] + 1 - curr_template.shape[0]

        result = np.zeros([dX, dY])


        #On the first level performs regular template matching.
        if lvl == 0:
            result = cv.matchTemplate(curr_image, curr_template,
                                      cv.TM_CCORR_NORMED)

        #On every other level, perform pyramid transformation and template
        #matching on the predefined ROI areas, obtained using the result of the
        #previous level.
        else:
            mask = cv.pyrUp(r)

            mask8u = cv.inRange(mask, 0, 255)
            contours = cv.findContours(mask8u, cv.RETR_EXTERNAL,
                                       cv.CHAIN_APPROX_NONE)

            #Uses contours to define the region of interest and perform TM on
            #the areas.

            for i in range(0, np.size(contours)-1):
                x, y, w, h = cv.boundingRect(contours[i][0])
                tpl_X = curr_template.shape[1]
                tpl_Y = curr_template.shape[0]

                #result = cv.matchTemplate(curr_image, curr_template,
                #                          cv.TM_CCORR_NORMED)

                result[y:y+h, x:x+w] = cv.matchTemplate(
                                curr_image[y:y+h+tpl_Y, x:x+w+tpl_X],
                                curr_template, cv.TM_CCORR_NORMED)

        T, r = cv.threshold(result, 0.94, 1., cv.THRESH_TOZERO)
        cv.imshow("test", r)
        cv.waitKey()
        results.append(r)
    return results


def ftm_pyramid(input_file, template_file, max_level = 5):

    if file_exists(input_file) == False:
        raise IOError("Input file not found.")

    if file_exists(template_file) == False:
        raise IOError("Input file not found.")

    img = cv.imread(input_file)
    tpl = cv.imread(template_file)

    image = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    template = cv.cvtColor(tpl, cv.COLOR_BGR2GRAY)

    tm_results = temp_match(image, template, max_level)

    c = 0
    flag = False

    while flag == False and c < np.size(tm_results):
        current = tm_results[c]
        min_val, max_val, min_loc, max_loc = cv.minMaxLoc(current)
        if max_val > 0.9:
            cv.rectangle(img,
                        max_loc,
                        (max_loc[0] + template.shape[1],
                         max_loc[1] + template.shape[0]),
                        (0,0,255), 2)
        else:
            flag = True

        c = c+1

    cv.imshow("Result", img)
    cv.waitKey()
    return 0


# Auxiliary methods

def file_exists(input_file):
    """
    :param input_file: path to the input file
    :return: true or false wether the file exists or not.
    """
    if input_file == '':
        raise ValueError("The input file can't be ''.")
    if input_file == None:
        raise ValueError("The input file can't be a None object")

    return os.path.isfile(input_file)


if __name__ == '__main__':
    #CLI arguments
    ap = argparse.ArgumentParser()
    ap.add_argument("-i", "--input", required="True",
                    help="Path to the input image.")
    ap.add_argument("-t", "--template", required="True",
                    help="Path to the template image.")
    ap.add_argument("-l", "--levels", help="Number of levels of the pyramid.")
    args = vars(ap.parse_args())

    #Loading values
    input_file = args["input"]
    template = args["template"]
    max_lvl = args["levels"]

    if max_lvl == None:
        max_lvl = 5

    ftm_pyramid(input_file, template, max_lvl)
#!/usr/bin/python3
# 2017.10.04 14:50:50 CST START
# 2017.10.04 17:32:39 CST FINISH

import cv2
import numpy as np
import argparse
import os

def fileExists(filename):
    """Judge wether the file exists!
    """
    if filename in ('', None):
        raise ValueError("The input file can't be '' or None.")
    return os.path.isfile(filename)

def buildPyramid(image, maxleval):
    """Build image pyramid for level [0,...,maxlevel]
    """
    imgpyr = [image]
    aux = image
    for i in range(0,maxleval):
        aux = cv2.pyrDown(aux)
        imgpyr.append(aux)

    imgpyr.reverse()
    return imgpyr


def fastTemplateMatchPyramid(src_refimg, src_tplimg, maxleval):
    """Do fast template matching using matchTemplate plus an approximation
    through pyramid construction to improve it's performance on large images.
    """
    results = []

    ## Change BGR to Grayscale
    gray_refimg = cv2.cvtColor(src_refimg, cv2.COLOR_BGR2GRAY)
    gray_tplimg = cv2.cvtColor(src_tplimg, cv2.COLOR_BGR2GRAY)

    ## Build image pyramid
    refimgs = buildPyramid(gray_refimg, maxleval)
    tplimgs = buildPyramid(gray_tplimg, maxleval)

    ## Do template match
    for idx in range(0, maxleval+1):
        refimg = refimgs[idx]
        tplimg = tplimgs[idx]

        # On the first level performs regular template matching.
        # On every other level, perform pyramid transformation and template matching
        # on the predefined ROI areas, obtained using the result of the previous level.
        # Uses contours to define the region of interest and perform TM on the areas.
        if idx == 0:
            result = cv2.matchTemplate(refimg, tplimg, cv2.TM_CCORR_NORMED)
        else:
            mask = cv2.pyrUp(threshed)
            mask8u = cv2.inRange(mask, 0, 255)
            contours = cv2.findContours(mask8u, cv2.RETR_EXTERNAL,  cv2.CHAIN_APPROX_NONE)[-2]

            tH, tW = tplimg.shape[:2]
            for cnt in contours:
                x, y, w, h = cv2.boundingRect(cnt)
                src = refimg[y:y+h+tH, x:x+w+tW]
                result = cv2.matchTemplate(src, tplimg, cv2.TM_CCORR_NORMED)

        T, threshed = cv2.threshold(result, 0.90, 1., cv2.THRESH_TOZERO)
        results.append(threshed)

    return threshed
    #return results


def fastTemplateMatch(refname, tplname, maxleval = 5):
    """Fast template match.
    """
    ## Read the image pairs.
    if fileExists(refname) == False:
        raise IOError("Input file not found.")
    if fileExists(tplname) == False:
        raise IOError("Input file not found.")

    refimg = cv2.imread(refname)
    tplimg = cv2.imread(tplname)
    cv2.imwrite("cat.png",refimg)

    ## Call fastTemplateMatchInPyramid()
    result = fastTemplateMatchPyramid(refimg, tplimg, maxleval)

    ## Analysis the result
    minval, maxval, minloc, maxloc = cv2.minMaxLoc(result)
    if maxval > 0.9:
        pt1 = maxloc
        pt2 = (maxloc[0] + tplimg.shape[1], maxloc[1] + tplimg.shape[0])
        print("Found the template region: {} => {}".format(pt1,pt2))
        dst = refimg.copy()
        cv2.rectangle(dst, pt1, pt2, (0,255,0), 2)
        cv2.imshow("Result", dst)
        cv2.imwrite("template_matching_result.png",dst)
        cv2.waitKey()
    else:
        print("Cannot find the template in the origin image!")


if __name__ == '__main__':
    ## CLI arguments
    """
    ap = argparse.ArgumentParser()
    ap.add_argument("-r", "--referer", required="True",
                    help="Path to the referer image.")
    ap.add_argument("-t", "--template", required="True",
                    help="Path to the template image.")
    ap.add_argument("-l", "--levels", help="Number of levels of the pyramid.")
    args = vars(ap.parse_args())

    ## Loading values
    refname = args["referer"]
    tplname = args["template"]
    maxlevel = args["levels"]
    """
    ## Set parmeters
    refname = "/home/auss/Pictures/cat.jpg"
    tplname = "cat_face.png"
    maxlevel = 5

    ## call the function
    fastTemplateMatch(refname, tplname, maxlevel)