OpenCV模板匹配,多种模板

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

我正在尝试为游戏制作一个机器人。基本上它会从地上捡起物品,但这些物品有时看起来会有所不同。角度不同或者它们位于不同颜色的地面上等。为了使一切正常工作,我需要多个模板。有什么办法可以做到这一点吗?如果您不明白,请在评论中告诉我。这是我迄今为止尝试过的:

files = ["bones_{}.png".format(x) for x in range(6)]

    for i in range(6):
        img_gray = cv2.cvtColor(imageGrab(), cv2.COLOR_BGR2GRAY)
        f = str(files[i])
        template = cv2.imread(f, 0)
        w, h = template.shape[:: -1]
        res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
        threshhold = 0.70
        loc = np.where( res >= threshhold)

这可行,但还可以更好。你有什么想法吗?

python opencv templates template-matching
2个回答
10
投票

在您当前的代码中,有很多步骤需要多次执行,其中一次(每帧)就足够了。您可以通过将它们分开来提高效率。

您当前正在每一帧上重新加载模板,这是非常低效的,因为您很容易每秒加载 100+ 次。相反,创建一个包含模板的列表,以便它们保留在内存中。从内存访问比从磁盘加载要快得多。
您可以对模板的宽度/长度执行相同的操作,但它实际上并未在您的代码中使用,因此也许您可以一起跳过它。
阈值只需设置一次。

templates = []
templ_shapes = []
threshold = 0.70

for i in range(6):
    templates.append(cv2.imread("bones_{}.png".format(i),0))
    templ_shapes.append(templates[i].shape[:: -1])

所有模板都可以与同一个屏幕截图进行比较,因此您应该将其放在 for 循环之外。这是一场轻松但相当巨大的胜利。因此,在每一帧上,抓取屏幕一次,并匹配所有模板。为了清晰和方便起见,您可以将其放入函数中:

def doTemplateMatch():
    img_gray = cv2.cvtColor(imageGrab(), cv2.COLOR_BGR2GRAY)
    for template in templates: 
        res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
        loc = np.where( res >= threshold)

0
投票

他们是一个更好的匹配多个模板的算法。它比 OpenCV 更快。看看这里,它叫OpenFDCM。

您可以在 Google Colab 此处尝试。

pip install openfdcm
import openfdcm

templates = # A list of 4xN array where each array is a template represented as N lines [x1, y1, x2, y2]^T
scene = # A 4xM array representing the M scene lines

# Perform template matching
max_tmpl_lines, max_scene_lines = 4, 4  # Combinatory search parameters.
depth = 30              # The [0, pi] discretization.
coeff = 5.0             # A weighting factor to enhance the angular cost vs distance cost in FDCM algorithm.
scene_padding = 1.5     # A ratio to pad the scene images used in the FDCM algorithm, use if best match may appear on image boundaries.
distance_type = openfdcm.distance.L2 # or openfdcm.distance.L2_SQUARED or openfdcm.distance.L1
#num_threads = 4

threadpool = openfdcm.ThreadPool() # could pass num_threads here, but default is optimal
featuremap_params = openfdcm.Dt3CpuParameters(depth, coeff, scene_padding, distance_type)
search_strategy = openfdcm.DefaultSearch(max_tmpl_lines, max_scene_lines)
optimizer_strategy = openfdcm.BatchOptimize(10, threadpool)
matcher = openfdcm.DefaultMatch()
penalizer = openfdcm.ExponentialPenalty(tau=1.5)

# Build FDCm feature map and search
start_time = time.time()
featuremap = openfdcm.build_cpu_featuremap(scene, featuremap_params, threadpool)
raw_matches = openfdcm.search(matcher, search_strategy, optimizer_strategy, featuremap, templates, scene)
penalized_matches = openfdcm.penalize(penalizer, raw_matches, openfdcm.get_template_lengths(templates))
sorted_matches = openfdcm.sort_matches(penalized_matches)
search_time = time.time() - start_time

print(f"Template matching search completed in {search_time:.4f} seconds.")

best_match = sorted_matches[0]                 # Best match (lower score) is first
best_match_id = best_match.tmpl_idx
best_matched_tmpl = templates[best_match_id]
result_rotation = best_match.transform[0:2, 0:2]
result_translation = best_match.transform[0:2, 2]
© www.soinside.com 2019 - 2024. All rights reserved.