更新找到link to an implementation of bwlabel in the R image processing toolbox。所以以下可能不是必需的,但创建起来很有趣:-) 你应该看看那个包,因为它有其他对象分割算法(即分水岭),可能比你的 k-means 聚类的第一步更好.
如果您的分割在背景和对象之间正确标记,并且至少有一个背景像素将不同对象之间的边界分开,那么您可能希望在 R 中实现 matlab 的 bwlabel 函数。有关该解释,请参阅 this SO question/answer
下面是一个不执行标记的实现(尽管它很容易被采用):
find.contiguous <- function(img, x, bg) {
## we need to deal with a single (row,col) matrix index
## versus a collection of them in a two column matrix separately.
if (length(x) > 2) {
lbl <- img[x][1]
img[x] <- bg
xc <- x[,1]
yc <- x[,2]
} else {
lbl <- img[x[1],x[2]]
img[x[1],x[2]] <- bg
xc <- x[1]
yc <- x[2]
}
## find all neighbors of x
x <- rbind(cbind(xc-1, yc-1),
cbind(xc , yc-1),
cbind(xc+1, yc-1),
cbind(xc-1, yc),
cbind(xc+1, yc),
cbind(xc-1, yc+1),
cbind(xc , yc+1),
cbind(xc+1, yc+1))
## that have the same label as the original x
x <- x[img[x] == lbl,]
## if there is none, we stop and return the updated image
if (length(x)==0) return(img);
## otherwise, we call this function recursively
find.contiguous(img,x,bg)
}
find.contiguous 是一个递归函数,对于它收到的每个调用:
- 图片
img的工作副本。
- 像素(矩阵)索引
x (row,col) 的集合,属于图像img 中的对象。
- 背景值
bg
find.contiguous 然后继续:
- 将
img 中x 处的所有像素设置为bg 颜色。这标志着我们已经访问了像素。
- 查找
x 中与x 具有相同标签(值)的所有相邻像素。这会扩大同一对象的区域。请注意,由于x 不一定是单个像素,x 会以几何形状增长,因此,事实上,这个函数并没有懈怠。
- 如果没有更多的邻居属于同一个对象,我们返回更新后的图像;否则,我们进行递归调用。
从对应于对象的单个像素开始,对find.contiguous 的调用将扩大该区域以包含对象的所有像素并返回更新的图像,其中对象被背景替换。然后可以循环重复此过程,直到图像中不再有对象,因此可以生成计数。
为了说明,我假设你的二进制图像是一个名为matrix 的img:
## set the background pixel value
bg <- 0
## set the object pixel value
obj <- 1
## pad image so that the edge is background, this is necessary because
## the neighborhood generated in find.contiguous must lie strictly within
## the image
tmp <- matrix(bg,nrow=nrow(img)+2,ncol=ncol(img)+2)
tmp[2:(nrow(img)+1),2:(ncol(img)+1)] <- img
img <- tmp
## initialize the count to zero
count <- 0
## get all pixel coordinates that are objects
x <- which(img==obj, arr.ind=TRUE)
## loop until there are no more pixels that are objects
while (length(x) > 0) {
## choose a single (e.g., first) pixel location. This belongs to the current
## object that we will grow and remove from the image using find.contiguous
if (length(x) > 2) {
x <- x[1,]
}
## increment the count
count <- count + 1
## make the call to remove the object from img
img <- find.contiguous(img, x, bg)
## find the remaining pixel locations belonging to objects
x <- which(img==obj, arr.ind=TRUE)
}
您的答案在count。在上一个链接中的示例数据上运行:
img <- as.matrix(read.table(text="
0 0 0 0 0 1 1 1 0 0
0 1 0 1 0 0 1 1 0 0
0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 1 1
0 0 1 1 1 1 0 0 1 1", header=FALSE))
我们得到:
print(paste("number of objects: ",count))
##[1] "number of objects: 4"