R:计算图片中的对象 [英] R: Count objects in a picture

查看:124
本文介绍了R:计算图片中的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在解决一个问题,即使用图片构建分类器来预测结果。基本上,我有一个图片上的对象(一个或几个),我想识别它们。因为我可以有一个或多个对象(并不总是相同),我首先想要计算我的图片上有多少个对象。我不想运行任何机器学习算法,我想尽可能快地做到这一点。

I am currently working on a problem where I build a classifier using pictures to predict an outcome. Basically, I have objects on a picture (one or several), and I want to identify them. As I can have one object or several of them (not always identical), I first would like to be able to count how many objects are present on my picture. I don't want to run any machine learning algorithm and I'd like to have some way of doing it as fast as possible.

运行k-means(使用使我能够将图片分成2个颜色组,这使得背景和物体之间已经有了很好的分离。从这张图片中我想找到一种方法来计算所有不同的区域。我尝试使用颜色和位置来运行k-means以尝试一步完成但由于向kmeans添加位置会降低其结果,因此效果不佳。

Running a k-means (using color) enables me to separate the picture in 2 color groups which gives already a pretty good separation between background and objects. From this picture I'd like to find a way to count all the different "regions". I tried to run a k-means using both color and positions to try to do all in one step but it does not work out very well since adding positions to the kmeans degrades its result.

这是一个图片的例子,一旦用kmeans将它分成两个颜色区域:

Here is an example of what the picture would like, once having separated it in two color regions with the kmeans:

显然这里有5个对象和一个背景。或者,或者,6个不同的区域。

Obviously there are 5 objects and one background here. Or, alternatively, 6 distinctive regions.

我想做的是在该图片上运行一个能告诉我这个数字的算法。我不熟悉图像处理,所以我想不出快速有效的方法。我想到的一个解决方案是从对象类中获取一个像素,并测试相邻像素是否属于同一个类,或者实际上是背景类的一部分。但这将是一个痛苦的漫长的做事方式。

What I would like to do is run an algorithm on that picture that would tell me that number. I am not familiar with image processing so I cannot think of a fast and efficient way of doing it. One solution I would think of would be to take a pixel from the objects class and test if the neighbouring pixels belong to the same class or are actually part of the background class. But this would be a painfully long way of doing things.

我尝试过blob识别,但看起来这个算法并不适合我需要的东西。

I have tried blob recognition but it does not look like this algorithm is suited for what I need.

我很想知道如何解决这类问题。我不介意自己编写算法代码,但我也很想知道是否有R软件包可以轻松实现这类功能。

I would be quite interested in knowing how to do that kind of problem. I don't mind having to code the algorithm myself but I'm also interested in knowing if there are R packages that enables this kind of thing easily.

我希望一切很清楚。非常感谢你提前!

I hope everything is clear enough. Thank you a lot in advance!

推荐答案

更新找到链接到R图像处理工具箱中的bwlabel实现。所以下面的内容可能没有必要,但创建起来很有趣:-)你应该看看那个包,因为它有其他对象分割算法(即分水岭)可能比你k-means聚类的第一步更好。

Update Found a link to an implementation of bwlabel in the R image processing toolbox. So the following is probably not necessary, but it was fun to create :-) You should take a look at that package as it has other object segmentation algorithms (i.e., watershed) that may be better than your first step of k-means clustering.

如果您的分段在背景和对象之间正确标记,并且至少有一个背景像素将不同对象之间的边界分开,那么您可能希望实现matlab的<$ c $ R中的b> bwlabel 函数。有关该函数的解释,请参阅这个问题/答案

If your segmentation is correctly labeling between background and object with at least one background pixel separating the boundaries between distinct objects, then you would want to implement matlab's bwlabel function in R. For an explanation of that see this SO question/answer

下面是一个不执行标记的实现(尽管可以很容易地采用这样做):

Below is an implementation that does not perform labeling (although it can be easily adopted to do so):

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 是一个递归函数,对于它接收的每个调用:

find.contiguous is a recursive function in which for each call it receives:


  1. 图像的工作副本 img

  2. 像素(矩阵)的集合索引 x (row,col)属于图像中的对象 img

  3. 背景值 bg

  1. A working copy of the image img.
  2. A collection of pixel (matrix) indices x (row,col) that belong to an object in the image img.
  3. The background value bg

find.contiguous 然后转到:


  1. 将所有像素设置为 x in img bg 颜色。这标志着我们已经访问了像素。

  2. 查找与 x 中具有相同标签(值)的所有相邻像素 X 。这会增加同一对象的区域。请注意,由于 x 不一定是单个像素, x 几何增长 ,以便事实上,这个功能并不懈怠。

  3. 如果没有更多的邻居属于同一个对象,我们会返回更新的图像;否则,我们进行递归调用。

  1. Set all pixels at x in img to the bg color. This marks that we have visited the pixels.
  2. Find all neighboring pixels of x that have the same label (value) as that in x. This grows the region of the same object. Note that since x is not necessarily a single pixel, x grows geometrically so that, in fact, this function is no slouch.
  3. If there are no more neighbors belonging to the same object, we return the updated image; otherwise, we make the recursive call.

从对应一个对象的单个像素开始,调用 find.contiguous 将增大区域以包含所有对象的像素,并返回更新的图像,其中对象被背景替换。然后可以在循环中重复此过程,直到图像中不再有对象,因此能够生成计数。

Starting from a single pixel that correspond to an object, a call to find.contiguous will grow the region to include all the object's pixels and return an updated image where the object is replaced by the background. This process can then be repeated in a loop until there are no more objects in the image, hence the ability to generate a count.

为了说明,我假设您的二进制文件image是矩阵名为 img

To illustrate, I assume that your binary image is a matrix named 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 。在上一个链接的示例数据上运行此操作:

Your answer is in count. Running this on a sample data from the previous link:

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"

这篇关于R:计算图片中的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