图像解码器示例#

在本笔记本中,我们将展示不同类型的 decoders.image 的用法示例。您将看到,这些变体为 CPU 后端 (device="cpu") 和混合后端 (device="mixed" - 其中解码由 GPU 加速) 提供了相同的功能。

请注意,我们定义了所有示例以接受 device 参数,以便我们稍后可以轻松更改它。

通用代码#

首先,让我们定义一些通用函数,使我们能够轻松显示图像。

[1]:
from nvidia.dali import pipeline_def
import nvidia.dali.fn as fn
import nvidia.dali.types as types
import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
from nvidia.dali.backend import TensorListGPU

%matplotlib inline

seed = 1549361629


def show_images(image_batch):
    columns = 4
    rows = (batch_size + 1) // (columns)
    fig = plt.figure(figsize=(32, (32 // columns) * rows))
    gs = gridspec.GridSpec(rows, columns)
    for j in range(rows * columns):
        plt.subplot(gs[j])
        plt.axis("off")
        plt.imshow(image_batch.at(j))


image_dir = "../data/images"
batch_size = 4


def show_pipeline_output(pipeline):
    pipe.build()
    (images,) = pipe.run()
    if isinstance(images, TensorListGPU):
        images = images.as_cpu()
    show_images(images)

图像解码器 (CPU)#

decoders.image 解码以常见格式(包括 JPEG、JPEG2000、TIFF、PNG)存储的图像

[2]:
@pipeline_def(seed=seed)
def image_decoder_pipeline(device="cpu"):
    jpegs, labels = fn.readers.file(file_root=image_dir)
    return fn.decoders.image(jpegs, device=device)


pipe = image_decoder_pipeline(batch_size=batch_size, num_threads=1, device_id=0)
show_pipeline_output(pipe)
../../_images/examples_image_processing_decoder_examples_4_0.png

具有随机裁剪窗口大小和锚点的图像解码器 (CPU)#

decoders.image_random_crop 生成随机裁剪的图像。随机裁剪窗口基于给定的纵横比和面积分布生成。

[3]:
@pipeline_def(seed=seed)
def image_decoder_random_crop_pipeline(device="cpu"):
    jpegs, labels = fn.readers.file(file_root=image_dir)
    images = fn.decoders.image_random_crop(
        jpegs,
        random_aspect_ratio=[0.8, 1.25],
        random_area=[0.1, 1.0],
        num_attempts=100,
        device=device,
    )
    return images


pipe = image_decoder_random_crop_pipeline(
    batch_size=batch_size, num_threads=1, device_id=0
)
show_pipeline_output(pipe)
../../_images/examples_image_processing_decoder_examples_6_0.png

具有固定裁剪窗口大小和外部锚点的图像解码器#

decoders.image_crop 生成具有固定裁剪窗口大小和可变位置的裁剪图像

[4]:
@pipeline_def(seed=seed)
def image_decoder_crop_pipeline(device="cpu"):
    jpegs, labels = fn.readers.file(file_root=image_dir)
    pos_x = fn.random.uniform(range=(0.0, 1.0))
    pos_y = fn.random.uniform(range=(0.0, 1.0))
    return fn.decoders.image_crop(
        jpegs,
        crop=(244, 244),
        crop_pos_x=pos_x,
        crop_pos_y=pos_y,
        device=device,
    )


pipe = image_decoder_crop_pipeline(
    batch_size=batch_size, num_threads=1, device_id=0
)
show_pipeline_output(pipe)
../../_images/examples_image_processing_decoder_examples_8_0.png

具有外部窗口大小和锚点的图像解码器 (CPU)#

decoders.image_slice 基于描述裁剪窗口大小和位置的附加张量输入生成裁剪图像

[5]:
import numpy as np
from itertools import product

pos_source = [[0.4, 0.2], [0.3, 0.3]]
size_source = [[0.3, 0.5], [0.3, 0.2]]


def ext_source_generator():
    for pos, size in product(pos_source, size_source):
        yield np.array(pos, dtype=np.float32), np.array(size, dtype=np.float32)


@pipeline_def(seed=seed)
def image_decoder_slice_pipeline(device="cpu"):
    crop_pos, crop_size = fn.external_source(
        source=ext_source_generator,
        cycle=True,
        num_outputs=2,
        batch=False,
        dtype=types.FLOAT,
    )
    jpegs, labels = fn.readers.file(file_root=image_dir)
    return fn.decoders.image_slice(jpegs, crop_pos, crop_size, device=device)


pipe = image_decoder_slice_pipeline(
    batch_size=batch_size, num_threads=1, device_id=0
)
show_pipeline_output(pipe)
../../_images/examples_image_processing_decoder_examples_10_0.png

图像解码器 (混合)#

decoders.image 与混合后端一起使用时,会将 JPEG 解码卸载到 GPU 或专用硬件单元(如果存在)。

请注意,我们重复了上面显示的示例,仅更改了 device 参数。操作器及其其他参数都保持不变并提供相同的功能 - 但现在我们使用 GPU 加速。

注意

如果您想知道为什么解码器使用 device="mixed" 而不是 device="gpu" - 这是因为它将 GPU 解码与将图像从 CPU 传输到 GPU 内存融合在一起。要了解有关 DALI pipeline 阶段的更多信息,请参阅pipeline 文档部分

[6]:
pipe = image_decoder_pipeline(
    batch_size=batch_size, num_threads=1, device_id=0, device="mixed"
)
pipe.build()
(images,) = pipe.run()
show_images(images.as_cpu())
../../_images/examples_image_processing_decoder_examples_12_0.png

具有随机裁剪窗口大小和锚点的图像解码器 (混合)#

decoders.image_random_crop 生成随机裁剪的图像。随机裁剪窗口基于给定的纵横比和面积分布生成。

[7]:
pipe = image_decoder_random_crop_pipeline(
    batch_size=batch_size, num_threads=1, device_id=0, device="mixed"
)
show_pipeline_output(pipe)
../../_images/examples_image_processing_decoder_examples_14_0.png

具有固定裁剪窗口大小和外部锚点的图像解码器 (混合)#

decoders.image_crop 生成具有固定裁剪窗口大小和可变位置的裁剪图像

[8]:
pipe = image_decoder_crop_pipeline(
    batch_size=batch_size, num_threads=1, device_id=0, device="mixed"
)
show_pipeline_output(pipe)
../../_images/examples_image_processing_decoder_examples_16_0.png

具有外部窗口大小和锚点的图像解码器 (混合)#

decoders.image_slice 基于描述裁剪窗口大小和位置的附加张量输入生成裁剪图像

[9]:
pipe = image_decoder_slice_pipeline(
    batch_size=batch_size, num_threads=1, device_id=0, device="mixed"
)
show_pipeline_output(pipe)
../../_images/examples_image_processing_decoder_examples_18_0.png