问题描述
我最近开始处理OpenCV,现在我正在尝试对另一张图片中的图案图片进行检查。
现在的问题是,匹配器可以找到关键点的良好匹配项,但没有考虑它们之间的相对位置。
例如: 在这两种情况下,匹配器都找到了关键点的匹配项并正确地进行了匹配,但是在第二种情况下,匹配项是在图片的不同位置发现的。我想将这种情况处理为“找不到模式”,最好使用内置的OpenCV函数。
比较关键点的功能:
def keypoint_match(pic,pattern,pic_desc,pattern_desc,drawDebug=False):
bf = cv2.BFMatcher()
matches = bf.knnMatch(pattern_desc[1],pic_desc[1],k=2)
good = []
for m,n in matches:
if (m.distance < 0.75 * n.distance):
good.append(m)
print('Good matches:',len(good))
find = True if len(good) > 10 else False
if drawDebug or find:
image = cv2.drawMatches(np.uint8(pattern),pattern_desc[0],np.uint8(pic),pic_desc[0],good,flags=0,matchColor=(0,255,0),singlePointColor=(255,0))
plt.figure(figsize=(20,20))
plt.axis('off')
plt.imshow(image.astype(np.uint8))
plt.show()
return good,find
结果:
test1.png
Good matches: 32
Pattern found: 'smile.png'
Result: pattern found
test2.png
Good matches: 25
Pattern found: 'smile.png'
Result: pattern found
测试图片和我上传的here的完整源代码。
UPD:
据我所知,有3种方法可以在图像中找到对象:
- 模板匹配
- 关键点检测
- 轮廓检测
我的任务是找出图片中是否有特定标志。图片中的标志可能会略微倾斜或具有不同的比例。图像的背景色也可能不同,例如,如果是照片。通常,标志具有困难的结构,但它们的轮廓大致相同。
这就是为什么我选择“关键点检测”方法的原因。
我为测试添加了2张照片。
问题是存在部分匹配项,我想排除它们,但我不知道如何。图片仅用于演示部分匹配的问题。
解决方法
免责声明:
如果我的理解是正确的,那是臭名昭著的XY-Problem的情况,并且您实际上想在随后的两个测试图像中找到微笑图像,而不管使用哪种精确技术,那么我想介绍以下内容:
解决方案:template_matching.py
import cv2
import numpy as np
from matplotlib import pyplot as plt
import sys
img_rgb = cv2.imread(sys.argv[1])
img_gray = cv2.cvtColor(img_rgb,cv2.COLOR_BGR2GRAY)
template = cv2.imread('smile.png',0)
w,h = template.shape[::-1]
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
cv2.rectangle(img_rgb,pt,(pt[0] + w,pt[1] + h),(0,255),2)
cv2.imwrite('res.png',img_rgb)
您可以这样运行:
结果:
python3 template_matching.py test1.png
它会给您这样的结果:
另一张测试图像
python3 template_matching.py test2.png
给出这样的结果:
说明:
我可能并不完全熟悉SIFT(所谓的最佳特征检测算法),但是它通常用于检测角点,提取特征等等。仅凭这一点还不够(至少在我看来)。您需要将这些功能放在一起以定义对象。然后您可以尝试在测试图像集中找到该对象。
我想到的另一种方法可能涉及更多,并且不使用内置的黑盒opencv函数,而是使用霍夫线变换来获取两条垂直线。然后,霍夫圆变换以得到由微笑形成的半圆。他们在一起将定义您的“笑脸”。但无论如何,您确实要在问题中说:
最好具有内置的OpenCV函数。
然后上述解决方案对于我认为的问题是最快,最简洁的。