Python 3.x OpenCV无法将模板与图像匹配(匹配模板)

Python 3.x OpenCV无法将模板与图像匹配(匹配模板),python-3.x,opencv,computer-vision,matchtemplate,Python 3.x,Opencv,Computer Vision,Matchtemplate,所以我有一个图像 和一个模板 我想在图像中找到模板图像,但是我的代码没有找到任何东西。我试着缩小尺寸,但还是没有发现。请帮我举个例子: import cv2 import imutils import glob, os import numpy as np image = cv2.imread("mainimage.png") gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) h, w = gray.shape[:2] for file in g

所以我有一个图像

和一个模板

我想在图像中找到模板图像,但是我的代码没有找到任何东西。我试着缩小尺寸,但还是没有发现。请帮我举个例子:

import cv2
import imutils
import glob, os
import numpy as np

image = cv2.imread("mainimage.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
h, w = gray.shape[:2]
for file in glob.glob("template.png"):
    template = cv2.imread(file)
    template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
    found = None
    (tH, tW) = template.shape[:2]
    cv2.imshow("Template", template)

    for scale in np.linspace(1, 0.2, 20)[::-1]:
        resized = imutils.resize(gray, width=int(gray.shape[1] * scale))
        r = gray.shape[1] / float(resized.shape[1])

        if resized.shape[0] < tH or resized.shape[1] < tW:
            break
        edged = cv2.Canny(resized, 50, 200)
        result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF)
        (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)

        if found is None or maxVal > found[0]:
            found = (maxVal, maxLoc, r)

    (_, maxLoc, r) = found
    (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r))
    (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r))
    cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2)
    cv2.imshow("Image", image)
    cv2.waitKey(0)
导入cv2
导入imutils
导入全局操作系统
将numpy作为np导入
image=cv2.imread(“mainimage.png”)
灰色=cv2.CVT颜色(图像,cv2.COLOR\u BGR2GRAY)
h、 w=灰色。形状[:2]
对于glob.glob(“template.png”)中的文件:
模板=cv2.imread(文件)
模板=cv2.CVT颜色(模板,cv2.COLOR\u BGR2GRAY)
找到=无
(tH,tW)=模板形状[:2]
cv2.imshow(“模板”,模板)
对于np.linspace(1,0.2,20)[:-1]中的比例:
resized=imutils.resize(灰色,宽度=int(灰色.shape[1]*比例))
r=gray.shape[1]/浮动(已调整大小的.shape[1])
如果调整了.shape[0]found[0]:
找到=(maxVal、maxLoc、r)
(u,maxLoc,r)=找到
(startX,startY)=(int(maxLoc[0]*r),int(maxLoc[1]*r))
(endX,endY)=(int((maxLoc[0]+tW)*r),int((maxLoc[1]+tH)*r))
cv2.矩形(图像,(startX,startY),(endX,endY),(0,0,255),2)
cv2.imshow(“图像”,图像)
cv2.等待键(0)

您的代码基本上是好的。在您发布的代码中,您的缩放方式错误。您正在缩小主映像,而不是扩大它。此外,您还需要对模板和图像进行精明处理

在您发布的图像中,模板(160x160)比主图像中的区域(88x88)大。如果缩放mainimage,则缩放因子应为1.818。扩展模板可能会快得多

import cv2
# import imutils
import glob, os
import numpy as np

image = cv2.imread("mainimage.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
h, w = gray.shape[:2]
for file in glob.glob("template.png"):
    template = cv2.imread(file)
    template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
    found = None
    (tH, tW) = template.shape[:2]
    # cv2.imshow("Template", template)

    tEdged = cv2.Canny(template, 50, 200)

    for scale in np.linspace(1, 2, 20):
        # resized = imutils.resize(gray, width=int(gray.shape[1] * scale))
        resized = cv2.resize(gray, dsize = (0,0), fx = scale, fy = scale)

        r = gray.shape[1] / float(resized.shape[1])

        if resized.shape[0] < tH or resized.shape[1] < tW:
            break
        edged = cv2.Canny(resized, 50, 200)
        result = cv2.matchTemplate(edged, tEdged, cv2.TM_CCOEFF)
        (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)

        if found is None or maxVal > found[0]:
            found = (maxVal, maxLoc, r)

    (_, maxLoc, r) = found
    (startX, startY) = (int(maxLoc[0] * r), int(maxLoc[1] * r))
    (endX, endY) = (int((maxLoc[0] + tW) * r), int((maxLoc[1] + tH) * r))
    cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2)

    # cv2.imshow("Image", image)
    cv2.imwrite('output.jpg', image)
    # ~ cv2.waitKey(0)
导入cv2
#导入imutils
导入全局操作系统
将numpy作为np导入
image=cv2.imread(“mainimage.png”)
灰色=cv2.CVT颜色(图像,cv2.COLOR\u BGR2GRAY)
h、 w=灰色。形状[:2]
对于glob.glob(“template.png”)中的文件:
模板=cv2.imread(文件)
模板=cv2.CVT颜色(模板,cv2.COLOR\u BGR2GRAY)
找到=无
(tH,tW)=模板形状[:2]
#cv2.imshow(“模板”,模板)
tEdged=cv2.Canny(模板,50200)
对于np.linspace(1,2,20)中的比例:
#resized=imutils.resize(灰色,宽度=int(灰色.shape[1]*比例))
调整大小=cv2。调整大小(灰色,dsize=(0,0),fx=比例,fy=比例)
r=gray.shape[1]/浮动(已调整大小的.shape[1])
如果调整了.shape[0]found[0]:
找到=(maxVal、maxLoc、r)
(u,maxLoc,r)=找到
(startX,startY)=(int(maxLoc[0]*r),int(maxLoc[1]*r))
(endX,endY)=(int((maxLoc[0]+tW)*r),int((maxLoc[1]+tH)*r))
cv2.矩形(图像,(startX,startY),(endX,endY),(0,0,255),2)
#cv2.imshow(“图像”,图像)
cv2.imwrite('output.jpg',image)
#~cv2.waitKey(0)
在我的电脑上,这个代码运行需要6秒钟

