SOCR ≫ TCIU Website ≫ TCIU GitHub ≫

1 2D FT and Image Synthesis

Let’s try to perform the same image synthesis to reconstruct the Cyrillic and English alphabet images.

## [1] 411 353
## [1] 411 353

############## FT of img_CyrAlpha  
#X1 = fft(img_CyrAlpha); display(fftshift(Re(X1)), method = "raster")
#X1_mag <- sqrt(Re(X1)^2+Im(X1)^2); display(fftshift(X1_mag), method = "raster") # magnitude only
#X1_phase  <- atan2(Im(X1), Re(X1)); display(fftshift(X1_phase), method = "raster") # phase only
#####  Implicit Automated IFT
#hat_X1 = Re(fft(X1, inverse = T)/length(square_arr)); display(hat_X1, method = "raster")  
###### Manually invert the FT (IFT) using the magnitudes and phases
#Real1 = X1_mag * cos(X1_phase)
#Imaginary1 = X1_mag * sin(X1_phase)
#man_hat_X1 = Re(fft(Real1+1i*Imaginary1, inverse = T)/length(X1)); display(man_hat_X1, method = "raster")  

############### FT of img_EngAlpha
#X2 = fft(circle_arr); display(Re(X2), method = "raster")
#X2_mag <- sqrt(Re(X2)^2+Im(X2)^2); display(X2_mag, method = "raster") # magnitude only
#X2_phase  <- atan2(Im(X2), Re(X2)); display(X2_phase, method = "raster") # phase only
######  Implicit Automated IFT
# hat_X2 = Re(fft(X2, inverse = T)/length(circle_arr)); display(hat_X2, method = "raster") 
###### Manually invert the FT (IFT) using the magnitudes and phases
#Real2 = X2_mag * cos(X2_phase)
#Imaginary2 = X2_mag * sin(X2_phase)
#man_hat_X2 = Re(fft(Real2+1i*Imaginary2, inverse = T)/length(X1)); display(man_hat_X2, method = "raster")  

# IFT Magnitude=mag_ft_img_CyrAlpha   AND  Phase=phase_ft_img_EngAlpha
Real = mag_ft_img_CyrAlpha * cos(phase_ft_img_EngAlpha)
Imaginary = mag_ft_img_CyrAlpha * sin(phase_ft_img_EngAlpha)
ift_MagCyr_PhaseEng = Re(fft(Real+1i*Imaginary, inverse = T)/length(mag_ft_img_CyrAlpha))
EBImage::display(ift_MagCyr_PhaseEng, method = "raster", title="(IFT o FT) Magnitude=Cyr | Phase=Eng")

2 Appendix: Functions Used

2.1 fftshift()

# FFT SHIFT
#' This function is useful for visualizing the Fourier transform with the zero-frequency 
#' component in the middle of the spectrum.
#' 
#' @param img_ff A Fourier transform of a 1D signal, 2D image, or 3D volume.
#' @param dim Number of dimensions (-1, 1, 2, 3).
#' @return A properly shifted FT of the array.
#' 
fftshift <- function(img_ff, dim = -1) {

  rows <- dim(img_ff)[1]    
  cols <- dim(img_ff)[2]
  # planes <- dim(img_ff)[3]

  swap_up_down <- function(img_ff) {
    rows_half <- ceiling(rows/2)
    return(rbind(img_ff[((rows_half+1):rows), (1:cols)], img_ff[(1:rows_half), (1:cols)]))
  }

  swap_left_right <- function(img_ff) {
    cols_half <- ceiling(cols/2)
    return(cbind(img_ff[1:rows, ((cols_half+1):cols)], img_ff[1:rows, 1:cols_half]))
  }
  
  #swap_side2side <- function(img_ff) {
  #  planes_half <- ceiling(planes/2)
  #  return(cbind(img_ff[1:rows, 1:cols, ((planes_half+1):planes)], img_ff[1:rows, 1:cols, 1:planes_half]))
  #}

  if (dim == -1) {
    img_ff <- swap_up_down(img_ff)
    return(swap_left_right(img_ff))
  }
  else if (dim == 1) {
    return(swap_up_down(img_ff))
  }
  else if (dim == 2) {
    return(swap_left_right(img_ff))
  }
  else if (dim == 3) {
    # Use the `abind` package to bind along any dimension a pair of multi-dimensional arrays
    # install.packages("abind")
    library(abind)
    
    planes <- dim(img_ff)[3]
    rows_half <- ceiling(rows/2)
    cols_half <- ceiling(cols/2)
    planes_half <- ceiling(planes/2)
    
    img_ff <- abind(img_ff[((rows_half+1):rows), (1:cols), (1:planes)], 
                    img_ff[(1:rows_half), (1:cols), (1:planes)], along=1)
    img_ff <- abind(img_ff[1:rows, ((cols_half+1):cols), (1:planes)], 
                    img_ff[1:rows, 1:cols_half, (1:planes)], along=2)
    img_ff <- abind(img_ff[1:rows, 1:cols, ((planes_half+1):planes)], 
                    img_ff[1:rows, 1:cols, 1:planes_half], along=3)
    return(img_ff)
  }
  else {
    stop("Invalid dimension parameter")
  }
}

2.2 ifftshift()

# IFFT SHIFT
#' This function is useful for moving back the zero-frequency component in the middle of the spectrum
#' back to (0,0,0).  It rearranges in reverse (relative to fftshift()) the indices appropriately,
#' so that the image can be correctly reconstructed by the IFT in spacetime
#' 
#' @param img_ff An Inverse Fourier transform of a 1D signal, 2D image, or 3D volume.
#' @param dim Number of dimensions (-1, 1, 2, 3).
#' @return A properly shifted IFT of the input array.
#' 
ifftshift <- function(img_ff, dim = -1) {

  rows <- dim(img_ff)[1]    
  cols <- dim(img_ff)[2]    

  swap_up_down <- function(img_ff) {
    rows_half <- floor(rows/2)
    return(rbind(img_ff[((rows_half+1):rows), (1:cols)], img_ff[(1:rows_half), (1:cols)]))
  }

  swap_left_right <- function(img_ff) {
    cols_half <- floor(cols/2)
    return(cbind(img_ff[1:rows, ((cols_half+1):cols)], img_ff[1:rows, 1:cols_half]))
  }

  if (dim == -1) {
    img_ff <- swap_left_right(img_ff)
    return(swap_up_down(img_ff))
  }
  else if (dim == 1) {
    return(swap_up_down(img_ff))
  }
  else if (dim == 2) {
    return(swap_left_right(img_ff))
  }
  else if (dim == 3) {
    # Use the `abind` package to bind along any dimension a pair of multi-dimensional arrays
    # install.packages("abind")
    library(abind)
    
    planes <- dim(img_ff)[3]
    rows_half <- floor(rows/2)
    cols_half <- floor(cols/2)
    planes_half <- floor(planes/2)
    
    img_ff <- abind(img_ff[1:rows, 1:cols, ((planes_half+1):planes)], 
                    img_ff[1:rows, 1:cols, 1:planes_half], along=3)
    img_ff <- abind(img_ff[1:rows, ((cols_half+1):cols), (1:planes)], 
                    img_ff[1:rows, 1:cols_half, (1:planes)], along=2)
    img_ff <- abind(img_ff[((rows_half+1):rows), (1:cols), (1:planes)], 
                    img_ff[(1:rows_half), (1:cols), (1:planes)], along=1)
    return(img_ff)
  }
  else {
    stop("Invalid dimension parameter")
  }
}

2.3 fftinv()

SOCR Resource Visitor number SOCR Email