python,如何将模板透明图像与opencv匹配

qacovj5a  于 2022-11-15  发布在  Python
关注(0)|答案(1)|浏览(248)

我使用matchtemplate在后台检测67x45 sqaure。我认为我的代码工作正常,没有任何问题,但问题是我必须为它设置高阈值才能成功检测,否则它会给予这么多的错误检测。所以我尝试将方法改为cv2.TM_CCOEFF_NORMED,但它没有很好地工作。我也试着寻找opencv文档来了解所有这些方法是如何工作的,但对我来说真的很难理解,因为它们只提供数学公式。所以我的问题是我对我的代码没问题吗?或者有没有更好的方法来完成我想做的事情?(我也不确定我是否以正确的方式在matchtemplate中使用“template”参数)

import cv2
import numpy as np 
import win32gui, win32ui, win32con

    
def imagesearch(per):

    filename = 'target.png'

    img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
    img1 = cv2.imread(filename)

    template = cv2.imread('./map/6745.png', cv2.IMREAD_GRAYSCALE)

    w, h = template.shape[::-1]

    meth = [cv2.TM_CCOEFF, cv2.TM_CCOEFF_NORMED, cv2.TM_CCORR, cv2.TM_CCORR_NORMED, cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]

    res = cv2.matchTemplate(img, template, meth[3], None, template)

    threshold = per 
    loc = np.where(res>=threshold)

    if loc[0].any():


        for pt in zip(*loc[::-1]):
            cv2.rectangle(img1, pt, (pt[0] + w, pt[1] + h), (0,0,255), 1) 

    cv2.imshow("dst", img1)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

imagesearch(0.99)

影像

样板

阈值= 0.99的结果

阈值= 0.95的结果
正如“克里斯托弗·拉克维茨”所说,

import cv2
import numpy as np 
import win32gui, win32ui, win32con

def imagesearch():

    filename = 'target.png'

    img = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
    img1 = cv2.imread(filename)

    template = cv2.imread('./map/6745.png', cv2.IMREAD_GRAYSCALE)

    w, h = template.shape[::-1]

    meth = [cv2.TM_CCOEFF, cv2.TM_CCOEFF_NORMED, cv2.TM_CCORR, cv2.TM_CCORR_NORMED, cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]

    method = meth[5]
    res = cv2.matchTemplate(img, template, meth[5], None, template)

    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:

        min_val,max_val,min_loc, max_loc = cv2.minMaxLoc(res)
        top_left = min_loc
         
        bottom_right = (top_left[0]+w,top_left[1]+h)
        cv2.rectangle(img1,top_left,bottom_right,255,1)

    cv2.imshow("dst", img1)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

imagesearch()

这个也不行。


指令集

cyvaqqii

cyvaqqii1#

  • 我使用匹配模板来检测背景上的67x45正方形。*

在边界盒状矩形的特殊情况下,使用自己的方法直接在numpy图像阵列上工作来检测它是有意义的,而不是使用OpenCV匹配函数与模板图像以及应对不同的匹配算法和阈值。
下面的代码可以检测任意数量的矩形,这些矩形的边长为模板图像中给定形状的一个像素宽。它适用于任何矩形的线条颜色,因此无论它是黑色背景上的白色矩形还是明亮背景上的黑色矩形,或者矩形的灰度值是否等于背景的灰度值,都没有关系,因为它使用了全色信息。
为了简化搜索条件,图像的BGR元组被转换为表示RGB颜色的单个整数值,因此用于搜索算法的图像阵列是纯2D阵列(就像使用灰度时一样)。
为了确保不检测单色背景中的矩形,检查矩形左上角的一个内部像素,并且必须具有另一种颜色作为矩形。这种情况可能导致未检测到矩形,并且随后需要检查多个像素。但是如果需要的话,可以容易地将检查扩展到多于一个像素,并将其实现到所检查的条件的序列中。并且如果背景图像不具有矩形大小的单色的大区域,则像素检查可以从检查的条件的序列中完全去除。
提供的代码中的Python循环可能会被矢量化的numpy方法所取代,因此欢迎对如何实现这一点发表评论。

import cv2
import numpy as np 

img_filename = "openCV_squareOnBackground.png"
ibgr = cv2.imread(img_filename, cv2.IMREAD_UNCHANGED)
assert ibgr.shape[2] == 3
sizeY, sizeX, _ = ibgr.shape 
# Convert uint8 BGR tuples to uint32 value: 
iint32 = np.dstack((ibgr, np.zeros(ibgr.shape[:2], 'uint8'))).view('uint32').squeeze(-1)

img_filename = "openCV_squareOnBackground_template.png"
grey_t = cv2.imread(img_filename, cv2.IMREAD_GRAYSCALE)
t_sizeY, t_sizeX = grey_t.shape

rectAt = []
for x in range(sizeX - t_sizeX):
    for y in range(sizeY - t_sizeY):
        if \
           (iint32[y,x] == iint32[y+1:y+t_sizeY  ,x              ]).all() and \
           (iint32[y,x] == iint32[y              ,x+1:x+t_sizeX  ]).all() and \
           (iint32[y,x] == iint32[y+1:y+t_sizeY  ,x    +t_sizeX-1]).all() and \
           (iint32[y,x] == iint32[y    +t_sizeY-1,x+1:x+t_sizeX  ]).all() and \
           (iint32[y,x] != iint32[y+1,x+1]) and \
                       True:
            rectAt.append((x,y))

print(rectAt)

for x, y in rectAt:
    cv2.rectangle(ibgr, (x-1,y-1), (x+t_sizeX, y+t_sizeY), (0,255,255), 1) 

cv2.imshow("ibgr", ibgr)
cv2.waitKey(0)
cv2.destroyAllWindows()

程式码会在提供的影像中找到一个矩形:

在[(89,13)]处。

相关问题