关键点匹配+单应 作为替代方案,关键点匹配+单应性对比例不敏感。在以下代码中,dst保留包含找到的模板的边界框的点。对我来说,以下代码在0.06秒内执行:

import cv2
# import imutils
import glob, os
import numpy as np
import time

image = cv2.imread("mainimage.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
h, w = gray.shape[:2]

MIN_MATCH_COUNT = 3

start_time = time.time()

for file in glob.glob("template.png"):
    template = cv2.imread(file, 0)

    patchSize = 16

    orb = cv2.ORB_create(edgeThreshold = patchSize, 
                            patchSize = patchSize)
    kp1, des1 = orb.detectAndCompute(template, None)
    kp2, des2 = orb.detectAndCompute(gray, None)

    FLANN_INDEX_LSH = 6
    index_params= dict(algorithm = FLANN_INDEX_LSH,
               table_number = 6,
               key_size = 12,    
               multi_probe_level = 1)
    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 = []

    for pair in matches:
        if len(pair) == 2:
            if pair[0].distance < 0.7*pair[1].distance:
                good.append(pair[0])

    print('len(good) ', len(good))
    print('match %03d, min_match %03d, kp %03d' % (len(good), MIN_MATCH_COUNT, len(kp1)))
    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)
        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)

        # dst contains points of bounding box of template in image. 
        # draw a close polyline around the found template:
        image = cv2.polylines(image,[np.int32(dst)], 
                              isClosed = True,
                              color = (0,255,0),
                              thickness = 3, 
                              linetype = cv2.LINE_AA)                    
    else:
        print( "Not enough matches are found - {}/{}".format(len(good), MIN_MATCH_COUNT) )
        matchesMask = None

    draw_params = dict(matchColor = (0,255,0), # draw matches in green color
               singlePointColor = None,
               matchesMask = matchesMask, # draw only inliers
               flags = 2)

    if len(good)>MIN_MATCH_COUNT:
        output2 = cv2.drawMatches(template,kp1,gray,kp2,good,None,**draw_params)

    print('elapsed time ', time.time()-start_time)
    # cv2.imshow("Image", image)
    cv2.imwrite('output_homography.jpg', image)
    cv2.imwrite('output2.jpg', output2)
导入cv2
#导入imutils
导入全局操作系统
将numpy作为np导入
导入时间
image=cv2.imread(“mainimage.png”)
灰色=cv2.CVT颜色(图像,cv2.COLOR\u BGR2GRAY)
h、 w=灰色。形状[:2]
最小匹配计数=3
开始时间=time.time()
对于glob.glob(“template.png”)中的文件:
模板=cv2.imread(文件,0)
补丁大小=16
orb=cv2.orb_创建(edgeThreshold=patchSize,
补丁大小=补丁大小)
kp1,des1=orb.detectAndCompute(模板,无)
kp2,des2=球形检测和计算(灰色,无)
法兰指数=6
索引参数=dict(算法=法兰索引),
表_编号=6,
键大小=12,
多探头(水平=1)
搜索参数=dict(检查=50)
flann=cv2.FlannBasedMatcher(索引参数、搜索参数)
匹配=法兰N.knnMatch(des1、des2、k=2)
#根据Lowe比率测试存储所有良好匹配项。
好的=[]
对于配对:
如果len(对)==2:
如果对[0]。距离<0.7*对[1]。距离:
好。追加(对[0])
打印('len(good'),len(good))
打印('匹配%03d,最小匹配%03d,kp%03d'(长度(良好),最小匹配计数,长度(kp1)))
如果长度(良好)>最小匹配计数:
src_pts=np.float32([kp1[m.queryIdx].pt代表m处于良好状态])。重塑(-1,1,2)
dst_pts=np.float32([kp2[m.trainIdx].pt代表m处于良好状态])。重塑(-1,1,2)
M、 掩模=cv2.findHomography(src_pts,dst_pts,cv2.RANSAC,5.0)
matchesMask=mask.ravel().tolist()
h、 w=模板形状
pts=np.float32([[0,0],[0,h-1],[w-1,h-1],[w-1,0]])。重塑(-1,1,2)
dst=cv2.透视变换(pts,M)
#dst包含图像中模板边界框的点。
#围绕找到的样板绘制闭合多段线:
图像=cv2.多段线(图像[np.int32(dst)],
isClosed=True,
颜色=(0255,0),
厚度=3,
线型=cv2.LINE_AA)
其他:
打印(“没有找到足够的匹配项-{}/{}”。格式(len(good),MIN_MATCH_COUNT))
matchesMask=None
绘制参数=dict(匹配颜色=(0255,0),#绘制绿色的匹配
singlePointColor=无,
matchesMask=matchesMask,#只绘制内线
旗帜=2)
如果长度(良好)>最小匹配计数:
欧点