[PYTHON] Affine Transformation durch OpenCV (CUDA)

Motivation

Siehe Frühere Artikel

Zusammenfassung

--Affine Konvertierung wurde mit OpenCV unter Python durchgeführt --Fazit

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). Weitere Informationen zu diesem Bereich finden Sie unter Frühere Artikel.

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
print('Enabled CUDA devices:',cv.cuda.getCudaEnabledDeviceCount()) # 1

src = cv.cvtColor(cv.imread("maharo.jpg "),cv.COLOR_BGR2RGB)
h, w, c = src.shape #200, 200, 3
plt.subplot(111),plt.imshow(src)
plt.title('otter image'), plt.xticks([]), plt.yticks([])
plt.show()

g_src = cv.cuda_GpuMat()
g_dst = cv.cuda_GpuMat()
g_src.upload(src)

image.png Definieren Sie zunächst die affine Umwandlungsmatrix. Durch die Kombination von Drehung um die Mitte und paralleler Bewegung wird die Mittelachse um Skalenzeiten gedreht.

def get_rot_affine(src, rot, scale):
    h, w = src.shape[::-1]
    rot_affine = cv.getRotationMatrix2D((h/2, w/2), rot, scale)
    rot_affine[:2,2] -= [h/2, w/2]
    rot_affine[:2,2] += [h/2*scale, w/2*scale]
    return rot_affine

1x 20 Grad Drehung

Definieren Sie für die gleiche 20-Grad-Drehung die Affiliate-Matrix wie folgt. CUDA unterstützt übrigens keine Lanczos-Interpolation.

rot_affine = get_rot_affine(src, 20, 1)

CPU Versuchen Sie es zuerst auf der CPU.

%%timeit
img_dst = cv.warpAffine(src, rot_affine, (w*1, h*1), flags=cv.INTER_CUBIC)
# 1.08 ms ± 7.24 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

image.png

CUDA Ich möchte den Geschmack von GPU-Materialien nur durch Verarbeitung erfahren, bei der keine Lese- / Schreibinformationen in der Schleife enthalten sind. Wie üblich wird "cv2.cuda.wrapAffine" verwendet, aber die Argumente sind nur das Quellbild "src" und das Ausgabebild "dst" auf der GPU, und die Affiliate-Matrix und die dst-Größe sind die gleichen wie bei der normalen cv.wrapAffine. Scheint zu verwenden. (Ich werde wütend, wenn ich es auf die GPU lege).

%%timeit
g_dst = cv.cuda.warpAffine(g_src, rot_affine, (w*1, h*1), flags=cv.INTER_CUBIC)
# 383 µs ± 28.6 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

Nun, es ist so ... Wenn das Bild klein ist, scheint es nur etwa zwei- bis dreimal effektiver zu sein.

%%timeit
g_src.upload(src)
g_dst = cv.cuda.warpAffine(g_src, rot_affine, (w*1, h*1), flags=cv.INTER_CUBIC)
gpu_dst = g_dst.download()
# 450 µs ± 5.11 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

image.png

Selbst wenn Sie lesen / schreiben möchten, ändert sich die Geschwindigkeit nicht so stark. (Weil das Bild hell ist)

10 mal 20 Grad Drehung

Machen Sie Mahalo 10 Mal (2K) und drehen Sie es um 20 Grad. Die affine Matrix heißt wie folgt.

rot_affine = get_rot_affine(src, 20, 10)

CPU Versuchen Sie es zuerst auf der CPU.

%%timeit
img_dst = cv.warpAffine(src, rot_affine, (w*10, h*10), flags=cv.INTER_CUBIC)
# 7.29 ms ± 36.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Für eine 10-fache Vergrößerung ist es ziemlich schnell. Dies ist umgebungsabhängig. Die Parallelisierung funktionierte bei der Verarbeitung von 200-Pixel-Bildern nicht gut, und die CPU wurde mit 1 Thread ausgeführt. Bei der Verarbeitung von 2K-Bildern funktionierte die Parallelisierung von 32 Threads jedoch ordnungsgemäß. Das hängt von der Geschwindigkeit ab. (Es wird langsamer, wenn Sie es mit einem normalen Core i5 / 7 usw. tun. Übrigens ist 2 * Xeon E5-2667 v3 bei 3,20 GHz in der Verifizierungsumgebung laut Cinebench ungefähr 1 * Ryzen 9 3900XT. Es ist die Ära ...)

image.png

CUDA

%%timeit
g_dst = cv.cuda.warpAffine(g_src, rot_affine, (w*10, h*10), flags=cv.INTER_CUBIC)
# 1.42 ms ± 16.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Es ist ungefähr 5 mal schneller als die CPU. Nun, es ist ziemlich einfach zu verstehen und schnell, es sei denn, die andere Partei ist Xeon, aber es scheint, dass GTX 1080 ein bisschen schlecht ist.

%%timeit
g_src.upload(src)
g_dst = cv.cuda.warpAffine(g_src, rot_affine, (w*10, h*10), flags=cv.INTER_CUBIC)
gpu_dst = g_dst.download()
# 2.64 ms ± 163 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Beim Importieren / Exportieren dauert es etwas, da das Bild groß ist.

image.png

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

Referenz

Affin-Konvertierung vollständig verstehen

Recommended Posts

Affine Transformation durch OpenCV (CUDA)
Template Matching von OpenCV (CUDA)
Affin-Konvertierung
Anwendung der affinen Umwandlung durch Tensor - von der Basis- zur Objekterkennung -
[FSL] Affine Umwandlung (parallele Bewegung + lineare Umwandlung)
[Python] Verwenden von OpenCV mit Python (Bildtransformation)
Denken Sie an Transformation Janken durch Optimierung
Beschleunigung des Lesevorgangs durch Angabe eines OpenCV-Frames
Horizontale Linienverarbeitung mit OpenCV-Morphologietransformation
Objekterkennung mit openCV durch traincascade
Erkennen Sie das Othello-Board mit OpenCV