【问题标题】:Increase performance of template matching in OpenCV提高 OpenCV 中模板匹配的性能
【发布时间】:2017-05-27 15:29:01
【问题描述】:

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

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

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

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

【问题讨论】:

  • 一张图片可能有助于了解您的比赛有多困难...可能在已知位置进行简单的减法可能就足够了
  • 我同意@Miki,提供示例输入图像将有助于想象给定场景
  • 这里是棋盘的示例图片:imgur.com/UQxjB70 这是一个棋盘模板的示例图片:imgur.com/s6PkWdT

标签: python performance opencv chess template-matching


【解决方案1】:

我也面临同样的挑战。

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

正如您所建议的,“为每种类型的棋子调用 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 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-04
    • 2018-10-02
    • 2015-04-20
    相关资源
    最近更新 更多