python - 如何使用 Python 找到图片中的几个关键像素点?
问题描述
我知道通过 Opencv-python 的 matchtemplate 函数可以从图 1 中匹配图 2。
import cv2
template = cv2.imread("1.bmp")
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
template = cv2.Canny(template, 50, 200)
edged = cv2.imread("2.bmp")
edged = cv2.cvtColor(edged, cv2.COLOR_BGR2GRAY)
edged = cv2.Canny(edged, 50, 200)
result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF_NORMED)
(_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)
但是如果我只有图3这样的像素,我如何匹配图1?
图3:图2中的部分像素被提取出来,其余部分用红色填充。
我没有找到 opencv-python 或 PIL 解决方案。我认为可以通过遍历像素来解决,但这并不能保证性能。那么有没有更好的方法呢?
解决方案
根据 Neeraj Komuravalli 对这个问题的回答,matchTemplate
支持该mask
论点作为在匹配中排除模板中某些像素的一种方式(文档)。
要根据红色像素生成遮罩,一个简单的解决方案是使用布尔表达式来选择那些0
蓝色和绿色但255
红色的像素:
mask = (template[:,:,0]==0) & (template[:,:,1]==0) & (template[:,:,2]==255)
mask = ~mask
mask = mask.astype(np.uint8)
请注意,转换为uint8
是必要的,因为掩码必须与模板具有相同的数据类型。
编辑: ~mask
反转掩码(0
变为1
,反之亦然),这是必要的,因为0
指示要掩码的像素,至少在使用方法时cv2.TM_CCORR_NORMED
。
虽然这原则上解决了您的问题,但在这种情况下不会产生有效的解决方案。
这是因为对图像应用了 Canny 边缘过滤器。由于在应用 Canny 时无法屏蔽模板中的红色像素,因此红色像素区域的边界会影响边缘检测的结果,从而使模板看起来与原来的完全不同。
在这个例子中,匹配失败,返回一个完全错误的位置。
删除 Canny 步骤解决了这个问题......但它也使该方法不太健壮/精确。在这种情况下,匹配实际上似乎与 100% 正确的匹配相差几个像素。不幸的是,我想不出任何改进的方法。
这是对我有用的完整代码(在精度方面有上述警告):
import cv2
import numpy as np
template = cv2.imread("masked_template.png")
mask = (template[:,:,0]==0) & (template[:,:,1]==0) & (template[:,:,2]==255)
mask = mask.astype(np.uint8)
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
#template = cv2.Canny(template, 50, 200)
edged = cv2.imread("edged.png")
edged = cv2.cvtColor(edged, cv2.COLOR_BGR2GRAY)
#edged = cv2.Canny(edged, 50, 200)
result = cv2.matchTemplate(edged, template, cv2.TM_CCORR_NORMED, mask=mask)
(_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)
推荐阅读
- powershell - 始终将参数附加到 Powershell 中的命令
- node.js - 尝试将 Heroku 连接到 Atlas MongoDB 时出现问题
- javascript - 覆盖常见的浏览器快捷方式(如 ctrl+s 等)是否可接受的可访问性做法?
- asp.net-core - Azure Key Vault 如何提供比加密配置设置更好的安全性?
- ruby-on-rails - ActiveStorage:按附件文件名订购 ActiveRecord 模型(错误缺少表“active_storage_blobs”的 FROM 子句条目)
- postgresql - 我有一个关于 postgreSQL 集群的问题
- kotlin - 如何使用 equals() 和 contains() 检查可为空的数据类型?我想它们都是字符串的方法,但是为什么它们的行为不同呢?
- javascript - 使用 jquery 显示上一个 ul 的后退按钮
- ios - 使用 Apple 分发证书进行数字签名和 iOS 中的正常分发配置文件有什么区别和目的?
- python - VS Code 中的 Jupyter Notebook 输出窗口