[PYTHON] Template Matching von OpenCV (CUDA)

Motivation

Zusammenfassung

Umgebung

Code

Vorverarbeitung

Lesen Sie zuerst verschiedene Dinge und erhalten Sie dann 200 * 200 maharo.jpg. Dies ist Kawauso [Mahalo-Kun] im Sunshine Aquarium (https://wikiwiki.jp/kawausotter/%E3%83%9E%E3%83%8F%E3%83%AD%EF%BC%88%E3% 82% B5% E3% 83% B3% E3% 82% B7% E3% 83% A3% E3% 82% A4% E3% 83% B3% E6% B0% B4% E6% 97% 8F% E9% A4% Es ist ein Bild von A8% EF% BC% 89).

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

src = cv.imread("maharo.jpg ", cv.IMREAD_GRAYSCALE)
h, w = src.shape[::-1] # w=200, h=200

plt.subplot(111),plt.imshow(src,cmap = 'gray')
plt.title('otter image'), plt.xticks([]), plt.yticks([])
plt.show()

image.png

Als nächstes legen Sie die Variablen um die GPU herum fest. Sie können überprüfen, ob die GPU aktiviert ist, indem Sie überprüfen, ob "cv2.cuda.getCudaEnabledDeviceCount ()" eine Zahl größer oder gleich 1 zurückgibt. Grundsätzlich kann CUDA-fähiges OpenCV verwendet werden, indem "cv2.function" in "cv2.cuda.function" umgeschrieben wird. (Es gibt einige Ausnahmen, wie z. B. die Übereinstimmung dieser Vorlage. Weitere Informationen finden Sie unter dir (cv2.cuda).) Zusätzlich wird der Speicher von Variablen und GPU durch "cv2.cuda_GpuMat ()" gesichert, und Informationen werden zwischen den Speichern durch ".upload () /. Download ()" ausgetauscht.

print(cv.cuda.getCudaEnabledDeviceCount())
g_src = cv.cuda_GpuMat()
g_dst = cv.cuda_GpuMat()
g_src.upload(src)

Vorerst habe ich das Bild von Mahalo auf die GPU verschoben. Resize Lassen Sie uns den Geschmack des GPU-Materials mit nur Resize (512-> 2K) erleben, das keine Lese- / Schreibinformationen in der Schleife enthält. CUDA unterstützt übrigens keine Lanczos-Interpolation. (Es gibt so etwas im Großen und Ganzen) CPU

%%timeit
cpu_dst = cv.resize(src, (h*10, w*10), interpolation=cv.INTER_CUBIC)
# 777 µs ± 8.06 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

CUDA

%%timeit
g_dst = cv.cuda.resize(g_src, (h*4, w*4), interpolation=cv.INTER_CUBIC)
# 611 µs ± 6.34 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

__ Der Geschmack des Materials ist langsam __ Dies hat zu einigen Nicht-GPU-Vorteilen geführt. Übrigens ist die Ausführungsgeschwindigkeit beim Lesen und Schreiben von der CPU langsamer.

%%timeit
g_src.upload(src)
g_dst = cv.cuda.resize(g_src, (h*4, w*4), interpolation=cv.INTER_CUBIC)
gpu_dst = g_dst.download()
# 1.51 ms ± 16.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Obwohl es mir schwer gefallen ist, CUDA einzusetzen, gefällt es mir nicht. Nun, parallel dazu sieht es nicht so aus, ist es schwierig? Es scheint, dass das Lesen und Schreiben ungefähr 800 μs dauert. Wovon hängt das ab? Ich denke, dass PCIe 3.0 der Engpass sein wird (keine Basis)

Template Matching Lassen Sie uns einen zweiten Blick darauf werfen und einen Vorlagenabgleich durchführen, der parallel nützlich zu sein scheint.

ex_src = cv.resize(src, (h*10, w*10), interpolation=cv.INTER_CUBIC)
tmpl = ex_src[1000:1200, 1000:1200]
th, tw = tmpl.shape[::-1]

CPU

%%timeit
result = cv.matchTemplate(ex_src, tmpl, cv.TM_CCOEFF_NORMED)
# 138 ms ± 5.03 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Es ist nicht langsamer als ich erwartet hatte ... (Ergänzung: Wahrscheinlich, weil der Prozess auf 32 Threads ausgeführt wird.)

result = cv.matchTemplate(ex_src, tmpl, cv.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
top_left = max_loc
bottom_right = (top_left[0] + th, top_left[1] + tw)
cv.rectangle(ex_src,top_left, bottom_right, 255, 2)
plt.subplot(121),plt.imshow(result,cmap = 'gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(ex_src,cmap = 'gray')
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.show()

image.png CUDA Die CUDA-Version der Vorlagenbearbeitung ist etwas speziell (für Python), wird jedoch als "createTemplateMatching (Genauigkeit, METHODE)" definiert.

gsrc = cv.cuda_GpuMat()
gtmpl = cv.cuda_GpuMat()
gresult = cv.cuda_GpuMat()
gsrc.upload(ex_src)
gtmpl.upload(tmpl)
matcher = cv.cuda.createTemplateMatching(cv.CV_8UC1, cv.TM_CCOEFF_NORMED)
%%timeit
gresult = matcher.match(gsrc, gtmpl)
# 10.5 ms ± 406 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

__ Das Material schmeckt gut __ CPU: Im Vergleich zu 138 ms hat CUDA eine Geschwindigkeit von 10,5 ms erreicht, was etwa zehnmal schneller ist.

%%timeit
gsrc.upload(ex_src)
gtmpl.upload(tmpl)
matcher = cv.cuda.createTemplateMatching(cv.CV_8UC1, cv.TM_CCOEFF_NORMED)
gresult = matcher.match(gsrc, gtmpl)
resultg = gresult.download()
# 16.6 ms ± 197 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Selbst wenn Sie das Lesen / Schreiben berechnen, ist es immer noch ungefähr achtmal schneller. Dies ist bei der GTX 1080 der Fall, also mit der kürzlich erwähnten GPU der Ampere-Generation noch schneller ...? Ich brauche nur max_locg, aber gibt es eine Möglichkeit, max_locg im Gresult-Stadium abzurufen?

gresult = matcher.match(gsrc, gtmpl)
resultg = gresult.download()
min_valg, max_valg, min_locg, max_locg = cv.minMaxLoc(resultg)
top_leftg = max_locg
bottom_rightg = (top_leftg[0] + tw, top_leftg[1] + th)
cv.rectangle(src,top_leftg, bottom_rightg, 255, 2)
plt.subplot(121),plt.imshow(resultg,cmap = 'gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(ex_src,cmap = 'gray')
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.show()

image.png

print(max_loc,max_locg)
# (1000, 1000) (1000, 1000)

Das gleiche Ergebnis wird erhalten.

Der diesmal verwendete Code (Jupyter Notebook) wird auf Github veröffentlicht.

Referenz

Testcode Erstellen Sie OpenCV mit aktiviertem CUDA unter Ubuntu

Recommended Posts

Template Matching von OpenCV (CUDA)
Affine Transformation durch OpenCV (CUDA)
07. Anweisungsgenerierung nach Vorlage
Objektextraktion im Bild durch Mustervergleich mit OpenCV mit Python
Beschleunigung des Lesevorgangs durch Angabe eines OpenCV-Frames
Notation des Template Matchings mittels Faltung
Objekterkennung mit openCV durch traincascade
Erkennen Sie das Othello-Board mit OpenCV