77 lines
3.0 KiB
Python
77 lines
3.0 KiB
Python
import cv2
|
||
import imutils
|
||
import numpy as np
|
||
from PIL.Image import Image
|
||
|
||
import utils.matplotlib
|
||
|
||
|
||
def match_resize(src: Image, tmpl: str, similarity=0.9, step=10, fast=False):
|
||
src = cv2.cvtColor(np.asarray(src), cv2.COLOR_RGB2BGR)
|
||
src_gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
|
||
tmpl = cv2.imread(tmpl)
|
||
tmpl_gray = cv2.cvtColor(tmpl, cv2.COLOR_BGR2GRAY)
|
||
found = None
|
||
tmp_r = 0
|
||
for scale in np.linspace(0.2, 2, step)[::-1]:
|
||
# 根据scale比例缩放图像,并保持其宽高比
|
||
resized = imutils.resize(src_gray, width=int(src_gray.shape[1] * scale))
|
||
r = src_gray.shape[1] / float(resized.shape[1])
|
||
result = cv2.matchTemplate(resized, tmpl_gray, cv2.TM_CCOEFF_NORMED)
|
||
found_location = convert_location(result, tmpl_gray, similarity, r)
|
||
# 快速匹配, 如果缩放比例越大 相似度越低就直接退出循环 返回当前最佳结果
|
||
if fast:
|
||
if found is not None and found_location is not None:
|
||
print(found[2], found_location[2])
|
||
if tmp_r < r and found[2] > found_location[2]:
|
||
break
|
||
tmp_r = r
|
||
# 如果我们找到了一个新的最大校正值,更新簿记变量值
|
||
if found is None or (
|
||
found_location is not None and found_location[2] >= similarity and found_location[2] > found[2]):
|
||
found = found_location
|
||
if found is None:
|
||
return None
|
||
x, y, _ = found
|
||
print("x,y (%s, %s)" % (x, y))
|
||
return found[0], found[1]
|
||
|
||
|
||
def match(src: Image, tmpl: str, similarity=0.9):
|
||
# cv::TM_CCOEFF_NORMED = 5 标准相关匹配
|
||
method = cv2.TM_CCOEFF_NORMED
|
||
src = cv2.cvtColor(np.asarray(src), cv2.COLOR_RGB2BGR)
|
||
# 灰度图提高精度
|
||
src_gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
|
||
tmpl = cv2.imread(tmpl)
|
||
tmpl_gray = cv2.cvtColor(tmpl, cv2.COLOR_BGR2GRAY)
|
||
# print('imagetempl.shape:', tmpl_gray.shape)
|
||
result = cv2.matchTemplate(src_gray, tmpl_gray, method)
|
||
print(result)
|
||
loc = convert_location(result, tmpl_gray, similarity)
|
||
if loc is None:
|
||
return
|
||
x, y, _ = loc
|
||
print("x,y (%s, %s)" % (x, y))
|
||
return x, y
|
||
|
||
|
||
def convert_location(result, tmpl, similarity, resize=1):
|
||
method = 5
|
||
min_max = cv2.minMaxLoc(result)
|
||
if method == 0 or method == 1: # 根据不同的模式最佳匹配位置取值方法不同
|
||
match_loc = min_max[2]
|
||
else:
|
||
match_loc = min_max[3]
|
||
right_bottom = (match_loc[0] + tmpl.shape[1], match_loc[1] + tmpl.shape[0])
|
||
# print('result.min_max:', min_max, 'method=', method)
|
||
# print('match_loc:', match_loc, type(match_loc))
|
||
# print('right_bottom', right_bottom, type(right_bottom))
|
||
x = int(match_loc[0] * resize) + int((right_bottom[0] - match_loc[0]) / 2 * resize)
|
||
y = int(match_loc[1] * resize) + int((right_bottom[1] - match_loc[1]) / 2 * resize)
|
||
|
||
print("(%s, %s) 缩放比例: %s, 相似度: %s" % (x, y, resize, min_max[1]))
|
||
if min_max[1] < similarity:
|
||
return None
|
||
return x, y, min_max[1]
|