我正在阅读有关使用opencv和python进行模板匹配的文档,最后一部分是关于模板与多个对象的匹配,代码检测到马里奥图像上的19个硬币但是,是否可以计算检测到的对象数量python上的一些函数,如len()或任何opencv方法?
以下是教程中显示的代码: http://docs.opencv.org/3.1.0/d4/dc6/tutorial_py_template_matching.html
模板匹配代码:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img_rgb = cv2.imread('mario.png')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('mario_coin.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,0,255), 2)
cv2.imwrite('res.png',img_rgb)
结果是: Mario Bros & Coins
那么,有没有办法计算图像上检测到的硬币并在终端上打印数字? 类似的东西:
The Template Matching code showed before...
print "Function that detect number of coins with template matching"
>>> 19
答案 0 :(得分:1)
我找到了一个合适的解决方案(对于我的应用),计算独特的匹配,正如Ulrich建议的那样。它并不理想,但玩的是"灵敏度"对于我的应用,通常会产生+/- 2%的结果。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img_rgb = cv2.imread('mario.png')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('mario_coin.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)
f = set()
for pt in zip(*loc[::-1]):
cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
sensitivity = 100
f.add((round(pt[0]/sensitivity), round(pt[1]/sensitivity)))
cv2.imwrite('res.png',img_rgb)
found_count = len(f)
答案 1 :(得分:0)
我使用列表来存储许多相同对象检测的第一个(x,y)。然后对于找到的检测中的每个(x,y)(在同一个对象上必须有很多检测),我计算新(x,y)和列表中每个点之间的距离。如果距离足够大,则必须首先找到新的检测。然后我把新的(x,y)放到列表中。这是愚蠢的,但确实有效。
目的是去除第一次检测到一个物体的(x,y)附近的点,并且只保留该“群”的一个点,然后迭代loc中的所有点以找到更多“群组”并找到每组中只有一个点。
import cv2
import numpy as np
import matplotlib.pyplot as plt
import math
def notInList(newObject):
for detectedObject in detectedObjects:
if math.hypot(newObject[0]-detectedObject[0],newObject[1]-detectedObject[1]) < thresholdDist:
return False
return True
img_rgb = cv2.imread("7.jpg")
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread("face.jpg",0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.85
loc = np.where( res >= threshold)
detectedObjects=[]
thresholdDist=30
for pt in zip(*loc[::-1]):
if len(detectedObjects) == 0 or notInList(pt):
detectedObjects.append(pt)
cellImage=img_rgb[pt[1]:pt[1]+h, pt[0]:pt[0]+w]
cv2.imwrite("results/"+str(pt[1])+"_"+str(pt[0])+".jpg",cellImage,
[int(cv2.IMWRITE_JPEG_QUALITY), 50])
答案 2 :(得分:0)
导入时间 导入cv2 将numpy导入为np 从PIL导入ImageGrab
为True时:
count = 0
stop = 0
img = ImageGrab.grab()
img_np = np.array(img)
gray = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2RGB)
Template = cv2.imread('image.png' ,0)
w, h = Template.shape[::-1]
res = cv2.matchTemplate(gray, Template, cv2.TM_CCOEFF_NORMED)
threshold = 0.90
loc = np.where(res >= threshold)
font = cv2.FONT_HERSHEY_SIMPLEX
for pt in zip(*loc[::-1]):
cv2.rectangle(frame, pt, (pt[0] + w, pt[1] + h), (0,0,255) ,2)
count = count + 1
print(count)
stop = 1
cv2.imshow('frame',frame)
if (stop == 1):
break
答案 3 :(得分:0)
对于仍在想知道的人:首先对列表“ zip(* loc [::-1})”进行排序比较容易。
例如,我的脚本返回的发现结果如下:
(580, 822)
(871, 822)
(1017, 822)
(434, 823)
(726, 823)
(871, 823)
(1017, 823)
7
您会注意到有多个重复项,而不仅仅是顺序重复。现在只需简单地使用“ sorted(zip(* loc [::-1]))”对它进行排序,就可以通过简单地计算相邻的2点并检查每个循环的距离来使距离变得小菜一碟。
通过在循环中添加条件并检查当前点的距离是否小于期望的距离,可以很好地完成工作。我从来没有正确学习过python,所以我不确定这是否是有效的方法。至少这对我的用例有用。您可以在下面查看。
Source code (Github) / Test Result (Imgur)
示例代码:
img = np.array( *YOUR_SCREENSHOT_HERE* )
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
template = cv2.imread( *TARGET_IMAGE_HERE* , 0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
loc = np.where(res >= precision)
count = 0
last_pt = [0, 0] # Set this negative if target image is at top-left corner.
for pt in sorted(zip(*loc[::-1])):
if sqrt(abs(last_pt[0]-pt[0])**2 + abs(last_pt[0]-pt[0])**2) < threshold*min([h, w]):
continue
else:
last_pt = pt
print(pt)
count = count + 1
cv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
cv2.imwrite('res.png', img)
return count
答案 4 :(得分:0)
我列出了所有匹配项,并为每个新匹配项检查列表中是否有任何匹配项与边界框相交:
res = cv.matchTemplate(image,template,cv.TM_CCOEFF_NORMED)
threshold = 0.5
loc = np.where(res >= threshold)
matches = []
for pt in zip(*loc[::-1]):
intersection = 0
for match in matches:
if intersected(match, (match[0] + w, match[1] + h), pt, (pt[0] + w, pt[1] + h)):
intersection = 1
break
if intersection == 0:
matches.append(pt)
rect = cv.rectangle(image, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
这是检查路口的代码:
def intersected(bottom_left1, top_right1, bottom_left2, top_right2):
if top_right1[0] < bottom_left2[0] or bottom_left1[0] > top_right2[0]:
return 0
if top_right1[1] < bottom_left2[1] or bottom_left1[1] > top_right2[1]:
return 0
return 1
答案 5 :(得分:0)
那是我的方法:
loc = np.where( res >= threshhold)
print(len(loc[0])) #match occurences count
loc是2D数组。