Nothing
#' @title Data matrix to be used as example image.
#' @description \code{matrix} object containing numeric data to plot a image.
#' The photo was taken by the author on 2016.
#' @docType data
#' @usage wbImage
#' @format A \code{matrix} with dimensions 1280x720.
"wbImage"
#' @title Make convolution calculations from numeric matrix
#'
#' @rdname convolutions
#'
#' @param X A numeric \code{matrix} object used for apply filters.
#' @param kernel A little matrix used as mask for each cell of \code{X}.
#' @param probs \code{numeric} vector of probabilities with values in [0,1].
#' @param times How many times do you want to apply the filter?
#' @param normalize \code{logical} indicating if results will (or not) be
#' normalized. See details.
#' @param na_only \code{logical}, Do you want to apply the filter ONLY in cells
#' with NA?
#'
#' @description This function takes a \code{matrix} object, and for each cell
#' multiplies its neighborhood by the \code{kernel}. Finally, it returns for
#' each cell the mean of the kernel-weighted sum.
#'
#' @return \code{convolution2D} returns a \code{matrix} object with the same
#' dimensions of \code{X}.
#'
#' @details
#' Convolution is a mathematical operation that combines two arrays of numbers
#' to produce an array of the same structure. The output will consist of only
#' valid values, meaning those where both arrays have non-missing data.
#' Consequently, any missing values (NAs) in the input matrix will propagate
#' outwards to the extent of the convolution kernel.
#'
#' Through normalization, the output of each convolution window is scaled by
#' dividing it by the sum of the absolute values of the kernel
#' (\code{sum(abs(as.numeric(kernel)))}, disabled by default).
#'
#' \code{na_only} performs two actions at once: (1) it applies the filter only in
#' the positions where the original value is \code{NA} and (2) for the rest of
#' the cells, it is replaced with the value of the original matrix.
#'
#'
#' @export
#'
#' @examples
#' # Generate example matrix
#' nRows <- 50
#' nCols <- 100
#'
#' myMatrix <- matrix(runif(nRows*nCols, 0, 100), nrow = nRows, ncol = nCols)
#' kernel <- diag(3)
#'
#' # Make convolution
#' myOutput1 <- convolution2D(myMatrix, kernel)
#' myOutput2 <- convolutionQuantile(myMatrix, kernel, probs = 0.7)
#'
#' # Plot results
#' par(mfrow = c(2, 2))
#' image(myMatrix, zlim = c(0, 100))
#' image(myOutput1, zlim = c(0, 100))
#' image(myOutput2, zlim = c(0, 100))
convolution2D <- function(X, kernel, times = 1, normalize = FALSE, na_only = FALSE){
armadillo_version(FALSE)
# Check and validation of arguments
checkedArgs <- list(X = X, kernel = kernel, times = times)
checkedArgs <- checkArgs(imagineArgs = checkedArgs, type = "convolution2D")
# Apply filters
output <- checkedArgs$X
for(i in seq(checkedArgs$times)){
gc(reset = TRUE)
output <- with(checkedArgs,
engine1_2dConv(data = output,
kernel = kernel,
na_only = isTRUE(na_only)))
if(normalize){
output <- output/sum(abs(as.numeric(kernel)), na.rm = TRUE)
}
}
output
}
#' @rdname convolutions
#' @return \code{convolutionQuantile} uses the kernel but, for each cell, it
#' returns the position of quantile 'probs' (value between 0 and 1).
#' @export
convolutionQuantile <- function(X, kernel, probs, times = 1, normalize = FALSE, na_only = FALSE){
# Check and validation of arguments
checkedArgs <- list(X = X, kernel = kernel, probs = probs, times = times)
checkedArgs <- checkArgs(imagineArgs = checkedArgs, type = "convolutionQuantile")
# Apply filters
output <- checkedArgs$X
for(i in seq(checkedArgs$times)){
gc(reset = TRUE)
output <- with(checkedArgs,
engine2_convWithQuantiles(data = output,
kernel = kernel,
probs = probs,
na_only = isTRUE(na_only)))
if(normalize){
output <- output/sum(abs(as.numeric(kernel)), na.rm = TRUE)
}
}
output
}
#' @rdname convolutions
#' @return \code{convolutionMedian} is a wrapper of \code{convolutionQuantile}
#' with probs = 0.5.
#' @export
convolutionMedian <- function(X, kernel, times = 1, na_only = FALSE){
convolutionQuantile(X = X,
kernel = kernel,
probs = 0.5,
times = times,
na_only = isTRUE(na_only))
}
#' @title Make a 2D filter calculations from numeric matrix
#'
#' @rdname basic2DFilter
#'
#' @param X A numeric \code{matrix} object used for apply filters.
#' @param radius Size of squared or rectangular kernel to apply median. See
#' Details.
#' @param probs \code{numeric} vector of probabilities with values in [0,1].
#' @param times How many times do you want to apply the filter?
#' @param na_only \code{logical}, Do you want to apply the filter ONLY in cells
#' with NA?
#'
#' @description This functions take a \code{matrix} object, and for each cell
#' calculate mean, median or certain quantile around a squared/rectangular
#' neighborhood.
#'
#' @return A \code{matrix} object with the same dimensions of \code{X}.
#'
#' @details \code{radius} must be defined as a 2-length numeric vector
#' specifying the number of rows and columns of the window which will be used to
#' make calculations. If the length of radius is 1, the window will be a square.
#'
#' Functions use C++ algorithms for running some statistical calculations. The
#' mean is far obvious, however, there are several ways to perform quantiles.
#' \code{quantileFilter} function uses
#' \href{https://arma.sourceforge.net/docs.html#quantile}{arma::quantile}: a
#' RcppArmadillo function, which is equivalent to use R \link[stats]{quantile}
#' funtion with \code{type = 5}.
#'
#' \code{medianFilter} is a wraper of \code{quantileFilter}, so the same
#' observations are applied to it.
#'
#' \code{na_only} performs two actions at once: (1) it applies the filter only in
#' the positions where the original value is \code{NA} and (2) for the rest of
#' the cells, it is replaced with the value of the original matrix.
#'
#' @export
#'
#' @examples
#' # Generate example matrix
#' nRows <- 50
#' nCols <- 100
#'
#' myMatrix <- matrix(runif(nRows*nCols, 0, 100), nrow = nRows, ncol = nCols)
#' radius <- 3
#'
#' # Make convolution
#' myOutput1 <- meanFilter(X = myMatrix, radius = radius)
#' myOutput2 <- quantileFilter(X = myMatrix, radius = radius, probs = 0.1)
#' myOutput3 <- medianFilter(X = myMatrix, radius = radius)
#'
#' # Plot results
#' par(mfrow = c(2, 2))
#' image(myMatrix, zlim = c(0, 100), title = "Original")
#' image(myOutput1, zlim = c(0, 100), title = "meanFilter")
#' image(myOutput2, zlim = c(0, 100), title = "quantileFilter")
#' image(myOutput3, zlim = c(0, 100), title = "medianFilter")
meanFilter <- function(X, radius, times = 1, na_only = FALSE){
# Check and validation of arguments
checkedArgs <- list(X = X,
radius = rep(x = radius, length.out = 2),
times = times)
checkedArgs <- checkArgs(imagineArgs = checkedArgs, type = "meanFilter")
# Apply filters
output <- checkedArgs$X
for(i in seq(checkedArgs$times)){
gc(reset = TRUE)
output <- with(checkedArgs,
engine3_meanFilter(data = output,
radius = radius,
na_only = isTRUE(na_only)))
}
output
}
#' @rdname basic2DFilter
#' @return \code{quantileFilter} don't use a kernel but, for each cell, it
#' returns the position of quantile 'probs' (value between 0 and 1).
#' @export
quantileFilter <- function(X, radius, probs, times = 1, na_only = FALSE){
# Check and validation of arguments
checkedArgs <- list(X = X,
radius = rep(x = radius, length.out = 2),
probs = probs,
times = times,
na = NA)
checkedArgs <- checkArgs(imagineArgs = checkedArgs, type = "quantileFilter")
# Apply filters
output <- checkedArgs$X
for(i in seq(checkedArgs$times)){
gc(reset = TRUE)
output <- with(checkedArgs,
engine4_quantileFilter(data = output,
radius = radius,
probs = probs,
na_only = isTRUE(na_only)))
}
output
}
#' @rdname basic2DFilter
#' @return \code{medianFilter} is a wrapper of \code{quantileFilter} with
#' \code{probs = 0.5}.
#' @export
medianFilter <- function(X, radius, times = 1, na_only = FALSE){
quantileFilter(X = X,
radius = radius,
probs = 0.5,
times = times,
na_only = na_only)
}
#' @title Performs Contextual Median Filter
#'
#' @param X A numeric \code{matrix} object used for apply filters.
#'
#' @description This function implements the Contextual Median Filter (CMF)
#' algorithm, which was first described by Belkin & O'Reilly (2009), following
#' the pseudocode provided in their paper.
#'
#' @details
#' Following the definition of CMF, since \strong{imagine} v.2.0.0, \code{times}
#' argument will not be available anymore.
#'
#' \strong{imagine} offers the CMF algorithm but for the using to find out
#' oceanographic fronts, it is recommended to see and use the functions of the
#' \href{https://CRAN.R-project.org/package=grec}{\strong{grec}} package.
#'
#' @references Belkin, I. M., & O'Reilly, J. E. (2009). An algorithm for oceanic
#' front detection in chlorophyll and SST satellite imagery. Journal of Marine
#' Systems, 78(3), 319-326 (\doi{http://dx.doi.org/10.1016/j.jmarsys.2008.11.018}).
#'
#' @export
#'
#' @return \code{contextualMF} returns a \code{matrix} object with the same
#' dimensions of \code{X}.
#'
#' @examples
#' data(wbImage)
#'
#' cmfOut <- contextualMF(X = wbImage)
#'
#' # image(cmfOut)
contextualMF <- function(X){
# Check and validation of arguments
checkedArgs <- list(X = X)
checkedArgs <- checkArgs(imagineArgs = checkedArgs, type = "contextualMF")
# Apply filters
with(checkedArgs, engine5_CMF(data = X))
}
#' @title Performs algorithms from Agenbag et al. (2003)
#'
#' @param X A numeric \code{matrix} used as main input.
#' @param algorithm \code{integer} specifying the type of method that will be
#' used. See Details.
#' @param ... Not used.
#'
#' @description This function performs two (gradient) calculation approaches for
#' SST, as outlined in the paper by Agenbag et al. (2003).
#'
#' @details
#' Section 2.2.4 of the paper by Agenbag et al. (2003) introduces the following
#' two methods:
#' \describe{
#' \item{\strong{Method 1: }}{Based on the equation
#' \deqn{Y_{i,j}=\sqrt{(X_{i+1,j}-X_{i-1,j})^2 +(X_{i,j+1}-X_{i,j-1})^2}}}
#' where \eqn{Y_{i,j}} represents the output value for each \eqn{X_{i,j}} pixel value
#' of a given \eqn{X} matrix.
#' \item{\strong{Method 2: }}{the standard deviation in a 3x3 pixel area centered on
#' position \eqn{(i,j)}.}
#' }
#'
#' As outlined in the original study, this method conducts searches within a
#' 1-pixel vicinity of each point. For method 1, it only returns a value for
#' points where none of the four involved values are NA. Conversely, for method
#' 2, the standard deviation calculation is performed only for points where at
#' least 3 non-NA values are found in the 3x3 neighborhood.
#'
#'
#' @references Agenbag, J.J., A.J. Richardson, H. Demarcq, P. Freon, S. Weeks,
#' and F.A. Shillington. "Estimating Environmental Preferences of South African
#' Pelagic Fish Species Using Catch Size- and Remote Sensing Data". Progress in
#' Oceanography 59, No 2-3 (October 2003): 275-300.
#' (\doi{https://doi.org/10.1016/j.pocean.2003.07.004}).
#'
#' @return \code{agenbagFilters} returns a \code{matrix} object with the same
#' dimensions of \code{X}.
#'
#' @export
#'
#' @examples
#' data(wbImage)
#'
#' # Agenbag, method 1
#' agenbag1 <- agenbagFilters(X = wbImage, algorithm = 1)
#'
#' # Agenbag, method 2
#' agenbag2 <- agenbagFilters(X = wbImage, algorithm = 2)
#'
#' # Plotting results
#' par(mfrow = c(3, 1), mar = rep(0, 4))
#'
#' # Original
#' image(wbImage, axes = FALSE, col = gray.colors(n = 1e3))
#'
#' # Calculated
#' cols <- hcl.colors(n = 1e3, palette = "YlOrRd", rev = TRUE)
#' image(agenbag1, axes = FALSE, col = cols)
#' image(agenbag2, axes = FALSE, col = cols)
agenbagFilters <- function(X, algorithm = c(1, 2), ...){
# Check and validation of arguments
checkedArgs <- list(X = X,
algorithm = algorithm)
checkedArgs <- checkArgs(imagineArgs = checkedArgs, type = "agenbagFilters")
switch(checkedArgs$algorithm,
"1" = engine6_agenbag1(data = checkedArgs$X),
"2" = engine7_agenbag2(data = checkedArgs$X, ...))
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.