knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
library(imagine)

imagine

IMAGing engINE, Tools for Application of Image Filters to Data Matrices

The imagine package streamlines the process of applying image-filtering algorithms to numeric data matrices. It employs efficient median-filter and 2D-convolution algorithms implemented in Rcpp (C++), enabling rapid processing of large datasets.

Installation

For installing imagine, as follows:

install.packages("imagine")

Engines

The imagine package employs C++-based algorithms, designated as 'engines,' crafted with Rcpp and RcppArmadillo, to expedite the application of image filters. These engines significantly enhance the performance of filtering operations, ensuring efficient processing of large datasets. As of version 2.1.0, imagine incorporates the following engines:

Since version 2.0.0, radius could accept 2 values to define the number of rows and columns respectively of the window.

Main functions

There are 5 main functions and 2 wrappers:

Convolution functions

# Build kernels
# Kernel 1: For bottom edge recognition
kernel1 <- matrix(c(-1, -2, -1,
                     0,  0,  0,
                     1,  2,  1), 
                  nrow = 3)

# Kernel 2: Diagonal weighting
kernel2 <- matrix(c(-2, 0, 0,
                     0, 1, 0,
                     0, 0, 2), 
                  nrow = 3)

# Apply filters
convolutionExample  <- convolution2D(X = wbImage, kernel = kernel1)
convQuantileExample <- convolutionQuantile(X = wbImage, kernel = kernel2, probs = 0.1)

In order to compare results, we will plot both data (original and filtered) using image function, as shows in figures 1 and 2.

Original vs filtered outputs

# Defining a copy of wbImage
myMatrix <- wbImage

# Defining color palette
cols <- gray.colors(n = 1e3, start = 1, end = 0)

# Build kernels
# Kernel 1: For bottom edge recognition
kernel1 <- matrix(c(-1, -2, -1,
                     0,  0,  0,
                     1,  2,  1), 
                  nrow = 3)

# Kernel 2: Diagonal weighting
kernel2 <- matrix(c(-2, 0, 0,
                     0, 1, 0,
                     0, 0, 2), 
                  nrow = 3)

# Apply filters
convolutionExample  <- convolution2D(X = myMatrix, kernel = kernel1)
convQuantileExample <- convolutionQuantile(X = myMatrix, kernel = kernel2, probs = 0.8)

# Make plots
par(mar = c(0, 0.5, 0, 0.5), oma = c(0, 0, 2, 0), mfrow = c(2, 1))

image(convolutionExample, col = cols, axes = FALSE)
mtext(text = "2D convolution", side = 1, line = -1.5, col = "white", font = 2, adj = 0.99)

image(convQuantileExample, col = cols, axes = FALSE)
mtext(text = "2D quantile convolution", side = 1, line = -1.5, col = "black", font = 2, adj = 0.99)

Median-filter asociated functions

# Add some noise (NA) to the image (matrix)
set.seed(7)
naIndex <- sample(x       = seq(prod(dim(myMatrix))), 
                  size    = as.integer(0.4*prod(dim(myMatrix))), 
                  replace = FALSE)
myMatrix[naIndex] <- NA

# Build kernel
radius <- 3

# Apply filters
meanfilterExample     <- meanFilter(X = myMatrix, radius = radius)
quantilefilterExample <- quantileFilter(X = myMatrix, radius = radius, probs = 0.1)
medianfilterExample   <- medianFilter(X = myMatrix, radius = radius)

Now, we will plot both data (original and filtered) using image function, as shows in figures 1 and 2.

Original and Filtered

# Defining a copy of wbImage
myMatrix <- wbImage

# Defining color palette
cols <- gray.colors(n = 1e3, start = 0, end = 1)

# Add some noise (NA) to the image (matrix)
set.seed(7)
naIndex <- sample(x = seq(prod(dim(myMatrix))), size = as.integer(0.4*prod(dim(myMatrix))))
myMatrix[naIndex] <- NA

# Apply filters
meanfilterExample   <- meanFilter(X = myMatrix, radius = 3)
medianfilterExample <- medianFilter(X = myMatrix, radius = 3)

# Make plots
par(mar = rep(0, 4), oma = rep(0.5, 4), mfrow = c(2, 2))

image(wbImage, col = cols, axes = FALSE)
mtext(text = "Original", side = 3, line = -1.5, font = 2, adj = 0.99)

image(myMatrix, col = cols, axes = FALSE)
mtext(text = "Original with noise (NA)", side = 3, line = -1.5, font = 2, adj = 0.99)

# meanfilterExample[meanfilterExample < 0] <- 0
image(meanfilterExample, col = cols, axes = FALSE)
mtext(text = "Mean filter", side = 3, line = -1.5, font = 2, adj = 0.99)

# medianfilterExample[medianfilterExample < 0] <- 0
image(medianfilterExample, col = cols, axes = FALSE)
mtext(text = "2D median filter", side = 3, line = -1.5, font = 2, adj = 0.99)

Kernel application

In the field of image processing, one of the tools most commonly used are the convolutions, which consist of operations between two arrays: The array of image data (as a big matrix) and kernels (as small matrices) which weighs each pixel values by the values of its corresponding neighborhood. Different kernels produce different effects, for instance: blur, shifted images (right, left, up or down), sharpening, etc. The users must be cautious with the size of the kernel because the larger the radius, the more pixels remain unanalyzed at the edges.

Besides, every function of imagine allows the recursive running of a filter by the using of times argument.

medianFilter(X = wbImage, radius = 5, times = 50)
times <- c(1, 5, 15)

# Defining color palette
cols <- gray.colors(n = 1e3, start = 0, end = 1)

# Apply filters
median_times1 <- medianFilter(X = wbImage, radius = 5, times = times[1])
median_times2 <- medianFilter(X = wbImage, radius = 5, times = times[2])
median_times3 <- medianFilter(X = wbImage, radius = 5, times = times[3])

# Make plots
par(mar = rep(0, 4), oma = rep(0.5, 4), mfrow = c(2, 2))

image(wbImage, col = cols, axes = FALSE)
mtext(text = "Original", side = 3, line = -1.5, font = 2, adj = 0.99)

image(median_times1, col = cols, axes = FALSE)
mtext(text = paste("2D median filter\ntimes =", times[1]), 
      side = 3, line = -2.5, font = 2, adj = 0.99)

image(median_times2, col = cols, axes = FALSE)
mtext(text = paste("2D median filter\ntimes =", times[2]), 
      side = 3, line = -2.5, font = 2, adj = 0.99)

image(median_times3, col = cols, axes = FALSE)
mtext(text = paste("2D median filter\ntimes =", times[3]), 
      side = 3, line = -2.5, font = 2, adj = 0.99)

Filters based on published articles

Since its version 2.1.0, imagine includes two functions that implement the algorithms of two papers related to the calculation of oceanographic gradients:

Although both functions are available and can be executed directly from imagine, it is recommended to use them through the grec package.



LuisLauM/imagine documentation built on Jan. 31, 2024, 3:14 p.m.