Area processing steps#
Area processing steps use a neighborhood of samples and therefore a non-zero local halo (the halo describes the neighborhood). They require the Shared-memory API. Some area processing steps may also require temporary storage. Compose halo on ingest and on each neighborhood step with Halo operators (see also Halos and step order). Resize is included as an area processing step because it needs halo and changes tile geometry like other area family steps.
Box blur#
function::box_blur. Function<function::box_blur>() with BoxBlur<Width, Height> applies a NxM
box filter (arithmetic mean) over the internal tile. Width and Height must be odd
integers \(\geq\) 1. The required halo is (Width - 1) / 2 horizontally and (Height - 1) / 2
vertically.
using BoxBlur3x3 = decltype(
Function<function::box_blur>() +
BoxBlur<3, 3>() +
TileSize<48, 48>() +
Block() +
SM<900>());
Each output sample is the average of all samples in the Width x Height neighborhood. The
cell-based implementation uses a sliding-window. Box blur is a common building block for
multi-pass smoothing (for example, three or more passes approximate a wider Gaussian).
Warning
Width and Height must be odd integers \(\geq\) 1. BoxBlur enforces this at compile
time with static_assert; even dimensions are rejected rather than accepted with a
shifted kernel.
Gaussian blur#
function::gaussian_blur. Function<function::gaussian_blur>() with GaussianBlur<RadiusTenths[, TailWidth]> applies a
discrete Gaussian FIR (Finite Impulse Response) filter over the internal tile. RadiusTenths is an integer from
1 to 100, giving a pixel radius of 0.1 to 10.0 in steps of 0.1 (for example 20 \(\rightarrow\) pixel radius
2.0). (As a rule of thumb, a pixel radius of 1.0 tends to remove detail that is 1.0 pixel or less in size.)
Optional TailWidth selects neighborhood size for the same \(\sigma\) (default
gaussian_tail_width::standard):
standard: discrete Gaussian with \(\sigma\) = RadiusTenths/10; neighborhood sized for approximately one \(\sigma\) of support.wide: at the same pixel radius, \(\sigma\) = RadiusTenths/10; larger support neighborhood (approximately two \(\sigma\) of support). The extra support improves accuracy by retaining more of the Gaussian tails.widerequiresRadiusTenths\(\leq\) 50 so the neighborhood stays within the library maximum of 21x21.
Neighborhood size grows with pixel radius; halo is half the neighborhood width.
For wide, the neighborhood is about twice as wide as standard for the same RadiusTenths
(for example 35 is 9x9 for standard and 17x17 for wide).
Range |
Neighborhood |
Neighborhood |
Actual pixel radius (\(\sigma\)) |
|---|---|---|---|
1–9 |
3x3 |
5x5 |
0.1–0.9 |
10–20 |
5x5 |
9x9 |
1.0–2.0 |
21–30 |
7x7 |
13x13 |
2.1–3.0 |
31–40 |
9x9 |
17x17 |
3.1–4.0 |
41–50 |
11x11 |
21x21 |
4.1–5.0 |
51–60 |
13x13 |
n/a ( |
5.1–6.0 |
61–70 |
15x15 |
n/a |
6.1–7.0 |
71–80 |
17x17 |
n/a |
7.1–8.0 |
81–90 |
19x19 |
n/a |
8.1–9.0 |
91–100 |
21x21 |
n/a |
9.1–10.0 |
// Radius 2.0, standard neighborhood, requires 2 halo on each side
using Gaussian2 = decltype(
Function<function::gaussian_blur>() +
GaussianBlur<20>() +
TileSize<48, 48>() +
Block() +
SM<900>());
// Radius 3.5, same sigma, wide neighborhood (17x17), halo 8
using GaussianWide35 = decltype(
Function<function::gaussian_blur>() +
GaussianBlur<35, gaussian_tail_width::wide>() +
TileSize<48, 48>() +
Block() +
SM<900>());
Three or more passes of box blur can approximate a Gaussian (see box blur above); gaussian_blur uses
an explicit FIR instead. See 03_area_operation/gaussian_blur_fused_conversion.cu.
Median filter#
function::median. Function<function::median>() with Median<median_radius:: ...> selects the median of a
fixed neighborhood on the internal tile. NPPDx distinguishes square windows (full
rectangular kernels) from round windows (plus-shaped or corner-trimmed neighborhoods).
The round medians are slightly faster and more isotropic than the square medians and their diagonal artifacts are minimized.
|
Shape |
Samples |
Neighborhood |
|---|---|---|---|
|
Round |
5 |
Plus (cross): center pixel and its four axis neighbors in a 3x3 footprint. |
|
Square |
9 |
3x3 Median filter. NPP 3x3 median equivalent; see |
|
Round |
21 |
Round 5x5: all positions in a 5x5 square except the four corners. |
|
Square |
25 |
5x5 Median Filter. NPP 5x5 median equivalent. |
Halo size follows the extent of the neighborhood: 1 pixel for r0_5 and r1_0;
2 pixels for r1_5 and r2_0.
// Square 3x3 median
using Median3x3 = decltype(
Function<function::median>() +
Median<median_radius::r1_0>() +
TileSize<48, 48>() +
Block() +
SM<900>());
// Round 21-sample median (5x5 minus corners)
using MedianRound = decltype(
Function<function::median>() +
Median<median_radius::r1_5>() +
TileSize<48, 48>() +
Block() +
SM<900>());
Resize#
function::resize. Function<function::resize>() with Resize<J, K, Method> performs a resize of
J input samples to K output samples along each axis (coprime J and K).
Method is an interpolation_method:
Nearest neighbor
nearest: Selects the nearest input sample; no blurring but blocky or pixellated results when going larger, has aliasing artifacts when going smaller. No halo required.Bilinear interpolation
bilinear: Linear interpolation on both axes. Smooth linear blend of neighboring samples. Best used for integer scaling factors.Mitchell-Netravali cubic kernel
bicubic: Catmull-Rom (B=0, C=0.5). Smoother than bilinear; loses detail near Nyquist but adds some sharpening to make up for it.Lanczos-3
lanczos3: Windowed sinc function (sinc(x)*sinc(x/3)). Preserves high frequency details the best of these methods. Requires a large halo especially when downscaling.
Resize typically needs a non-zero local halo that depends on the interpolation kernel, and it changes
output tile geometry relative to the input. Refer to resize-related storage traits (for example
output_storage_of_t and temp_storage_of_t) and size the grid from the output dimensions.
See Shared-memory storage traits and 04_resize/resize_example.cu.
using Resize2x = decltype(
Function<function::resize>() +
Resize<1, 2, interpolation_method::bilinear>() +
TileSize<48, 48>() +
Block() +
SM<900>());
See also 04_resize/fused_resize.cu for resize fused with box blur and color convert.