0

A big picture (300*300 pixels) divided into 3 areas. 2 small ones (AAA.png and BBB.png) are portions of the big picture.

3-areas.png

3-areas.png

AAA.png

AAA.png

BBB.png

BBB.png

I want to know in which areas they located in, i.e. find small pictures in the big picture. The ideal output would be: "AAA.png is in the left"; "BBB.png is in the right".

I have these codes running:

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

I want to simplify it by making for loops. What I tried:

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]

The "for y,y1,x,x1 in value:" line gives error: "TypeError: 'int' object is not iterable."

What would be the best way to achieve it? Thank you.

2
  • Another general advice: It seems, you're using Python 2 (print, iteritems). It's beneficial to mention that, for example by adding the python-2.x tag. So people don't get confused, because they wondering, why there's no iteritems for dictionaries... ;-)
    – HansHirse
    Commented Dec 6, 2019 at 9:23
  • @HansHirse, thanks! would you consider to make it an answer so that we can close this question?
    – Mark K
    Commented Dec 13, 2019 at 2:59

3 Answers 3

1

In your outer loop, iterating the dictionary entries

for key, value in list_of_areas.iteritems():

the value is a list of four integers, e.g. [0, 300, 0, 100]. So, when you now try to iterate this list using

for (...) in value:

you'll get four iterations, and in each iteration, exactly one list item will be "returned" at a time. But now, you try to assign this "returned", single integer value to four variables simultaneously by

for y, y1, x, x1 in value:

hence the error! So, from my point of view, the easiest solution would be, to skip the inner loop, and directly assign all items in value to your four variables, like so:

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

Hope that helps!

1

what you tried to do is an objet detection algorithm. take a look at this opencv tutorial. https://docs.opencv.org/2.4/doc/tutorials/features2d/feature_homography/feature_homography.html to improve speed, try to replace Surf keypoint by orb keypoint (for your use case it will be probably good enougth, (if you do that, do not forget to modify the norm from L2 to Hamming )) it is a generalization of your problem. kind regards

0
1

This is how to detect multiple templates and crop 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
  • thanks for the help. but the pictures are of different sizes.
    – Mark K
    Commented Dec 13, 2019 at 2:57
  • So set 1st and n-th size and use them in your loop in same order.
    – Ziri
    Commented Dec 13, 2019 at 3:18
  • thank you for your follow-up. but I still don't understand...
    – Mark K
    Commented Dec 13, 2019 at 5:08
  • I edited my answer . you can check the modification
    – Ziri
    Commented Dec 13, 2019 at 9:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.