Motion Blur Filters

Motion Blur Custom Kernel Filter in Python

         You can create a custom kernel by placing elements in a specific way, like along a horizontal line. In this setup, the central pixel value is figured out by looking at the average of these pixels, creating the 'Motion Blur' effect. When certain elements have higher importance, they impact the final pixel value more in the Motion Blur effect. Making sure the total of all these elements adds up to 1 helps keep the original brightness of the picture. The freedom to arrange elements in different directions lets you make various motion effects in the image.

# custom MotionBlur horizontal 7x7 kernel
[
  [ 0,    0,    0,    0,    0,   0,    0    ],
  [ 0,    0,    0,    0,    0,   0,    0    ],
  [ 0,    0,    0,    0,    0,   0,    0    ],
  [ 0.15, 0.15, 0.15, 0.1,  0.15, 0.15, 0.15],
  [ 0,    0,    0,    0,    0,   0,    0    ],
  [ 0,    0,    0,    0,    0,   0,    0    ],
  [ 0,    0,    0,    0,    0,   0,    0    ],
]

         This effect imitates the case of a camera moving horizontally while capturing a photo, generating the illusion of motion in the image.

Original image
MotionBlur filter
Original vector image
Custom Motion blur 7x7 horizontal kernel filter in Python
Custom MotionBlur kernel filter

Python code example

         The provided Python code example demonstrates how to utilize the Aspose.Imaging Python API. You can use the `ConvolutionFilter` class, which provides pre-defined kernel filters like get_blur_motion() with customizable size and angle parameters. Moreover, you retain the freedom to design your custom kernel matrix. In this instance, image templates in raster PNG and as well as vector SVG formats are loaded from the "templates" directory, and a set of filters is applied from the `kernel_filters` list.

import os, random
import aspose.pycore as aspycore
from aspose.imaging import Image, RasterImage, VectorImage
from aspose.imaging.imagefilters.complexutils import Complex
from aspose.imaging.imagefilters.convolution import *
from aspose.imaging.imagefilters.filteroptions import *
if 'TEMPLATE_DIR' in os.environ:
templates_folder = os.environ['TEMPLATE_DIR']
else:
templates_folder = r"C:\Users\USER\Downloads\templates"
delete_output = 'SAVE_OUTPUT' not in os.environ
def delete_file(file):
if delete_output:
os.remove(file)
# Example code:
def filter(raster, options, output_path):
raster.filter(raster.bounds, options)
raster.save(output_path)
def get_random_kernel(cols, rows):
custom_kernel = [0.0] * (cols * rows)
for y in range(rows):
for x in range(cols):
custom_kernel[y*cols + x] = random.random()
return custom_kernel
size: int = 5
sigma: float = 1.5
angle: float = 45
custom_kernel = get_random_kernel(size, 7)
custom_complex = ConvolutionFilter.to_complex(custom_kernel)
kernel_filters = [
# convolution filters
ConvolutionFilterOptions(ConvolutionFilter.get_emboss_3x3()),
ConvolutionFilterOptions(ConvolutionFilter.get_emboss_5x5()),
ConvolutionFilterOptions(ConvolutionFilter.get_sharpen_3x3()),
ConvolutionFilterOptions(ConvolutionFilter.get_sharpen_5x5()),
ConvolutionFilterOptions(ConvolutionFilter.get_blur_box(size)),
ConvolutionFilterOptions(ConvolutionFilter.get_blur_motion(size, angle)),
ConvolutionFilterOptions(ConvolutionFilter.get_gaussian(size, sigma)),
ConvolutionFilterOptions(custom_kernel),
GaussianBlurFilterOptions(size, sigma),
SharpenFilterOptions(size, sigma),
MedianFilterOptions(size),
# deconvolution filters
DeconvolutionFilterOptions(ConvolutionFilter.get_gaussian(size, sigma)),
DeconvolutionFilterOptions(custom_kernel),
DeconvolutionFilterOptions(custom_complex),
GaussWienerFilterOptions(size, sigma),
MotionWienerFilterOptions(size, sigma, angle)
]
data_dir = templates_folder
input_paths = [
os.path.join(data_dir, "template.png"),
os.path.join(data_dir, "template.svg")
]
outputs = []
for input_path in input_paths:
for i, options in enumerate(kernel_filters):
with Image.load(input_path) as image:
output_path = f"{input_path}-{i}.png"
if aspycore.is_assignable(image, RasterImage):
raster = aspycore.as_of(image, RasterImage)
filter(raster, options, output_path)
outputs.append(output_path)
elif aspycore.is_assignable(image, VectorImage):
vector = aspycore.as_of(image, VectorImage)
vector_as_png = input_path + ".png"
if not os.path.exists(vector_as_png):
vector.save(vector_as_png)
outputs.append(vector_as_png)
with Image.load(vector_as_png) as png:
filter(aspycore.as_of(png, RasterImage), options, output_path)
outputs.append(output_path)
# Removing all output files
for p in outputs:
delete_file(p)