--J'ai installé CUDA activé OpenCV (Python), mais je n'ai pas trouvé la documentation (japonais / anglais) et l'exemple de code, donc je l'ai écrit en référence à la version c ++. --CUDA Vive voulait essayer ――Je voulais écrire un article sur Qiita
--OpenCV compatible CUDA installé sur Ubuntu
Tout d'abord, lisez diverses choses, puis obtenez 200 * 200 maharo.jpg. Il s'agit du [Mahalo-kun] de Kawauso dans l'aquarium Sunshine (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% C'est une image de 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()
Ensuite, définissez les variables autour du GPU.
Vous pouvez vérifier si le GPU est activé en vérifiant si «cv2.cuda.getCudaEnabledDeviceCount ()» renvoie un nombre supérieur ou égal à 1.
Fondamentalement, OpenCV compatible CUDA peut être utilisé en réécrivant «cv2.function» en «cv2.cuda.function». (Il y a quelques exceptions, comme ce modèle de correspondance. Voir dir (cv2.cuda)
pour plus de détails)
De plus, la mémoire des variables et du GPU est sécurisée par cv2.cuda_GpuMat ()
, et les informations sont échangées entre les mémoires par .upload () /. Download ()
.
print(cv.cuda.getCudaEnabledDeviceCount())
g_src = cv.cuda_GpuMat()
g_dst = cv.cuda_GpuMat()
g_src.upload(src)
Pour le moment, j'ai déplacé l'image de Mahalo vers le GPU. Resize Expérimentons le goût du matériel GPU avec juste Resize (512-> 2K) qui n'inclut pas les informations de lecture / écriture dans la boucle. À propos, CUDA ne prend pas en charge l'interpolation Lanczos. (Il y a quelque chose comme ça dans l'ensemble) 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)
__ Le goût du matériau est lent __ Cela a entraîné certains avantages non liés au GPU. À propos, la vitesse d'exécution compte tenu de la lecture et de l'écriture à partir du processeur est plus lente.
%%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)
Même si j'ai eu du mal à intégrer CUDA, je n'aime pas ça. Eh bien, ça ne ressemble pas à ça en parallèle, est-ce difficile? Il semble que la lecture et l'écriture prennent environ 800 μs. De quoi cela dépend-il? Je pense que PCIe 3.0 sera le goulot d'étranglement (aucune base)
Template Matching Jetons un second regard et faisons la correspondance de modèles qui semble être utile en parallèle.
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)
Ce n'est pas plus lent que prévu ... (Ajout: probablement parce que le processus s'exécute sur 32 threads.)
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()
CUDA
La version CUDA du template maching est un peu spéciale (pour Python), mais elle est définie comme createTemplateMatching (precision, METHOD)
.
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)
__ Le matériau a bon goût __ CPU: Par rapport à 138 ms, CUDA a atteint une vitesse de 10,5 ms, soit environ 10 fois plus rapide.
%%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)
Même si vous calculez la lecture / écriture, c'est toujours environ 8 fois plus rapide. C'est le cas de la GTX 1080, donc avec le GPU de génération Ampère récemment évoqué, encore plus rapide ...? J'ai seulement besoin de max_locg, mais y a-t-il un moyen de récupérer max_locg au stade gresult?
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()
print(max_loc,max_locg)
# (1000, 1000) (1000, 1000)
Le même résultat est obtenu.
Le code utilisé cette fois (Jupyter Notebook) est publié sur Github.
Code de test Construire OpenCV avec CUDA activé sur Ubuntu
Recommended Posts