¿Cómo contar el número de objetos detectados con la coincidencia de plantillas?

Estaba leyendo los documentos sobre la coincidencia de plantillas con opencv y python y en la última parte sobre la coincidencia de plantillas con múltiples objetos, el código detecta las 19 monedas en la imagen de mario, pero ¿es posible contar el número de objetos detectados con alguna función en ¿Python como len () o cualquier método opencv?

Aquí está el código que se muestra en el tutorial: http://docs.opencv.org/3.1.0/d4/dc6/tutorial_py_template_matching.html

Código de coincidencia de plantilla:

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) 

Y el resultado es: Mario Bros & Coins.

Entonces, ¿hay alguna forma de contar las monedas detectadas en la imagen e imprimir el número en el terminal? Algo como:

 The Template Matching code showed before... print "Function that detect number of coins with template matching" >>> 19 

Encontré una solución adecuada (para mi aplicación) en el conteo de coincidencias únicas como sugirió Ulrich. No es lo ideal, pero jugar con la “sensibilidad” normalmente produce resultados dentro de +/- 2% para mi aplicación.

 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) 

Utilicé una lista para almacenar la primera (x, y) de muchas detecciones del mismo objeto. Luego, para cada (x, y) en las detecciones encontradas (debe haber muchas detecciones en el mismo objeto), calculo la distancia entre el nuevo (x, y) y todos los puntos en la lista. Si la distancia es lo suficientemente grande, debe ser el primer hallazgo de una nueva detección. Luego puse el nuevo (x, y) a la lista. Es estúpido pero realmente funciona.

El propósito es eliminar los puntos cercanos al (x, y) de la primera detección de un objeto y mantener solo un punto de ese ‘grupo’, luego iterar todos los puntos en loc para ubicar más ‘grupos’ y encontrar uno y el solo un punto en cada grupo

 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]) 

tiempo de importación importar número cv2 importar como np desde PIL importar ImageGrab

mientras que 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