0
votes

Cv2 trouver des images dans une autre image

Une grande image (300 * 300 pixels) divisée en 3 zones. 2 petits (AAA.png et BBB.png) sont des portions de la grande image.

3-areas.png

3-areas.png

AAA.png em>

 AAA.png

BBB.png

 BBB.png

Je veux savoir dans quelles zones ils se trouvent, c'est-à-dire trouver de petites images dans une vue d'ensemble. La sortie idéale serait: "AAA.png est à gauche"; "BBB.png est dans la bonne".

J'ai ces codes en cours d'exécution:

big_pic = cv2.imread("c:\\TEM\\3-areas.png")

list_of_areas = {
left : [0,300, 0,100],
mid : [0,300, 100,200],
right : [0,300, 200,300]}

small_picture_folder = "C:\\TEM\\"
small_pictures = []

root, dirs, files = os.walk(small_picture_folder).next()

for path, subdirs, files in os.walk(root):
    for f in files:
        if ""AAA"" in f or ""BBB"" in f:
           small_pictures.append(small_picture_folder + f)

for key, value in list_of_areas.iteritems():
    for y,y1,x,x1 in value:
        target_area = big_pic[y:y1, x:x1]

Je veux le simplifier en créant des boucles. Ce que j'ai essayé:

import cv2, os
import numpy as np

big_pic = cv2.imread("c:\\TEM\\3-areas.png")

left_area = big_pic[0:300, 0:100]   # [y,y1 : x,x1]
mid_area = big_pic[0:300, 100:200]
right_area = big_pic[0:300, 200:300]

AAA = cv2.imread('C:\\TEM\\AAA.png')
AAA_res = cv2.matchTemplate(left_area,AAA,cv2.TM_CCOEFF_NORMED)

threshold = 0.99
AAA_loc = np.where(AAA_res >= threshold)
a_x_cor = list(AAA_loc[0])
a_y_cor = list(AAA_loc[1])
print a_x_cor, a_y_cor

BBB = cv2.imread('C:\\TEM\\BBB.png')
BBB_res = cv2.matchTemplate(right_area,BBB,cv2.TM_CCOEFF_NORMED)

BBB_loc = np.where(BBB_res >= threshold)
b_x_cor = list(BBB_loc[0])
b_y_cor = list(BBB_loc[1])

print b_x_cor, b_y_cor

La ligne "for y, y1, x, x1 in value:" donne une erreur: "TypeError: 'int' object is not iterable."

Quelle serait la meilleure façon d'y parvenir? Merci.


2 commentaires

Un autre conseil général: il semble que vous utilisez Python 2 ( print , iteritems ). Il est utile de le mentionner, par exemple en ajoutant la balise python-2.x . Pour que les gens ne soient pas confus, car ils se demandent pourquoi il n'y a pas de iteritems pour les dictionnaires ...


@HansHirse, merci! envisageriez-vous d'en faire une réponse afin que nous puissions clore cette question?


3 Réponses :


1
votes

Voici comment détecter plusieurs modèles et recadrer le ROI

import cv2
import numpy as np
templates = []
templ_shapes = []
threshold = 0.9
# get 1st template
temp1 =cv2.imread("YourImagePath1.png",cv2.IMREAD_GRAYSCALE)
templates.append(temp1)
templ_shapes.append(temp1.shape[:: -1])

# get 2nd template
temp2 =cv2.imread("YourImagePath2.png",cv2.IMREAD_GRAYSCALE)
templates.append(temp2)
templ_shapes.append(temp2.shape[:: -1])

# templ_shapes contains (width and height) dimensions of your templates
# so use them to display bounding box

# detect and get ROI
target =cv2.imread("YourImage_Target_Path.png",cv2.IMREAD_GRAYSCALE)
count = 0
for template in templates:
result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)
loc = np.where(result >= threshold)
for pt in zip(*loc[::-1]):
    # pt is the top left corner of the template location so pt[0] + templ_shapes[count][0] is the X bottom right ...
    # templ_shapes[count][0] is the width and templ_shapes[count][1] is height
    cv2.rectangle(target, pt, (pt[0] + templ_shapes[count][0], pt[1] + templ_shapes[count][1]), (0, 0, 255), 2)
    roi = target[pt[1]:pt[1] + templ_shapes[count][1] ,pt[0] :pt[0] +templ_shapes[count][0]] 
count+=1


4 commentaires

Merci pour l'aide. Mais les images sont de tailles différentes.


Définissez donc la 1ère et la n-ième taille et utilisez-les dans votre boucle dans le même ordre.


Nous vous remercions de votre suivi. mais je ne comprends toujours pas ...


J'ai édité ma réponse. vous pouvez vérifier la modification



1
votes

ce que vous avez essayé de faire est un algorithme de détection d'objets. jetez un œil à ce tutoriel opencv. https://docs.opencv.org/2.4/doc/ tutoriels / features2d / feature_homography / feature_homography.html pour améliorer la vitesse, essayez de remplacer Surf keypoint par orb keypoint (pour votre cas d'utilisation, ce sera probablement assez bon, (si vous faites cela, n'oubliez pas de modifier la norme de L2 à Hamming)) c'est une généralisation de votre problème. Cordialement


0 commentaires

1
votes

Dans votre boucle externe, en itérant les entrées du dictionnaire

for key, value in list_of_areas.iteritems():
    y, y1, x, x1 = value
    target_area = big_pic[y:y1, x:x1]

la valeur est une liste de quatre entiers, par exemple [0, 300, 0, 100] . Ainsi, lorsque vous essayez maintenant d'itérer cette liste en utilisant

for y, y1, x, x1 in value:

, vous obtiendrez quatre itérations, et à chaque itération, exactement un élément de la liste sera "retourné" à la fois . Mais maintenant, vous essayez d'attribuer cette valeur entière unique "retournée" à quatre variables simultanément par

for (...) in value:

d'où l'erreur! Donc, de mon point de vue, la solution la plus simple serait de sauter la boucle interne et d'assigner directement tous les éléments de la valeur à vos quatre variables, comme ceci:

for key, value in list_of_areas.iteritems():

J'espère que cela vous aidera!


0 commentaires