---
title: "imagine"
author: "Wencheng Lau-Medrano"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{imagine}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, echo = FALSE, message = FALSE}
library(imagine)
```

# imagine

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

This package was built up to take numeric data matrices and apply image-filtering algoriths.

Algoriths used by `imagine` include median-filter and 2D-convolution based algoriths performed on Rcpp (C++) in order to speed up the application of this filters to large numeric matrices.


## Installation

For installing `imagine`, as follows:

```{r, eval=FALSE}
install.packages("imagine")
```

## Engines
`imagine` performs algorithms written in Rcpp (called 'engines'), ensuring a faster application of filters. At version 1.5.0, `imagine` includes four main engines, described as follows:

* Engine 1: Basic 2D-convolution algorithm. It multiplies kernel by the neighborhood of each cell and then it sums all values.
* Engine 2: Make the same of Engine 1 but, at the end, it returns the position indicated by the parameter `probs`.
* Engine 3: It uses the `radius` argument to extract the values of squared neighborhood ($radius \times radius$) and calculates the mean.
* Engine 4: It uses the `radius` argument to extract the values of squared neighborhood ($radius \times radius$) and returns the position indicated by the parameter `probs`
* Engine 5: It performs a generalization of the Contextual Median Filter propose by Belkin & O'Reilly (2009). The default parameters reproduce the algorithm of the paper, but the function allows certain customization.

## Main functions

There are 5 main functions and 2 wrappers:

### Convolution functions
```{r, eval=FALSE}
# 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**

```{r, message=FALSE, fig.height=3, fig.width=5.33, fig.cap = "Figure 2: Original matrix", results='hide', fig.pos="h", echo=FALSE}
par(mar = rep(0, 4), mfrow = c(1, 1))
cols <- colorRampPalette(colors = c("black", "white"))(1e4)

image(wbImage, col = cols)
```


**Filtered**

```{r, message=FALSE, fig.height=6, fig.width=5.33, fig.cap = "Figure 1: Filtered matrices", results='hide', fig.pos="h", echo=FALSE}

myMatrix <- wbImage

# 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.1)

# 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
```{r, eval=FALSE}
# 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, times = 10)

```

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

**Original**

```{r, message=FALSE, fig.height=3, fig.width=5.33, fig.cap = "Figure 2: Original matrix", results='hide', fig.pos="h", echo=FALSE}
set.seed(7)
naIndex <- sample(x = seq(prod(dim(myMatrix))), size = as.integer(0.4*prod(dim(myMatrix))), replace = FALSE)
myMatrix[naIndex] <- NA

par(mar = rep(0, 4), mfrow = c(1, 1))
image(myMatrix, col = cols)
```


**Filtered**

```{r, message=FALSE, fig.height=9, fig.width=5.33, fig.cap = "Figure 1: Filtered matrices", results='hide', fig.pos="h", echo=FALSE}
# Build kernel
radius <- 3

# 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, times = 10)

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

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

# quantilefilterExample[quantilefilterExample < 0] <- 0
image(quantilefilterExample, col = cols, axes = FALSE)
mtext(text = "Quantile filter (probs = 0.1)", side = 1, line = -1.5, col = "white", font = 2, adj = 0.99)

# medianfilterExample[medianfilterExample < 0] <- 0
image(medianfilterExample, col = cols, axes = FALSE)
mtext(text = "2D median filter", side = 1, line = -1.5, col = "white", 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.
