Multiple template matching

In the actual combat of the last article, we found out the position of the person’s eyes in the image through the subgraph. But, in some cases, not just once, for example, when we showed the Fourier transform, we showed a picture of a lion in a prairie. If you match one grass, there may be many in a single image, so you have to find multiple matches.

The cv2.minmaxloc () function can only find the maximum value, but cannot give the location information of all matching regions. So, to match multiple results, you need to go through the following four steps:

Gets a collection of matching locations

First, the where() function in the Numpy library gets a collection of the locations where the template matches. The return value is different for different inputs.

  1. When the input is a one-dimensional array, the return value is a one-dimensional index, just a set of indexed arrays.
  2. When the input is a two-dimensional array, the index of the position of the matched value is returned, so there are two sets of indexed arrays representing the position of the returned value.

For example, our grayscale images are usually two-dimensional arrays. Next, let’s find the index of the elements in a two-dimensional array whose value is greater than 8:

import numpy as np

img = np.array([[2.4.6.8.10], [9.60.10.30.4], [55.21.11.7.5]])
result = np.where(img > 5)
print(result)
Copy the code

After running, the console will output something like this:

If you don’t know much about Numpy. The following blogger in the data conversion below, basically can understand. After conversion, the format is as follows:

The x-coordinate of the value greater than 5 in the first behavior, the y-coordinate of the value greater than 5 in the second behavior. Then the array index greater than 5 above is: [0, 2], [0, 3], [0, 4], [1, 0], [1, 1], [1, 2], [1, 3], [2, 0], [2, 1], [2], [2, 3]. You can go back and see if it’s consistent.

The np.where() function is used to find out where the value in the return value of the cv2.matchtemplate () function is greater than threshold. The specific operation code is as follows:

loc=np.where(res>threshold)
Copy the code

cycle

Because the original image we found corresponds to more than one template image, we must use a loop to process multiple values. Therefore, after obtaining the index of the matching value, you can use the following statement to traverse all the matching positions and mark them:

for i inSet of matching positions: Marks matching positionsCopy the code

Using zip() in a loop

The function zip() takes iterable objects as arguments, packages the corresponding elements of the object into tuples, and then returns a list of those tuples.

For example, we get indexes x,y,z. Let’s use zip() to package them into tuples. The code is as follows:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = np.array([[2.4.6.8.10], [9.60.10.30.4], [55.21.11.7.5]])
result = np.where(img > 5)
for i in zip(*result):
    print(i)
Copy the code

Here we use the above values again, and the output looks like this:

The index that we just met the criteria is automatically packaged into an element format. Is it more intuitive than the console output just now?

Replace the coordinates

The result we got above is the index that meets the criteria :(row number, column number), but we need to draw the rectangle matching the position, and what we need is (column number, row number).

So, before you use cv2.Rectangle () to draw a rectangle, swap the rows and positions obtained by numpy.Where (). You can do this by using the following code:

import numpy as np

img = np.array([[2.4.6.8.10], [9.60.10.30.4], [55.21.11.7.5]])
result = np.where(img > 5)
for i in zip(*result[::-1) :print(i)
Copy the code

After running, the output is as follows:

Actual combat multiple template matching

Now that we’ve seen the four steps to tag the location of multiple templates to draw. Below, we will directly clean up the above code, you can complete the match of multiple templates. The specific code is as follows:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("34.jpg".0)
template = cv2.imread("4_1.jpg".0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.9
loc = np.where(res >= 0.9)
for i in zip(*loc[::-1]):
    cv2.rectangle(img, i, (i[0] + w, i[1] + h), 255.1)
plt.imshow(img, cmap="gray")
plt.axis("off")
plt.show()
Copy the code

The code here is exactly the same as the above four steps, so I won’t go into details too much. After running, the multiple templates are matched.

Appendix:

Template figure

The original image