#' fuzzySpatialCMeansSegmentation
#'
#' Fuzzy spatial c-means for image segmentation.
#'
#' Image segmentation using fuzzy spatial c-means as described in
#'
#' Chuang et al., Fuzzy c-means clustering with spatial information for image
#' segmentation. CMIG: 30:9-15, 2006.
#'
#' @param image image to be segmented.
#' @param mask optional mask image. Otherwise, the entire image is used.
#' @param numberOfClusters number of segmentation clusters
#' @param m fuzziness parameter (default = 2).
#' @param p membership importance parameter (default = 1).
#' @param q spatial constraint importance parameter (default = 1).
#' \code{q = 0} is equivalent to conventional fuzzy c-means.
#' @param radius neighborhood radius (scalar or array) for spatial
#' constraint.
#' @param maxNumberOfIterations iteration limit (default = 20).
#' @param convergenceThreshold Convergence between iterations is measured
#' using the Dice coefficient (default = 0.02).
#' @param verbose print progress.
#' @return list containing segmentation and probability images
#'
#' @author NJ Tustison
#'
#' @examples
#' image <- antsImageRead(getANTsRData("r16"))
#' mask <- getMask(image)
#' fuzzy <- fuzzySpatialCMeansSegmentation(image, mask)
#'
#' @export fuzzySpatialCMeansSegmentation
fuzzySpatialCMeansSegmentation <- function(
image, mask = NULL, numberOfClusters = 4,
m = 2, p = 1, q = 1, radius = 2, maxNumberOfIterations = 20, convergenceThreshold = 0.02,
verbose = FALSE) {
if (is.null(mask)) {
mask <- antsImageClone(image) * 0 + 1
}
x <- image[mask != 0]
v <- seq(from = 0, to = 1, length.out = numberOfClusters + 2)[2:(numberOfClusters + 1)]
v <- v * (max(x) - min(x)) + min(x)
cc <- length(v)
if (verbose == TRUE) {
cat("Initial cluster centers: ", v, "\n")
}
xx <- matrix(data = 0, nrow = cc, ncol = length(x))
for (i in seq.int(cc))
{
xx[i, ] <- x
}
if (length(radius) == 1) {
radius <- rep(radius, image@dimension)
}
segmentation <- antsImageClone(image) * 0
probabilityImages <- NULL
iter <- 0
diceValue <- 0
while (iter < maxNumberOfIterations && diceValue < 1.0 - convergenceThreshold) {
# Update membership values
xv <- matrix(data = 0, nrow = cc, ncol = length(x))
for (k in seq.int(cc))
{
xv[k, ] <- abs(x - v[k])
}
u <- matrix(data = 0, nrow = nrow(xv), ncol = ncol(xv))
for (i in seq.int(cc))
{
n <- xv[i, ]
d <- n * 0
for (k in seq.int(cc))
{
d <- d + (n / xv[k, ])^(2 / (m - 1))
}
u[i, ] <- 1 / d
}
u[is.nan(u)] <- 1
# Update cluster centers
v <- rowSums((u^m) * xx, na.rm = TRUE) / rowSums(u^m, na.rm = TRUE)
if (verbose == TRUE) {
cat("Updated cluster centers: ", v, "\n")
}
# Spatial function
h <- matrix(data = 0, nrow = nrow(u), ncol = ncol(u))
for (i in seq.int(cc))
{
uImage <- antsImageClone(image) * 0
uImage[mask != 0] <- u[i, ]
uNeighborhoods <- getNeighborhoodInMask(uImage, mask, radius)
h[i, ] <- colSums(uNeighborhoods, na.rm = TRUE)
}
# u prime
d <- rep(0, ncol(u))
for (k in seq.int(cc))
{
d <- d + (u[k, ]^p) * (h[k, ]^q)
}
probabilityImages <- list()
uprime <- matrix(data = 0, nrow = nrow(u), ncol = ncol(u))
for (i in seq.int(cc))
{
uprime[i, ] <- (u[i, ]^p) * (h[i, ]^q) / d
uprimeImage <- antsImageClone(image) * 0
uprimeImage[mask != 0] <- uprime[i, ]
probabilityImages[[i]] <- uprimeImage
}
tmpSegmentation <- antsImageClone(image) * 0
tmpSegmentation[mask != 0] <- max.col(t(uprime))
diceValue <- labelOverlapMeasures(segmentation, tmpSegmentation)$MeanOverlap[1]
iter <- iter + 1
if (verbose == TRUE) {
cat("Iteration ", iter, " (out of ", maxNumberOfIterations, "): ",
"Dice overlap = ", diceValue, "\n",
sep = ""
)
}
segmentation <- tmpSegmentation
}
return(list(
segmentationImage = segmentation,
probabilityImages = probabilityImages
))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.