首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >R:计算图片中的对象

R:计算图片中的对象
EN

Stack Overflow用户
提问于 2016-08-15 16:57:17
回答 2查看 3.1K关注 0票数 7

我目前正在研究一个问题,在这个问题上,我使用图片来预测结果,从而构建了一个分类器。基本上,我在图片上有对象(一个或几个),我想识别它们。由于我可以有一个或几个对象(并不总是相同的),我首先想要能够计算出我的图片上有多少个对象。我不想运行任何机器学习算法,我希望有一些方法来尽快完成它。

运行k-方法(使用颜色)使我能够将图片分割成两个颜色组,这使得背景和对象之间已经有了很好的分离。从这张照片中,我想找到一种计算所有不同“区域”的方法。我试着运行一个k-意思是使用颜色和位置,尝试在一步完成所有,但它并不是很好的工作,因为添加位置的kmeans降低了它的结果。

下面是图片的一个示例,一旦将它与kmeans分割成两个颜色区域:

显然这里有5个物体和一个背景。或者,另外,6个不同的区域。

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

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

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

我希望一切都足够清楚。提前谢谢你!

EN

回答 2

Stack Overflow用户

发布于 2016-08-15 20:14:22

Update找到了一个链接到R图像处理工具箱中bwlabel的实现。因此,下面的内容可能是不必要的,但创建起来很有趣:-)您应该看看这个包,因为它有其他对象分割算法(即分水岭),这些算法可能比k均值聚类的第一步更好。

如果您的分割在背景和目标之间的标记正确,至少有一个背景像素分隔不同对象之间的边界,那么您需要在R中实现matlab的bwlabel函数,以了解对此的解释,参见这是如此的问题/答案

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

代码语言:javascript
运行
复制
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是一个递归函数,在这个函数中,它接收到的每个调用:

  1. 图像img的工作副本。
  2. 像素(矩阵)集合索引属于图像x中的对象的img (行,col)。
  3. 背景值bg

然后,find.contiguous继续进行:

  1. ximg中的所有像素设置为bg颜色。这标志着我们已经访问了像素。
  2. 查找x的所有相邻像素,这些像素具有与x中相同的标签(值)。这将增长同一对象的区域。请注意,由于x不一定是单个像素,x以几何方式增长,因此,实际上,这个函数不是懒散的。
  3. 如果没有更多的邻居属于同一个对象,则返回更新的映像;否则,进行递归调用。

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

为了说明,我假设您的二进制映像是一个名为matrix img的图像。

代码语言:javascript
运行
复制
## 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。在上一链接中的示例数据上运行此操作:

代码语言:javascript
运行
复制
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))

我们得到:

代码语言:javascript
运行
复制
print(paste("number of objects: ",count))
##[1] "number of objects:  4"
票数 7
EN

Stack Overflow用户

发布于 2016-08-15 20:29:20

我不是图片识别方面的专家,所以我的方法可能会失败。如果您的对比是好的,并且所有的矩形都是水平对齐的,那么您也许可以尝试以下方法:

  • 找到边界-简化为一维:建立图像的渐变,并在某个阈值以上的梯度取点(希望这会给出所有矩形的“边界线”)
  • 随机得到4个角:Pic一个点。采取一个小步长的增量,并找到邻居(应该有2-“以前的邻居不允许=>总是朝同一个方向走)。同时跟踪x和y的变化。迭代这个过程,直到你回到第一个)。改变x或y的点属于角。
  • 重构矩形:用一条线(步长三角形的外露区域)从角点对角点进行拟合。限制线之间的两个角落之间的空间。
  • 删除已找到的矩形:如果fit足够好(例如r平方),删除数据中接近fit的所有点--从以前找到的矩形中不应该保留任何东西,您可以增加找到的矩形的数量。
  • 迭代上面的内容,直到数据为空,

如果这有效的话,你也有矩形的中心。希望这能帮上忙..。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38959470

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档