library(imager)
mainDir <- "/run/media/issactoast/My Passport/Documents/Blog/R-programming/Topics/R imager"
setwd(mainDir)
tmp <- load.image("test.jpg")
plot(tmp, axes = FALSE)
tmp[tmp < quantile(tmp[tmp>0], 0.99)] <- 0
tmp <- isoblur(tmp, 2)
# Check the result
plot(tmp, axes = FALSE)
df <- as.data.frame(tmp) %>% subset(value > 0.1)
centers <- dplyr::group_by(df,value) %>%
dplyr::summarise(mx=mean(x),my=mean(y))
#check the result
plot(tmp)
with(centers, points(mx, my, col="red"))
We can check the number of points we have and what they look like:
coor <- as.matrix(centers[,2:3])
head(coor)
## mx my
## [1,] 280 250
## [2,] 223 47
## [3,] 267 177
## [4,] 467 87
## [5,] 282 153
## [6,] 215 51
dim(coor)
## [1] 4948 2
There are many points but we can see they are sticking together. Thus, we can use k-mean algorithm to classify them into the desired categories based on the eucledian distance. Let’s prepare some variables:
# Do k-mean
l <- length(coor[,1])
membership <- rep(0, l)
class.point <- coor[1,]
# Distance function between point and class.points set
dist.m <- function(x, y){
if (is.null(dim(y))) sqrt( sum((x-y)^2) )
else sqrt(rowSums(sweep(y, 2, x)^2))
}
Set our radius r and do clustering:
r <- 10
while(TRUE){
for (i in 1:l){
d <- dist.m(coor[i,], class.point)
if (min(d) > r){
# updata class
class.point <- rbind(class.point, coor[i, ])
# updata membership
membership[i] <- length(class.point[,1])
} else {
membership[i] <- which.min(d)
}
}
# class point update
class.point <- aggregate(coor, list(membership), mean)[,2:3]
# closest distance between classes
k <- length(class.point[,1])
d <- min(as.vector(dist(class.point, method = "euclidean")))
# do this until the closest distance is larger than radius
if (d > r) break
else {
a <- which.min(as.vector(dist(class.point, method = "euclidean")))
nearClass <- which( (a - cumsum((k-1):1)) < 0 )[1]
class.point <- class.point[-nearClass, ]
row.names(class.point) <- 1:(k-1)
}
}
par(mfrow = c(1,2), mar = c(0.2,0.2,0.2,0.2))
plot(tmp, axes = FALSE)
plot(tmp, axes = FALSE)
points(class.point[,1], class.point[,2], col="white")
Number of points:
## [1] 28