提高 OpenCV 中模板匹配的性能

问题描述 投票:0回答:2

我目前正在使用 OpenCV 用 python 编写一个项目,旨在识别屏幕上棋盘上棋子的位置。

我已经成功地使用模板匹配功能来识别每件作品的位置。这是通过获取整个棋盘的屏幕截图并运行模板匹配功能 12 次(每种颜色 6 种棋子)来完成的。现在我正在寻求提高程序的速度。我相信我可以在这里大幅提高性能:

据我了解,模板匹配算法基本上是将模板图像一次一个像素地滑动到基本图像上以查找匹配项。显然,我只期望在棋盘的 64 个方格中进行匹配,因此每次移动图像一个像素的效率非常低。有没有办法自定义滑动间隔以匹配棋盘一格的宽度,所以我只检查 64 格。对于如何提高速度还有其他建议吗?

我考虑过对每种类型的棋子调用模板匹配函数 64 次的可能性,以匹配相同大小的每个单独的方块。我不确定这是否会更快,而且获取 64 个屏幕截图也需要相当长的时间。

python performance opencv chess template-matching
2个回答
0
投票

我面临着同样的挑战。

更快的解决方案 - 相同大小减法的模板匹配

正如您所建议的,“为每种类型的棋子调用模板匹配函数 64 次,以匹配相同大小的每个单独的方块”要快得多。 但你不需要获得 64 张屏幕截图。只需 1 个屏幕截图即可,然后您将得到 64 个减法。

full_image= cv2.imread('path_to_screenshot')
square_subtraction = full_image[yi:yf,xi:xf]

如果棋盘并不总是在屏幕上的同一位置,您应该先在全屏上搜索它,然后创建减法。

最快的解决方案 - 像素签名

也有可能每件作品都有一个特定的 x,y 坐标的唯一像素,这将使其与所有其他 11 件作品不同。我称之为“像素签名”。

如果你能找到这个签名,你可以使用像素匹配而不是第一个解决方案中的模板匹配。

这是我在一组模板上查找唯一像素的代码。

from os import walk

def compare_pixel_RGB(rgb_to_compare, row, column):
    n = 0         
    for item in templates:
        rgb = templates[item][row][column] 
        if (rgb_to_compare == rgb).all() :
            n += 1
    return n

#Load template images. They should all have the same size.
templates = dict()
for (dirpath, dirnames, filenames) in walk('templates_board/'):
    for filename in filenames:
        if filename.endswith('.png'):
            template = cv2.imread('templates_board/'+filename)
            templates.update({filename: template})

#Create and populate matching DataFrame with same dimensions of the templates. 
#Each cell of the DataFrame corresponds to a pixel of the templates and has the sum of matching pixels for all pieces on this specific coordinate.
#We are hoping to find a cell = 12, meaning that each piece only matches itself and not any other one.
matching_list = list()
random_item = list(templates.keys())[0]
matching = pd.DataFrame(np.zeros((templates[random_item].shape[0],templates[random_item].shape[1])))                          
for item in templates:
    for row in range(templates[item].shape[0]):
        for column in range(templates[item].shape[1]):
            rgb = templates[item][row][column] 
            count_same_pixel = compare_pixel_RGB(rgb, row, column)
            matching_list.append([item, row, column, count_same_pixel])
            matching[column][row] = matching[column][row] + count_same_pixel

如果您找到像素签名坐标(上面的

column
x
row
),您可以使用它来获得棋盘 64 个正方形中每个正方形的像素减法,并与模板像素签名进行比较:

full_image = cv2.imread('path_to_screenshot')
square_subtraction = full_image[yi:yf,xi:xf]
square_pixel = square_subtraction[column][row]

template = cv2.imread('path_to_template')
template_signature = template[column][row]

只需遍历棋盘的每个方块并与每个模板进行比较,就像第一个解决方案一样,但不需要模板匹配,您只需要比较像素。

template_signature  == square_pixel 

0
投票
  • 您不必滑过方块,因为棋子必须大致居中。

  • 您可能可以对“通用”部件执行匹配,只是为了找到位置;当您知道(大约)位置时,您可以在较小的窗口中尝试每一件作品。

  • 您可以对缩小图像(和缩小模板)进行首次搜索以获得初始近似值;然后细化至全分辨率。

© www.soinside.com 2019 - 2024. All rights reserved.