R/sharpen.R

Defines functions sharpen convolve2d

Documented in sharpen

#' Author: Frank Lu
#' Function name: sharpen
#'
#' Detects and enhances the edges in the image and
#' returns a sharpened and monotoned version (the same size as the original).
#'
#' @param img array input image
#'
#' @return array sharpened monotone image
#' @export
#'
#' @examples
#' old_img <- array(rep(c(0.5), 100 * 100 * 3), dim = c(100, 100, 3))
#' new_img <- sharpen(old_img)
sharpen <- function(img) {

  if (!is.array(img)){
    stop("TypeError: input image should be array")
  }
  if (dim(img)[1] < 50 | dim(img)[2] < 50){
    stop("ValueError: height and width of the input image should be greater than 50 x 50")
  }
  if (min(img) < 0 | max(img) > 1){
    stop("ValueError: the brightness of pixels should be between 0 and 1")
  }

  n <- 3
  N <- 2 * n + 1
  C <- n + 1
  filter <- array(rep(c(-1/(16 * n**2)), N * N), dim = c(N, N))
  filter[C, C] <- 1
  img2 <- img[, , 1]

  convolve2d(img2, filter)
}

# Implement a 2D convolution here.
# The 2D square matrix filter will be applied on the input
# image, which is also a 2D matrix
# The algorithm is disign to account for borders and is equivalent
# to padding = True
convolve2d <- function(input, filter) {
  nrow <- dim(input)[1]
  ncol <- dim(input)[2]
  res <- array(1:(nrow*ncol), dim = c(nrow, ncol))

  filter_l <- dim(filter)[1]
  filter_half <- filter_l %/% 2
  filter_center <- filter_half + 1

  for(r in 1:nrow) {
    for(c in 1:ncol) {
      if(r - filter_half < 1) {
        ifil_start <-1 + filter_half - r + 1
        i_start <- 1
      } else {
        ifil_start <- 1
        i_start <- r - filter_half
      }

      if(r + filter_half > nrow) {
        ifil_end <- filter_l - (r + filter_half - nrow)
        i_end <- nrow
      } else {
        ifil_end <- filter_l
        i_end <- r + filter_half
      }

      if(c - filter_half < 1) {
        jfil_start <- 1 + filter_half - c + 1
        j_start <- 1
      } else {
        jfil_start <- 1
        j_start <- c - filter_half
      }

      if(c + filter_half > ncol) {
        jfil_end <- filter_l - (c + filter_half - ncol)
        j_end <- ncol
      } else {
        jfil_end <- filter_l
        j_end <- c + filter_half
      }
      filt <- filter[ifil_start:ifil_end, jfil_start:jfil_end]
      inp <- input[i_start:i_end, j_start:j_end]
      val <- sum(filt * inp)
      res[r, c] <- val
    }
  }

  (res - min(res)) / (max(res) - min(res))
}
UBC-MDS/Rgroup12 documentation built on April 1, 2020, 4:36 a.m.