python-3.x - 与 Python 3.9.1、opencv.python 4.5.1.48 和掩码匹配的模板(透明度)
问题描述
自 2J 以来,我遇到了与这个问题相同的问题,但没有一个答案适用于 Python 3,所以今天我花了一整天的时间来解决这个问题: python opencv cv2 matchTemplate with transparent (graphics from the question) 我终于设法写了一个 cv2.matchTemplate() 带有掩码(透明度/alpha通道)和python(3.9.1)和opencv-python(4.5.1.48)。
问题是我像在 Python 2 中一样将掩码作为 RGBA(RGB 为零)传递,并且始终找到 (0,0) 作为位置,因为结果的所有值始终为零。然后,当我尝试仅通过 alpha 通道时,它按预期工作!因为我没有找到任何关于 Python 3 的话题,所以我写了一个新问题,希望得到一些改进的建议。我在我的代码中编写了两个函数,一个是传统上只能找到一个位置 ( findImgLoc()
)。另一个 ( findImgTresh()
) 获取值高于阈值的所有坐标。这两个函数都标准化 (0 - 1) 所有方法并反转 SQDIFF 和 SQDIFF NORMED 的结果,所以你只得到坐标,或者在第二种情况下得到坐标列表,我认为这对初学者更友好。为了测试我有一个test()
函数获取cmd输出中的输出图形和信息。
仅仅因为我在旧答案中一遍又一遍地阅读这个,掩码适用于所有匹配方法的代码,不仅适用于 TM_SQDIFF 和 TM_CCORR_NORMED!
图片
模板
没有掩码的结果 (findImgTresh()
带有SQDIFF_NORMED
und thres=.95
-> 4 个位置)
输出: [[15, 123], [15, 124], [15, 165], [15, 166]]
带有掩码的结果 (findImgTresh()
带有SQDIFF_NORMED
und thres=.95
-> 2 个位置)
输出: [[15, 123], [15, 165]]
图像上没有蒙版的结果
图像上带有蒙版的结果
代码
import numpy as np
# Method: 0: SQDIFF | 1: SQDIFF NORMED | 2: TM CCORR | 3: TM CCORR NORMED | 4: TM COEFF | 5: TM COEFF NORMED
img_path = "/Path/to/your/file/source_image_name.png"
tem_path = "/Path/to/your/file/template_image_name.png"
def findImgLoc(image_path, template_path, mask=False, method=1):
img = cv2.imread(img_path, cv2.IMREAD_UNCHANGED) # cv2.IMREAD_COLOR (cv2.IMREAD_UNCHANGED)
tem = cv2.imread(tem_path, cv2.IMREAD_UNCHANGED) # cv2.IMREAD_COLOR (cv2.IMREAD_UNCHANGED)
# Match template with and without mask
if mask and img.shape[2] == 4:
alpha_channel = np.array(cv2.split(tem)[3])
result = cv2.matchTemplate(img, tem, method, mask=alpha_channel)
else:
result = cv2.matchTemplate(img, tem, method)
# Nomrmalize result data to percent (0-1)
result = cv2.normalize(result, None, 0, 1, cv2.NORM_MINMAX, -1)
# Invert Image to work similar across all methods!
if method == 0 or method == 1: result = (1 - result)
_minVal, _maxVal, minLoc, maxLoc = cv2.minMaxLoc(result, None)
matchLoc = maxLoc
# Make the Result viewable
# view_result = cv2.normalize(result, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
cv2.rectangle(result, matchLoc, (matchLoc[0] + tem.shape[0], matchLoc[1] + tem.shape[1]), (255,0,0), 2)
return matchLoc
def findImgthres(image_path, template_path, mask=False, method=1, thres=.95):
img = cv2.imread(img_path, cv2.IMREAD_UNCHANGED) # cv2.IMREAD_COLOR (cv2.IMREAD_UNCHANGED)
tem = cv2.imread(tem_path, cv2.IMREAD_UNCHANGED) # cv2.IMREAD_COLOR (cv2.IMREAD_UNCHANGED)
# Match template with and without mask
if mask and img.shape[2] == 4:
alpha_channel = np.array(cv2.split(tem)[3])
result = cv2.matchTemplate(img, tem, method, mask=alpha_channel)
else:
result = cv2.matchTemplate(img, tem, method)
# Nomrmalize result data to percent (0-1)
result = cv2.normalize(result, None, 0, 1, cv2.NORM_MINMAX, -1)
# Invert Image to work similar across all methods!
if method == 0 or method == 1: result = (1 - result)
result_list = np.argwhere(result > thres)
return result_list
def test():
global img_path, tem_path
mT = MatchTemplate()
def findImgthres(image_path, template_path, mask=False, method=1, thres=.95):
img = cv2.imread(img_path, cv2.IMREAD_UNCHANGED) # cv2.IMREAD_COLOR (cv2.IMREAD_UNCHANGED)
tem = cv2.imread(tem_path, cv2.IMREAD_UNCHANGED) # cv2.IMREAD_COLOR (cv2.IMREAD_UNCHANGED)
# Match template with and without mask
if mask and img.shape[2] == 4:
alpha_channel = np.array(cv2.split(tem)[3])
result = cv2.matchTemplate(img, tem, method, mask=alpha_channel)
else:
result = cv2.matchTemplate(img, tem, method)
# Nomrmalize result data to percent (0-1)
result = cv2.normalize(result, None, 0, 1, cv2.NORM_MINMAX, -1)
# Invert Image to work similar across all methods!
if method == 0 or method == 1: result = (1 - result)
result_list = np.argwhere(result > thres)
return result, result_list
tmp_source = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
tmp_mask_source = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
tmp_tem = cv2.imread(tem_path, cv2.IMREAD_UNCHANGED)
result = findImgthres(img_path, tem_path)
mask_result = findImgthres(img_path, tem_path, mask=True)
# Mark original Image with mask
matchLoc = mask_result[1]
if matchLoc is not None:
for loc in matchLoc:
cv2.rectangle(tmp_mask_source, tuple(loc)[::-1], (loc[1] + tmp_tem.shape[1], loc[0] + tmp_tem.shape[0]), (0,0,0), 1)
# Mark original Image without mask
matchLoc = result[1]
if matchLoc is not None:
for loc in matchLoc:
cv2.rectangle(tmp_source, tuple(loc)[::-1], (loc[1] + tmp_tem.shape[1], loc[0] + tmp_tem.shape[0]), (0,0,0), 1)
# Save Images
_dir = os.path.dirname(__file__)
cv2.imwrite(os.path.join(_dir, "source.png") , tmp_source)
cv2.imwrite(os.path.join(_dir, "mask_source.png") , tmp_mask_source)
cv2.imwrite(os.path.join(_dir, "result.png") , 255*result[0])
cv2.imwrite(os.path.join(_dir, "mask_result.png") , 255*mask_result[0])
# Output Result
print(f"[NO MASK] Match Locs: {result[1]}")
print(f"[MASK] Match Locs: {mask_result[1]}")
if __name__ == "__main__":
test()
我希望我能提供进一步的帮助,并对改进建议感到高兴!
解决方案
推荐阅读
- python - 如何将两个列表中的所有值相乘并获得相应的矩阵
- java - 如何使用 MediaMetadataRetriever() 从 .mp3 文件中检索专辑封面
- mysql - mySql每隔一个工作日获取日期
- javascript - 包含一个或多个 a 的字符串的正则表达式
- events - 事件溯源和密码更改安全隐患
- python - Python中的“无”是什么意思?
- java - 我需要将 UI 初始化代码放在 IntelliJ Idea 插件中的什么位置?
- android - FragmentPagerAdapter 使用 getChildFragmentManager() 崩溃
- html - 更改信用卡占位符颜色
- c# - 手动创建的 UserControl 未触发 SizeChanged 事件