diff --git a/bench_info/blur.json b/bench_info/blur.json new file mode 100644 index 0000000..c225032 --- /dev/null +++ b/bench_info/blur.json @@ -0,0 +1,26 @@ +{ + "benchmark": { + "name": "blur", + "short_name": "blur", + "relative_path": "image_processing/blur", + "module_name": "blur", + "func_name": "blur", + "kind": "microbench", + "domain": "Image Processing", + "dwarf": "dense_linear_algebra", + "parameters": { + "S": { }, + "M": { }, + "L": { }, + "paper": { } + }, + "init": { + "func_name": "initialize", + "input_args": [], + "output_args": ["image", "output"] + }, + "input_args": ["image", "output"], + "array_args": ["image", "output"], + "output_args": ["output"] + } +} \ No newline at end of file diff --git a/bench_info/hist.json b/bench_info/hist.json new file mode 100644 index 0000000..ec90748 --- /dev/null +++ b/bench_info/hist.json @@ -0,0 +1,26 @@ +{ + "benchmark": { + "name": "hist", + "short_name": "hist", + "relative_path": "image_processing/hist", + "module_name": "hist", + "func_name": "hist", + "kind": "microbench", + "domain": "Image Processing", + "dwarf": "dense_linear_algebra", + "parameters": { + "S": { }, + "M": { }, + "L": { }, + "paper": { } + }, + "init": { + "func_name": "initialize", + "input_args": [], + "output_args": ["image", "output"] + }, + "input_args": ["image", "output"], + "array_args": ["image", "output"], + "output_args": ["output"] + } +} \ No newline at end of file diff --git a/bench_info/iir_blur.json b/bench_info/iir_blur.json new file mode 100644 index 0000000..56b78c7 --- /dev/null +++ b/bench_info/iir_blur.json @@ -0,0 +1,26 @@ +{ + "benchmark": { + "name": "iir_blur", + "short_name": "iir_blur", + "relative_path": "image_processing/iir_blur", + "module_name": "iir_blur", + "func_name": "iir_blur", + "kind": "microbench", + "domain": "Image Processing", + "dwarf": "dense_linear_algebra", + "parameters": { + "S": { }, + "M": { }, + "L": { }, + "paper": { } + }, + "init": { + "func_name": "initialize", + "input_args": [], + "output_args": ["image", "output"] + }, + "input_args": ["image", "output"], + "array_args": ["image", "output"], + "output_args": ["output"] + } +} \ No newline at end of file diff --git a/data/image_processing/gray.png b/data/image_processing/gray.png new file mode 100644 index 0000000..87c6f2e Binary files /dev/null and b/data/image_processing/gray.png differ diff --git a/data/image_processing/rgb.png b/data/image_processing/rgb.png new file mode 100644 index 0000000..31038fd Binary files /dev/null and b/data/image_processing/rgb.png differ diff --git a/npbench/benchmarks/image_processing/blur/blur.py b/npbench/benchmarks/image_processing/blur/blur.py new file mode 100644 index 0000000..d9842da --- /dev/null +++ b/npbench/benchmarks/image_processing/blur/blur.py @@ -0,0 +1,12 @@ +# Copyright 2021 ETH Zurich and the NPBench authors. All rights reserved. +import numpy as np + +from PIL import Image +from pathlib import Path + +def initialize(): + image_path = Path(__file__).parent.parent.parent.parent.parent / "data/image_processing" / "gray.png" + image = np.array(Image.open(image_path), dtype=np.uint8) + output = np.empty((image.shape[0] - 2, image.shape[1] - 2), dtype=np.uint8) + + return image, output diff --git a/npbench/benchmarks/image_processing/blur/blur_cupy.py b/npbench/benchmarks/image_processing/blur/blur_cupy.py new file mode 100644 index 0000000..eb1d495 --- /dev/null +++ b/npbench/benchmarks/image_processing/blur/blur_cupy.py @@ -0,0 +1,16 @@ +import cupy as np + +def blur(image, output): + image = image.astype(np.float32) + blur_x = np.empty((image.shape[0], image.shape[1] - 2), dtype=np.float32) + blur_y = np.empty(output.shape, dtype=np.float32) + + filter = np.array([1.0, 1.0, 1.0], dtype=np.float32) / 3.0 + + for y in range(blur_x.shape[0]): + blur_x[y, :] = np.convolve(image[y, :], filter, mode='valid') + + for x in range(blur_y.shape[1]): + blur_y[:, x] = np.convolve(blur_x[:, x], filter, mode='valid') + + output[:,:] = np.clip(blur_y, 0.0, 255.0).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/blur/blur_dace.py b/npbench/benchmarks/image_processing/blur/blur_dace.py new file mode 100644 index 0000000..5f62bb7 --- /dev/null +++ b/npbench/benchmarks/image_processing/blur/blur_dace.py @@ -0,0 +1,20 @@ +import numpy as np +import dace as dc + +@dc.program +def blur(image: dc.uint8[2560, 1536], output: dc.uint8[2558, 1534]): + imagef = image.astype(np.float32) + blur_x = np.empty((imagef.shape[0], imagef.shape[1] - 2), dtype=np.float32) + blur_y = np.empty(output.shape, dtype=np.float32) + + for y in range(blur_x.shape[0]): + for x in range(blur_x.shape[1]): + blur_x[y, x] = (imagef[y, x] + imagef[y, x + 1] + imagef[y, x + 2]) / 3.0 + + for y in range(blur_y.shape[0]): + for x in range(blur_y.shape[1]): + blur_y[y, x] = (blur_x[y, x] + blur_x[y + 1, x] + blur_x[y + 2, x]) / 3.0 + + blur_y[blur_y < 0.0] = 0.0 + blur_y[blur_y > 255.0] = 255.0 + output[:,:] = blur_y.astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/blur/blur_numba_n.py b/npbench/benchmarks/image_processing/blur/blur_numba_n.py new file mode 100644 index 0000000..e2a0882 --- /dev/null +++ b/npbench/benchmarks/image_processing/blur/blur_numba_n.py @@ -0,0 +1,18 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=True, parallel=False, fastmath=True) +def blur(image, output): + image = image.astype(np.float32) + blur_x = np.empty((image.shape[0], image.shape[1] - 2), dtype=np.float32) + blur_y = np.empty(output.shape, dtype=np.float32) + + filter = np.array([1.0, 1.0, 1.0], dtype=np.float32) / 3.0 + + for y in range(blur_x.shape[0]): + blur_x[y, :] = np.convolve(image[y, :], filter)[2:-2] + + for x in range(blur_y.shape[1]): + blur_y[:, x] = np.convolve(blur_x[:, x], filter)[2:-2] + + output[:,:] = np.clip(blur_y, 0.0, 255.0).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/blur/blur_numba_np.py b/npbench/benchmarks/image_processing/blur/blur_numba_np.py new file mode 100644 index 0000000..b785035 --- /dev/null +++ b/npbench/benchmarks/image_processing/blur/blur_numba_np.py @@ -0,0 +1,18 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=True, parallel=True, fastmath=True) +def blur(image, output): + image = image.astype(np.float32) + blur_x = np.empty((image.shape[0], image.shape[1] - 2), dtype=np.float32) + blur_y = np.empty(output.shape, dtype=np.float32) + + filter = np.array([1.0, 1.0, 1.0], dtype=np.float32) / 3.0 + + for y in range(blur_x.shape[0]): + blur_x[y, :] = np.convolve(image[y, :], filter)[2:-2] + + for x in range(blur_y.shape[1]): + blur_y[:, x] = np.convolve(blur_x[:, x], filter)[2:-2] + + output[:,:] = np.clip(blur_y, 0.0, 255.0).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/blur/blur_numba_npr.py b/npbench/benchmarks/image_processing/blur/blur_numba_npr.py new file mode 100644 index 0000000..91cb963 --- /dev/null +++ b/npbench/benchmarks/image_processing/blur/blur_numba_npr.py @@ -0,0 +1,18 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=True, parallel=True, fastmath=True) +def blur(image, output): + image = image.astype(np.float32) + blur_x = np.empty((image.shape[0], image.shape[1] - 2), dtype=np.float32) + blur_y = np.empty(output.shape, dtype=np.float32) + + filter = np.array([1.0, 1.0, 1.0], dtype=np.float32) / 3.0 + + for y in nb.prange(blur_x.shape[0]): + blur_x[y, :] = np.convolve(image[y, :], filter)[2:-2] + + for x in nb.prange(blur_y.shape[1]): + blur_y[:, x] = np.convolve(blur_x[:, x], filter)[2:-2] + + output[:,:] = np.clip(blur_y, 0.0, 255.0).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/blur/blur_numba_o.py b/npbench/benchmarks/image_processing/blur/blur_numba_o.py new file mode 100644 index 0000000..7713cbd --- /dev/null +++ b/npbench/benchmarks/image_processing/blur/blur_numba_o.py @@ -0,0 +1,18 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=False, forceobj=True, parallel=False, fastmath=True) +def blur(image, output): + image = image.astype(np.float32) + blur_x = np.empty((image.shape[0], image.shape[1] - 2), dtype=np.float32) + blur_y = np.empty(output.shape, dtype=np.float32) + + filter = np.array([1.0, 1.0, 1.0], dtype=np.float32) / 3.0 + + for y in range(blur_x.shape[0]): + blur_x[y, :] = np.convolve(image[y, :], filter, mode='valid') + + for x in range(blur_y.shape[1]): + blur_y[:, x] = np.convolve(blur_x[:, x], filter, mode='valid') + + output[:,:] = np.clip(blur_y, 0.0, 255.0).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/blur/blur_numba_op.py b/npbench/benchmarks/image_processing/blur/blur_numba_op.py new file mode 100644 index 0000000..a824e94 --- /dev/null +++ b/npbench/benchmarks/image_processing/blur/blur_numba_op.py @@ -0,0 +1,18 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=False, forceobj=True, parallel=True, fastmath=True) +def blur(image, output): + image = image.astype(np.float32) + blur_x = np.empty((image.shape[0], image.shape[1] - 2), dtype=np.float32) + blur_y = np.empty(output.shape, dtype=np.float32) + + filter = np.array([1.0, 1.0, 1.0], dtype=np.float32) / 3.0 + + for y in range(blur_x.shape[0]): + blur_x[y, :] = np.convolve(image[y, :], filter, mode='valid') + + for x in range(blur_y.shape[1]): + blur_y[:, x] = np.convolve(blur_x[:, x], filter, mode='valid') + + output[:,:] = np.clip(blur_y, 0.0, 255.0).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/blur/blur_numba_opr.py b/npbench/benchmarks/image_processing/blur/blur_numba_opr.py new file mode 100644 index 0000000..b9c8693 --- /dev/null +++ b/npbench/benchmarks/image_processing/blur/blur_numba_opr.py @@ -0,0 +1,18 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=False, forceobj=True, parallel=True, fastmath=True) +def blur(image, output): + image = image.astype(np.float32) + blur_x = np.empty((image.shape[0], image.shape[1] - 2), dtype=np.float32) + blur_y = np.empty(output.shape, dtype=np.float32) + + filter = np.array([1.0, 1.0, 1.0], dtype=np.float32) / 3.0 + + for y in nb.prange(blur_x.shape[0]): + blur_x[y, :] = np.convolve(image[y, :], filter, mode='valid') + + for x in nb.prange(blur_y.shape[1]): + blur_y[:, x] = np.convolve(blur_x[:, x], filter, mode='valid') + + output[:,:] = np.clip(blur_y, 0.0, 255.0).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/blur/blur_numpy.py b/npbench/benchmarks/image_processing/blur/blur_numpy.py new file mode 100644 index 0000000..ee06849 --- /dev/null +++ b/npbench/benchmarks/image_processing/blur/blur_numpy.py @@ -0,0 +1,21 @@ +import numpy as np + +# from PIL import Image + +def blur(image, output): + image = image.astype(np.float32) + blur_x = np.empty((image.shape[0], image.shape[1] - 2), dtype=np.float32) + blur_y = np.empty(output.shape, dtype=np.float32) + + filter = np.array([1.0, 1.0, 1.0], dtype=np.float32) / 3.0 + + for y in range(blur_x.shape[0]): + blur_x[y, :] = np.convolve(image[y, :], filter, mode='valid') + + for x in range(blur_y.shape[1]): + blur_y[:, x] = np.convolve(blur_x[:, x], filter, mode='valid') + + output[:,:] = np.clip(blur_y, 0.0, 255.0).astype(np.uint8) + + # img = Image.fromarray(output) + # img.save("blur_output.png") diff --git a/npbench/benchmarks/image_processing/hist/hist.py b/npbench/benchmarks/image_processing/hist/hist.py new file mode 100644 index 0000000..b7d3f2b --- /dev/null +++ b/npbench/benchmarks/image_processing/hist/hist.py @@ -0,0 +1,12 @@ +# Copyright 2021 ETH Zurich and the NPBench authors. All rights reserved. +import numpy as np + +from PIL import Image +from pathlib import Path + +def initialize(): + image_path = Path(__file__).parent.parent.parent.parent.parent / "data/image_processing" / "rgb.png" + image = np.array(Image.open(image_path), dtype=np.uint8) + output = np.empty((image.shape[0], image.shape[1], 3), dtype=np.uint8) + + return image, output diff --git a/npbench/benchmarks/image_processing/hist/hist_cupy.py b/npbench/benchmarks/image_processing/hist/hist_cupy.py new file mode 100644 index 0000000..b457b3a --- /dev/null +++ b/npbench/benchmarks/image_processing/hist/hist_cupy.py @@ -0,0 +1,36 @@ +import cupy as np + +def hist(image, output): + image = image.astype(np.float32) + gray = 0.299 * image[:,:,0] + 0.587 * image[:,:,1] + 0.114 * image[:,:,2] + + Cr = (image[:,:,0] - gray) * 0.713 + 128 + Cb = (image[:,:,2] - gray) * 0.564 + 128 + + binned_gray = np.clip(gray, 0, 255).astype(np.uint8) + + # [0, ..., 256] where 256 is the rightmost edge + hist, _ = np.histogram(binned_gray, bins=np.arange(257)) + + npixels = gray.shape[0] * gray.shape[1] + density = np.ndarray((256,), dtype=np.float32) + density[:] = hist / npixels + + cdf = np.cumsum(density) + + eq = cdf[binned_gray] + eq = eq * 255.0 + eq = np.clip(eq, 0, 255) + + red = eq + (Cr - 128.0) * 1.4 + red = np.clip(red, 0, 255) + + green = eq - 0.343 * (Cb - 128.0) - 0.711 * (Cr - 128.0) + green = np.clip(green, 0, 255) + + blue = eq + 1.765 * (Cb - 128.0) + blue = np.clip(blue, 0, 255) + + output[:,:,0] = red.astype(np.uint8) + output[:,:,1] = green.astype(np.uint8) + output[:,:,2] = blue.astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/hist/hist_dace.py b/npbench/benchmarks/image_processing/hist/hist_dace.py new file mode 100644 index 0000000..616f1eb --- /dev/null +++ b/npbench/benchmarks/image_processing/hist/hist_dace.py @@ -0,0 +1,58 @@ +import numpy as np +import dace + +@dace.program +def hist(image: dace.uint8[2560, 1536, 3], output: dace.uint8[2560, 1536, 3]): + imagef = image.astype(np.float32) + gray = 0.299 * imagef[:,:,0] + 0.587 * imagef[:,:,1] + 0.114 * imagef[:,:,2] + + Cr = (imagef[:,:,0] - gray) * 0.713 + 128 + Cb = (imagef[:,:,2] - gray) * 0.564 + 128 + + gray[gray < 0] = 0 + gray[gray > 255] = 255 + binned_gray = gray.astype(np.uint8) + + # histogram + hist = np.zeros((256,), dtype=np.uint32) + for y, x in dace.map[0:2560, 0:1536]: + with dace.tasklet: + p << binned_gray[y, x] + out >> hist(1, lambda x, y: x + y)[:] + + out[p] = 1 + + npixels = gray.shape[0] * gray.shape[1] + density = np.ndarray((256,), dtype=np.float32) + density[:] = hist / npixels + + # cumsum + cdf = np.ndarray((256,), dtype=np.float32) + sum: dace.float32 = 0.0 + for i in range(256): + sum = sum + density[i] + cdf[i] = sum + + eq = np.ndarray((2560, 1536), dtype=np.float32) + for y, x in dace.map[0:2560, 0:1536]: + eq[y, x] = cdf[binned_gray[y, x]] + + eq = eq * 255.0 + eq[eq < 0] = 0 + eq[eq > 255] = 255 + + red = eq + (Cr - 128.0) * 1.4 + red[red < 0.0] = 0.0 + red[red > 255.0] = 255.0 + + green = eq - 0.343 * (Cb - 128.0) - 0.711 * (Cr - 128.0) + green[green < 0.0] = 0.0 + green[green > 255.0] = 255.0 + + blue = eq + 1.765 * (Cb - 128.0) + blue[blue < 0.0] = 0.0 + blue[blue > 255.0] = 255.0 + + output[:,:,0] = red.astype(np.uint8) + output[:,:,1] = green.astype(np.uint8) + output[:,:,2] = blue.astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/hist/hist_numba_n.py b/npbench/benchmarks/image_processing/hist/hist_numba_n.py new file mode 100644 index 0000000..8a6882a --- /dev/null +++ b/npbench/benchmarks/image_processing/hist/hist_numba_n.py @@ -0,0 +1,42 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=True, parallel=False, fastmath=True) +def hist(image, output): + image = image.astype(np.float32) + gray = 0.299 * image[:,:,0] + 0.587 * image[:,:,1] + 0.114 * image[:,:,2] + + Cr = (image[:,:,0] - gray) * 0.713 + 128 + Cb = (image[:,:,2] - gray) * 0.564 + 128 + + binned_gray = np.clip(gray, 0, 255).astype(np.uint8) + + # [0, ..., 256] where 256 is the rightmost edge + hist, _ = np.histogram(binned_gray, bins=np.arange(257)) + + npixels = gray.shape[0] * gray.shape[1] + density = np.empty((256,), dtype=np.float32) + density[:] = hist / npixels + + cdf = np.cumsum(density) + + eq = np.empty_like(binned_gray) + for y in range(eq.shape[0]): + for x in range(eq.shape[1]): + eq[y, x] = cdf[binned_gray[y, x]] + + eq = eq * 255.0 + eq = np.clip(eq, 0, 255) + + red = eq + (Cr - 128.0) * 1.4 + red = np.clip(red, 0, 255) + + green = eq - 0.343 * (Cb - 128.0) - 0.711 * (Cr - 128.0) + green = np.clip(green, 0, 255) + + blue = eq + 1.765 * (Cb - 128.0) + blue = np.clip(blue, 0, 255) + + output[:,:,0] = red.astype(np.uint8) + output[:,:,1] = green.astype(np.uint8) + output[:,:,2] = blue.astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/hist/hist_numba_np.py b/npbench/benchmarks/image_processing/hist/hist_numba_np.py new file mode 100644 index 0000000..8cd9bfc --- /dev/null +++ b/npbench/benchmarks/image_processing/hist/hist_numba_np.py @@ -0,0 +1,42 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=True, parallel=True, fastmath=True) +def hist(image, output): + image = image.astype(np.float32) + gray = 0.299 * image[:,:,0] + 0.587 * image[:,:,1] + 0.114 * image[:,:,2] + + Cr = (image[:,:,0] - gray) * 0.713 + 128 + Cb = (image[:,:,2] - gray) * 0.564 + 128 + + binned_gray = np.clip(gray, 0, 255).astype(np.uint8) + + # [0, ..., 256] where 256 is the rightmost edge + hist, _ = np.histogram(binned_gray, bins=np.arange(257)) + + npixels = gray.shape[0] * gray.shape[1] + density = np.empty((256,), dtype=np.float32) + density[:] = hist / npixels + + cdf = np.cumsum(density) + + eq = np.empty_like(binned_gray) + for y in range(eq.shape[0]): + for x in range(eq.shape[1]): + eq[y, x] = cdf[binned_gray[y, x]] + + eq = eq * 255.0 + eq = np.clip(eq, 0, 255) + + red = eq + (Cr - 128.0) * 1.4 + red = np.clip(red, 0, 255) + + green = eq - 0.343 * (Cb - 128.0) - 0.711 * (Cr - 128.0) + green = np.clip(green, 0, 255) + + blue = eq + 1.765 * (Cb - 128.0) + blue = np.clip(blue, 0, 255) + + output[:,:,0] = red.astype(np.uint8) + output[:,:,1] = green.astype(np.uint8) + output[:,:,2] = blue.astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/hist/hist_numba_npr.py b/npbench/benchmarks/image_processing/hist/hist_numba_npr.py new file mode 100644 index 0000000..7c41474 --- /dev/null +++ b/npbench/benchmarks/image_processing/hist/hist_numba_npr.py @@ -0,0 +1,42 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=True, parallel=True, fastmath=True) +def hist(image, output): + image = image.astype(np.float32) + gray = 0.299 * image[:,:,0] + 0.587 * image[:,:,1] + 0.114 * image[:,:,2] + + Cr = (image[:,:,0] - gray) * 0.713 + 128 + Cb = (image[:,:,2] - gray) * 0.564 + 128 + + binned_gray = np.clip(gray, 0, 255).astype(np.uint8) + + # [0, ..., 256] where 256 is the rightmost edge + hist, _ = np.histogram(binned_gray, bins=np.arange(257)) + + npixels = gray.shape[0] * gray.shape[1] + density = np.empty((256,), dtype=np.float32) + density[:] = hist / npixels + + cdf = np.cumsum(density) + + eq = np.empty_like(binned_gray) + for y in nb.prange(eq.shape[0]): + for x in nb.prange(eq.shape[1]): + eq[y, x] = cdf[binned_gray[y, x]] + + eq = eq * 255.0 + eq = np.clip(eq, 0, 255) + + red = eq + (Cr - 128.0) * 1.4 + red = np.clip(red, 0, 255) + + green = eq - 0.343 * (Cb - 128.0) - 0.711 * (Cr - 128.0) + green = np.clip(green, 0, 255) + + blue = eq + 1.765 * (Cb - 128.0) + blue = np.clip(blue, 0, 255) + + output[:,:,0] = red.astype(np.uint8) + output[:,:,1] = green.astype(np.uint8) + output[:,:,2] = blue.astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/hist/hist_numba_o.py b/npbench/benchmarks/image_processing/hist/hist_numba_o.py new file mode 100644 index 0000000..52d3c02 --- /dev/null +++ b/npbench/benchmarks/image_processing/hist/hist_numba_o.py @@ -0,0 +1,38 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=False, forceobj=True, parallel=False, fastmath=True) +def hist(image, output): + image = image.astype(np.float32) + gray = 0.299 * image[:,:,0] + 0.587 * image[:,:,1] + 0.114 * image[:,:,2] + + Cr = (image[:,:,0] - gray) * 0.713 + 128 + Cb = (image[:,:,2] - gray) * 0.564 + 128 + + binned_gray = np.clip(gray, 0, 255).astype(np.uint8) + + # [0, ..., 256] where 256 is the rightmost edge + hist, _ = np.histogram(binned_gray, bins=np.arange(257)) + + npixels = gray.shape[0] * gray.shape[1] + density = np.ndarray((256,), dtype=np.float32) + density[:] = hist / npixels + + cdf = np.cumsum(density) + + eq = cdf[binned_gray] + eq = eq * 255.0 + eq = np.clip(eq, 0, 255) + + red = eq + (Cr - 128.0) * 1.4 + red = np.clip(red, 0, 255) + + green = eq - 0.343 * (Cb - 128.0) - 0.711 * (Cr - 128.0) + green = np.clip(green, 0, 255) + + blue = eq + 1.765 * (Cb - 128.0) + blue = np.clip(blue, 0, 255) + + output[:,:,0] = red.astype(np.uint8) + output[:,:,1] = green.astype(np.uint8) + output[:,:,2] = blue.astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/hist/hist_numba_op.py b/npbench/benchmarks/image_processing/hist/hist_numba_op.py new file mode 100644 index 0000000..d3fdb3b --- /dev/null +++ b/npbench/benchmarks/image_processing/hist/hist_numba_op.py @@ -0,0 +1,38 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=False, forceobj=True, parallel=True, fastmath=True) +def hist(image, output): + image = image.astype(np.float32) + gray = 0.299 * image[:,:,0] + 0.587 * image[:,:,1] + 0.114 * image[:,:,2] + + Cr = (image[:,:,0] - gray) * 0.713 + 128 + Cb = (image[:,:,2] - gray) * 0.564 + 128 + + binned_gray = np.clip(gray, 0, 255).astype(np.uint8) + + # [0, ..., 256] where 256 is the rightmost edge + hist, _ = np.histogram(binned_gray, bins=np.arange(257)) + + npixels = gray.shape[0] * gray.shape[1] + density = np.ndarray((256,), dtype=np.float32) + density[:] = hist / npixels + + cdf = np.cumsum(density) + + eq = cdf[binned_gray] + eq = eq * 255.0 + eq = np.clip(eq, 0, 255) + + red = eq + (Cr - 128.0) * 1.4 + red = np.clip(red, 0, 255) + + green = eq - 0.343 * (Cb - 128.0) - 0.711 * (Cr - 128.0) + green = np.clip(green, 0, 255) + + blue = eq + 1.765 * (Cb - 128.0) + blue = np.clip(blue, 0, 255) + + output[:,:,0] = red.astype(np.uint8) + output[:,:,1] = green.astype(np.uint8) + output[:,:,2] = blue.astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/hist/hist_numpy.py b/npbench/benchmarks/image_processing/hist/hist_numpy.py new file mode 100644 index 0000000..67a4de4 --- /dev/null +++ b/npbench/benchmarks/image_processing/hist/hist_numpy.py @@ -0,0 +1,41 @@ +import numpy as np + +# from PIL import Image + +def hist(image, output): + image = image.astype(np.float32) + gray = 0.299 * image[:,:,0] + 0.587 * image[:,:,1] + 0.114 * image[:,:,2] + + Cr = (image[:,:,0] - gray) * 0.713 + 128 + Cb = (image[:,:,2] - gray) * 0.564 + 128 + + binned_gray = np.clip(gray, 0, 255).astype(np.uint8) + + # [0, ..., 256] where 256 is the rightmost edge + hist, _ = np.histogram(binned_gray, bins=np.arange(257)) + + npixels = gray.shape[0] * gray.shape[1] + density = np.ndarray((256,), dtype=np.float32) + density[:] = hist / npixels + + cdf = np.cumsum(density) + + eq = cdf[binned_gray] + eq = eq * 255.0 + eq = np.clip(eq, 0, 255) + + red = eq + (Cr - 128.0) * 1.4 + red = np.clip(red, 0, 255) + + green = eq - 0.343 * (Cb - 128.0) - 0.711 * (Cr - 128.0) + green = np.clip(green, 0, 255) + + blue = eq + 1.765 * (Cb - 128.0) + blue = np.clip(blue, 0, 255) + + output[:,:,0] = red.astype(np.uint8) + output[:,:,1] = green.astype(np.uint8) + output[:,:,2] = blue.astype(np.uint8) + + # img = Image.fromarray(output) + # img.save("hist_output.png") diff --git a/npbench/benchmarks/image_processing/iir_blur/iir_blur.py b/npbench/benchmarks/image_processing/iir_blur/iir_blur.py new file mode 100644 index 0000000..5a62a61 --- /dev/null +++ b/npbench/benchmarks/image_processing/iir_blur/iir_blur.py @@ -0,0 +1,12 @@ +# Copyright 2021 ETH Zurich and the NPBench authors. All rights reserved. +import numpy as np + +from PIL import Image +from pathlib import Path + +def initialize(): + image_path = Path(__file__).parent.parent.parent.parent.parent / "data/image_processing" / "rgb.png" + image = np.array(Image.open(image_path), dtype=np.uint8) + output = np.empty_like(image) + + return image, output diff --git a/npbench/benchmarks/image_processing/iir_blur/iir_blur_cupy.py b/npbench/benchmarks/image_processing/iir_blur/iir_blur_cupy.py new file mode 100644 index 0000000..560a7fd --- /dev/null +++ b/npbench/benchmarks/image_processing/iir_blur/iir_blur_cupy.py @@ -0,0 +1,23 @@ +import cupy as np + +def blur_cols_transpose(img, alpha): + blur = np.empty(img.shape, dtype=np.float32) + blur[0, :, :] = img[0, :, :] + + for y in range(1, blur.shape[0]): + blur[y, :, :] = (1.0 - alpha) * blur[y - 1, :, :] + alpha * img[y, :, :] + + for y in range(blur.shape[0] - 2, 0): + blur[y, :, :] = (1.0 - alpha) * blur[y + 1, :, :] + alpha * blur[y, :, :] + + blur_T = np.transpose(blur, axes=(1, 0, 2)) + return blur_T + +def iir_blur(image, output): + image = image.astype(np.float32) + alpha = 0.1 + + blur_y = blur_cols_transpose(image, alpha) + blur = blur_cols_transpose(blur_y, alpha) + + output[:,:,:] = np.clip(blur, 0, 255).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/iir_blur/iir_blur_dace.py b/npbench/benchmarks/image_processing/iir_blur/iir_blur_dace.py new file mode 100644 index 0000000..57137ac --- /dev/null +++ b/npbench/benchmarks/image_processing/iir_blur/iir_blur_dace.py @@ -0,0 +1,30 @@ +import numpy as np +import dace + +def blur_cols_transpose(img, alpha: dace.float32): + res = np.empty(img.shape, dtype=np.float32) + res[0, :, :] = img[0, :, :] + + for y in range(1, res.shape[0]): + res[y, :, :] = (1.0 - alpha) * res[y - 1, :, :] + alpha * img[y, :, :] + + for y in range(res.shape[0] - 2, 0): + res[y, :, :] = (1.0 - alpha) * res[y + 1, :, :] + alpha * res[y, :, :] + + res_T = np.empty((img.shape[1], img.shape[0], 3), dtype=np.float32) + for y, x in dace.map[0:img.shape[0],0:img.shape[1]]: + res_T[x, y] = res[y, x] + + return res_T + +@dace.program +def iir_blur(image: dace.uint8[2560, 1536, 3], output: dace.uint8[2560, 1536, 3]): + imagef = image.astype(np.float32) + alpha = 0.1 + + blur_y = blur_cols_transpose(imagef, alpha) + blur = blur_cols_transpose(blur_y, alpha) + + blur[blur < 0] = 0 + blur[blur > 255] = 255 + output[:,:,:] = blur.astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_n.py b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_n.py new file mode 100644 index 0000000..507d1b0 --- /dev/null +++ b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_n.py @@ -0,0 +1,26 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=True, parallel=False, fastmath=True) +def blur_cols_transpose(img, alpha): + blur = np.empty(img.shape, dtype=np.float32) + blur[0, :, :] = img[0, :, :] + + for y in range(1, blur.shape[0]): + blur[y, :, :] = (1.0 - alpha) * blur[y - 1, :, :] + alpha * img[y, :, :] + + for y in range(blur.shape[0] - 2, 0): + blur[y, :, :] = (1.0 - alpha) * blur[y + 1, :, :] + alpha * blur[y, :, :] + + blur_T = np.transpose(blur, axes=(1, 0, 2)) + return blur_T + +@nb.jit(nopython=True, parallel=False, fastmath=True) +def iir_blur(image, output): + image = image.astype(np.float32) + alpha = 0.1 + + blur_y = blur_cols_transpose(image, alpha) + blur = blur_cols_transpose(blur_y, alpha) + + output[:,:,:] = np.clip(blur, 0, 255).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_np.py b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_np.py new file mode 100644 index 0000000..b36840e --- /dev/null +++ b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_np.py @@ -0,0 +1,26 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=True, parallel=True, fastmath=True) +def blur_cols_transpose(img, alpha): + blur = np.empty(img.shape, dtype=np.float32) + blur[0, :, :] = img[0, :, :] + + for y in range(1, blur.shape[0]): + blur[y, :, :] = (1.0 - alpha) * blur[y - 1, :, :] + alpha * img[y, :, :] + + for y in range(blur.shape[0] - 2, 0): + blur[y, :, :] = (1.0 - alpha) * blur[y + 1, :, :] + alpha * blur[y, :, :] + + blur_T = np.transpose(blur, axes=(1, 0, 2)) + return blur_T + +@nb.jit(nopython=True, parallel=True, fastmath=True) +def iir_blur(image, output): + image = image.astype(np.float32) + alpha = 0.1 + + blur_y = blur_cols_transpose(image, alpha) + blur = blur_cols_transpose(blur_y, alpha) + + output[:,:,:] = np.clip(blur, 0, 255).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_npr.py b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_npr.py new file mode 100644 index 0000000..25d44c6 --- /dev/null +++ b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_npr.py @@ -0,0 +1,26 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=True, parallel=True, fastmath=True) +def blur_cols_transpose(img, alpha): + blur = np.empty(img.shape, dtype=np.float32) + blur[0, :, :] = img[0, :, :] + + for y in nb.prange(1, blur.shape[0]): + blur[y, :, :] = (1.0 - alpha) * blur[y - 1, :, :] + alpha * img[y, :, :] + + for y in nb.prange(blur.shape[0] - 2, 0): + blur[y, :, :] = (1.0 - alpha) * blur[y + 1, :, :] + alpha * blur[y, :, :] + + blur_T = np.transpose(blur, axes=(1, 0, 2)) + return blur_T + +@nb.jit(nopython=True, parallel=True, fastmath=True) +def iir_blur(image, output): + image = image.astype(np.float32) + alpha = 0.1 + + blur_y = blur_cols_transpose(image, alpha) + blur = blur_cols_transpose(blur_y, alpha) + + output[:,:,:] = np.clip(blur, 0, 255).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_o.py b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_o.py new file mode 100644 index 0000000..ad62c11 --- /dev/null +++ b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_o.py @@ -0,0 +1,26 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=False, forceobj=True, parallel=False, fastmath=True) +def blur_cols_transpose(img, alpha): + blur = np.empty(img.shape, dtype=np.float32) + blur[0, :, :] = img[0, :, :] + + for y in range(1, blur.shape[0]): + blur[y, :, :] = (1.0 - alpha) * blur[y - 1, :, :] + alpha * img[y, :, :] + + for y in range(blur.shape[0] - 2, 0): + blur[y, :, :] = (1.0 - alpha) * blur[y + 1, :, :] + alpha * blur[y, :, :] + + blur_T = np.transpose(blur, axes=(1, 0, 2)) + return blur_T + +@nb.jit(nopython=False, forceobj=True, parallel=False, fastmath=True) +def iir_blur(image, output): + image = image.astype(np.float32) + alpha = 0.1 + + blur_y = blur_cols_transpose(image, alpha) + blur = blur_cols_transpose(blur_y, alpha) + + output[:,:,:] = np.clip(blur, 0, 255).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_op.py b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_op.py new file mode 100644 index 0000000..431835a --- /dev/null +++ b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_op.py @@ -0,0 +1,26 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=False, forceobj=True, parallel=True, fastmath=True) +def blur_cols_transpose(img, alpha): + blur = np.empty(img.shape, dtype=np.float32) + blur[0, :, :] = img[0, :, :] + + for y in range(1, blur.shape[0]): + blur[y, :, :] = (1.0 - alpha) * blur[y - 1, :, :] + alpha * img[y, :, :] + + for y in range(blur.shape[0] - 2, 0): + blur[y, :, :] = (1.0 - alpha) * blur[y + 1, :, :] + alpha * blur[y, :, :] + + blur_T = np.transpose(blur, axes=(1, 0, 2)) + return blur_T + +@nb.jit(nopython=False, forceobj=True, parallel=True, fastmath=True) +def iir_blur(image, output): + image = image.astype(np.float32) + alpha = 0.1 + + blur_y = blur_cols_transpose(image, alpha) + blur = blur_cols_transpose(blur_y, alpha) + + output[:,:,:] = np.clip(blur, 0, 255).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_opr.py b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_opr.py new file mode 100644 index 0000000..e97bdfe --- /dev/null +++ b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numba_opr.py @@ -0,0 +1,26 @@ +import numpy as np +import numba as nb + +@nb.jit(nopython=False, forceobj=True, parallel=True, fastmath=True) +def blur_cols_transpose(img, alpha): + blur = np.empty(img.shape, dtype=np.float32) + blur[0, :, :] = img[0, :, :] + + for y in nb.prange(1, blur.shape[0]): + blur[y, :, :] = (1.0 - alpha) * blur[y - 1, :, :] + alpha * img[y, :, :] + + for y in nb.prange(blur.shape[0] - 2, 0): + blur[y, :, :] = (1.0 - alpha) * blur[y + 1, :, :] + alpha * blur[y, :, :] + + blur_T = np.transpose(blur, axes=(1, 0, 2)) + return blur_T + +@nb.jit(nopython=False, forceobj=True, parallel=True, fastmath=True) +def iir_blur(image, output): + image = image.astype(np.float32) + alpha = 0.1 + + blur_y = blur_cols_transpose(image, alpha) + blur = blur_cols_transpose(blur_y, alpha) + + output[:,:,:] = np.clip(blur, 0, 255).astype(np.uint8) diff --git a/npbench/benchmarks/image_processing/iir_blur/iir_blur_numpy.py b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numpy.py new file mode 100644 index 0000000..636e61b --- /dev/null +++ b/npbench/benchmarks/image_processing/iir_blur/iir_blur_numpy.py @@ -0,0 +1,28 @@ +import numpy as np + +# from PIL import Image + +def blur_cols_transpose(img, alpha): + blur = np.empty(img.shape, dtype=np.float32) + blur[0, :, :] = img[0, :, :] + + for y in range(1, blur.shape[0]): + blur[y, :, :] = (1.0 - alpha) * blur[y - 1, :, :] + alpha * img[y, :, :] + + for y in range(blur.shape[0] - 2, 0): + blur[y, :, :] = (1.0 - alpha) * blur[y + 1, :, :] + alpha * blur[y, :, :] + + blur_T = np.transpose(blur, axes=(1, 0, 2)) + return blur_T + +def iir_blur(image, output): + image = image.astype(np.float32) + alpha = 0.1 + + blur_y = blur_cols_transpose(image, alpha) + blur = blur_cols_transpose(blur_y, alpha) + + output[:,:,:] = np.clip(blur, 0, 255).astype(np.uint8) + + # img = Image.fromarray(output) + # img.save("iir_blur_output.png") diff --git a/requirements.txt b/requirements.txt index 5c2e18f..31c2d5a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ numpy pandas pygount scipy +Pillow diff --git a/scripts/image_difference.py b/scripts/image_difference.py new file mode 100644 index 0000000..26f72fa --- /dev/null +++ b/scripts/image_difference.py @@ -0,0 +1,26 @@ +import argparse +import numpy as np +from PIL import Image + +parser = argparse.ArgumentParser(description='Provide two images.') +parser.add_argument('imageA', help='') +parser.add_argument('imageB', help='') + +args = parser.parse_args() + +image_a = np.array(Image.open(args.imageA)).astype(np.float32) +image_b = np.array(Image.open(args.imageB)).astype(np.float32) + +assert image_a.shape == image_b.shape + +diff_image = np.abs(image_b - image_a) +print(diff_image) +diff = diff_image[diff_image > 0] + +if diff.shape[0] > 0: + print("Max abs deviation: ", diff.max()) + +img = Image.fromarray(diff_image.astype(np.uint8)) +img.save("difference.png") + +assert (diff <= 5).all()