nvImageCodec 与 cuPy#

[1]:
import os
import cv2
import cupy as cp
from matplotlib import pyplot as plt

设置资源文件夹

[2]:
resources_dir = os.getenv("PYNVIMGCODEC_EXAMPLES_RESOURCES_DIR", "../assets/images/")

导入 nvImageCodec 模块并创建解码器和编码器

[3]:
from nvidia import nvimgcodec
decoder = nvimgcodec.Decoder()
encoder = nvimgcodec.Encoder()

使用 nvImageCodec 加载 jpeg2000 图像

[4]:
nv_img = decoder.read(resources_dir + "cat-1046544_640.jp2")
print(nv_img.__cuda_array_interface__)
{'shape': (475, 640, 3), 'strides': None, 'typestr': '|u1', 'data': (12918456320, False), 'version': 3, 'stream': 1}

将 nvImageCodec 图像传递给 cupy asarray,因为它接受 __cuda_array_interface__

[5]:
%%time
cp_img = cp.asarray(nv_img)
print(cp_img.__cuda_array_interface__)
{'shape': (475, 640, 3), 'typestr': '|u1', 'descr': [('', '|u1')], 'stream': 1, 'version': 3, 'strides': None, 'data': (12918456320, False)}
CPU times: user 796 µs, sys: 716 µs, total: 1.51 ms
Wall time: 1.26 ms

转换为 numpy 并显示

[6]:
np_img4k = cp.asnumpy(cp_img)
plt.imshow(np_img4k)
[6]:
<matplotlib.image.AxesImage at 0x7f55c4f97fa0>
../_images/samples_cupy_sample_11_1.png

让我们在 GPU 上使用 cupyx.scipy 对图像进行一些操作

[7]:
import cupyx.scipy.ndimage
[8]:
cp_img_rotated = cupyx.scipy.ndimage.rotate(cp_img, 90)
cp_img_gaussian = cupyx.scipy.ndimage.gaussian_filter(cp_img, sigma = 5)

print(cp_img_rotated.__cuda_array_interface__)
{'shape': (640, 475, 3), 'typestr': '|u1', 'descr': [('', '|u1')], 'stream': 1, 'version': 3, 'strides': None, 'data': (140001566883840, False)}
[9]:
np_img = cp.asnumpy(cp_img_rotated)
plt.imshow(np_img)
[9]:
<matplotlib.image.AxesImage at 0x7f55b748de20>
../_images/samples_cupy_sample_15_1.png
[10]:
np_img = cp.asnumpy(cp_img_gaussian)
plt.imshow(np_img)
[10]:
<matplotlib.image.AxesImage at 0x7f55b740dee0>
../_images/samples_cupy_sample_16_1.png

使用 __cuda_array_interface__ 将 cupy 图像转换为 nvImageCodec 图像

[11]:
%%time
nv_rotated_img = nvimgcodec.as_image(cp_img_rotated)
CPU times: user 43 µs, sys: 29 µs, total: 72 µs
Wall time: 76.1 µs

检查内容

[12]:
plt.imshow(nv_rotated_img.cpu())
[12]:
<matplotlib.image.AxesImage at 0x7f55b738b820>
../_images/samples_cupy_sample_20_1.png

保存为 Jpeg2000

[13]:
encoder.write("rotated.j2k", nv_rotated_img)

使用 OpenCV 加载以验证

[14]:
image = cv2.imread("rotated.j2k")
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(image)
[14]:
<matplotlib.image.AxesImage at 0x7f55b72fd5e0>
../_images/samples_cupy_sample_24_1.png

使用 nvImageCodec 将 cupy 图像保存为 jpg

[15]:
nv_img_gaussian = nvimgcodec.as_image(cp_img_gaussian)
encoder.write("gaussian.jpg", nv_img_gaussian)

使用 OpenCV 重新读取以验证

[16]:
image = cv2.imread("gaussian.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(image)
[16]:
<matplotlib.image.AxesImage at 0x7f55b7270f40>
../_images/samples_cupy_sample_28_1.png

DLPack#

使用 DLPack 将 cuPy ndarray 传递给 nvImageCodec。cuPy ndarray 同时具有 __cuda_array_interface__ 和 __dlpack__ 接口。默认情况下,当我们使用 as_image 函数将 cuPy ndarray 传递给 nvImageCodec 时,将首选 __cuda_array_interface__ 并使用它。如果我们想使用 DLPack,首先需要从 cuPy ndarray 中获取 PyCapsule,然后将其传递给 nvImageCodec。

[17]:
dlpack_img = cp_img_gaussian.toDlpack()
nv_img_gaussian = nvimgcodec.as_image(dlpack_img)
encoder.write("gaussian_dlpack.jpg", nv_img_gaussian)
[18]:
image = cv2.imread("gaussian_dlpack.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
plt.imshow(image)

[18]:
<matplotlib.image.AxesImage at 0x7f55b71e9c70>
../_images/samples_cupy_sample_32_1.png

使用 DLPack 将 nvImageCodec 图像传递给 cuPy

[19]:
nv_img = decoder.read(resources_dir + "cat-1046544_640.jp2")
cp_img = cp.from_dlpack(nv_img)
[20]:
np_img = cp.asnumpy(cp_img)
plt.imshow(np_img)
[20]:
<matplotlib.image.AxesImage at 0x7f55b71e44c0>
../_images/samples_cupy_sample_35_1.png

或者,可以先获取 PyCapsule,然后将其传递给 cuPy

[21]:
nv_img = decoder.read(resources_dir + "cat-1046544_640.jp2")
py_cap = nv_img.__dlpack__()
cp_img = cp.from_dlpack(py_cap)
[22]:
np_img = cp.asnumpy(cp_img)
plt.imshow(np_img4k)
[22]:
<matplotlib.image.AxesImage at 0x7f55b7159310>
../_images/samples_cupy_sample_38_1.png