|
# Created by Matteo Silvestro for an essay about CFTP algorithm # 16/06/2016 # CC BY |
|
|
|
library(pixmap) # to extract a matrix of zeros and ones from a binary image |
|
library(grid) # to display a matrix of zeros and ones in R |
|
|
|
# I define as one-line-matrix a square matrix with all elements in a single vector. |
|
# It is easy to get a virtual matrix from such vector by setting number of cols/rows = sqrt(length of vector) |
|
|
|
# draw the one-line-matrix of -1 and +1 as an image in R |
|
drawImage <- function(image) { |
|
N <- sqrt(length(image)) # compute the size of the squared image |
|
grid.newpage() # delete all previous stuff on the drawing surface |
|
imagen <- matrix(1-(image+1)/2, ncol=N) # change of values from -1 -> 0, +1 -> 1 |
|
grid.raster(imagen, interp=F) # with a matrix of 0 and 1, the grid package can draw the image correctly |
|
} |
|
|
|
# return a vector with the neighbour elements of the k-th element of the one-line-matrix x |
|
neighbour <- function(x, k) { |
|
N <- sqrt(length(x)) # compute the size of the virtual matrix |
|
neigh <- NULL # this will be the vector of all neighbours |
|
# here there is a bit of algebra to get the right elements, remember that x is a one-line-matrix |
|
# (one-line-matrix vector index) k -> (floor(k/N), k % N) (virtual matrix index) |
|
# soppose (i, j) are the coordinate of x[k], then the neighbours are |
|
# (i, j-1), (i, j+1), (i-1, j), (i+1, j) if 1 <= i, j <= N |
|
if (k-N >= 1) neigh <- c(neigh, x[k-N]) |
|
if (k+N <= N*N) neigh <- c(neigh, x[k+N]) |
|
if (k %% N != 1) neigh <- c(neigh, x[k-1]) |
|
if (k %% N != 0) neigh <- c(neigh, x[k+1]) |
|
return(neigh) |
|
} |
|
|
|
fullcond <- function(x, y, k, beta, p) { |
|
return(1 / ( 1 + exp(-2*beta*sum(neighbour(x, k)) - log((1-p)/p)*y[k] ) )) |
|
} |
|
|
|
# apply the Propp-Wilson algorithm |
|
rimage <- function(y, beta, p, N, seed) { |
|
Time <- -0.5 # actual starting time is -1, since it is doubled immediately |
|
xmax <- rep(1, N*N) |
|
xmin <- rep(-1, N*N) |
|
while (!all(xmax == xmin)) { # continue until convergence does occur |
|
xmax <- rep(1, N*N) # image with all black pixels |
|
xmin <- rep(-1, N*N) # image with all white pixels |
|
Time <- Time*2 # double the time, as suggested by Propp-Wilson |
|
set.seed(seed) # seed must be fixes, since we use random mappings |
|
utot <- runif(N*N*(-Time)) # create the needed random mappings random numbers |
|
for (t in Time:-1) { |
|
u <- utot[ (N*N*(-t-1)+1) : (N*N*(-t)) ] # extract the random numbers to be used is this iteration |
|
for (k in 1:(N*N)) { # apply the Gibbs sampler, updating a pixel at a time |
|
xmax[k] = (u[k] < fullcond(xmax, y, k, beta, p))*2-1 |
|
xmin[k] = (u[k] < fullcond(xmin, y, k, beta, p))*2-1 |
|
} |
|
} |
|
} |
|
print(c(seed, Time)) |
|
return(xmax) |
|
} |
|
|
|
restoreImage <- function(file, p, beta, simn) { |
|
image <- read.pnm(file, cellres=1) # cellres is to avoid the warning |
|
image <- 1-as.vector(image@grey) |
|
N <- sqrt(length(image)) |
|
|
|
# make an array with the binary original binary image, with +1 as black and -1 as white |
|
x <- image*2-1 |
|
drawImage(x) |
|
|
|
# degrade the image with a Bernoulli noise with p as probability to degrade |
|
y <- x * (rbinom(N*N, 1, 1-p)*2-1) # apply Bernoulli noise |
|
drawImage(y) |
|
|
|
# apply the restoring algorithm, based on Gibbs sampler with CFTP |
|
sample <- NULL |
|
for (i in 1:simn) { |
|
sample <- c(sample, rimage(y, beta, p, N, i)) # make one long vector with all samples |
|
} |
|
sample <- matrix(sample, nrow=simn, ncol=N*N, byrow=T) # and then split it in a matrix with as each row a sample |
|
|
|
# MPM (marginal posterior mode) estimator |
|
mode <- rep(0, N*N) |
|
for (i in 1:(N*N)) { |
|
mode[i] <- (sum(sample[,i]) > 0)*2-1 # make the mode of each pixel, i.e. for each column of the matrix take the most frequent value (+1 or -1) |
|
} |
|
drawImage(mode) |
|
|
|
# compute the misclassification rate |
|
mis <- sum(mode != x)/(N*N) |
|
|
|
# return a list with all informations |
|
return(list(original=x, degraded=y, restored=mode, error=mis)) |
|
} |
|
|
|
# ptm <- proc.time() |
|
# result <- restoreImage("img/penguin.pbm", p=0.3, beta=0.45, simn=1) |
|
# time <- proc.time() - ptm |