将小阵列滑动到更大的有效方式来比较它们

时间:2015-09-28 19:51:47

标签: r

我有一组以3D阵列存储和组织的黑白参考图像。另外,我有一个较小的"目标"这与其他图像之一非常相似。想象一下,参考图像是不同城市的卫星图像,我的目标图像是任何城市中未知城市街区的照片。我想确定该街区所在的城市。

我有简单的代码(下面的简化演示),但是三个嵌套for循环它非常慢。

有没有人知道如何加快速度?任何想法都赞赏!

编辑:在真实场景中,图像已经处理完,因此只保留重要的功能,因此该部分的效果令人满意。我的主要问题是for循环是否可以用apply()函数替代。

# create 100 artificial images (cities), stored in a 3D array. Each image is 100x100 "pixels"
reference_images = sample(c(0,1),1000000, replace = TRUE)
dim(reference_images) = c(100,100,100)

# create  target image (city block). This is the piece we want to find.
# NB! In this artificial case, we just copy a 50x50 piece from the 7th of the randomly generated 
# reference images. This is obviously only useful for this demo, in the real case the  
# target image comes from an other source.
target_image = reference_images[51:100,51:100,7]

# example image
library(grid)
grid.raster(reference_images[,,1],interpolate = F)
# target_image
grid.raster(target_image,interpolate = F)

# array to store the error of each match. 
# The 50x50 target image can be compared to 51*51 positions in each of the 100x100 images.
# The error array will therefor be 51x51x100, each position corresponding to the position 
# of the "top left corner" of the target image when compared to the candidate images. 
error = rep(NA,51*51*100)
dim(error) = c(51,51,100)

# (SLOW!)
# Loop through each comparable position of each candidate image and stor the error of each
# By image...
for(k in 1:dim(reference_images)[3]){
  # by row...
  for(i in 1:51){
    # by column...
    for(j in 1:51){
      error[i,j,k] = sum(target_image != reference_images[i:(i+49),j:(j+49), k])
    }
  }
}

# If everything went as expected, the error of position [51,51,7] should be 0.
error[,,7]

1 个答案:

答案 0 :(得分:1)

这是一种不完美的方法,但显示方向。对于上面提到的数据集大小,应该足以将两个内部循环从R移动到某个编译扩展。 raster的焦点是候选人:

library(raster)
target_image <- reference_images[50:100,50:100,7]

best_match <- function(i) max(as.matrix(focal(raster(i), target_image, pad = T, padValue = 0)))
apply(reference_images, 3, best_match)

在~8秒内将图像#7识别为最佳候选者(Intel i7 CPU):

[1]  714  710  718  716  720  710 1327  724  727  717  703  720  718  715  712  722  715  711  711  722  702  747  705
[24]  717  725  744  744  713  736  726  724  706  725  716  710  728  715  709  695  719  717  736  733  702  695  718
[47]  711  714  712  713  733  692  714  702  719  717  717  719  703  701  718  726  704  713  712  725  712  708  721
[70]  706  709  715  707  718  723  714  708  703  712  737  720  701  737  723  723  720  732  714  703  708  719  727
[93]  703  723  705  711  702  699  712  700

有点hacky - focal需要奇数大小的窗口(查询)并计算查询和目标(元素方式产品的总和)的卷积,但对于二进制图像,这很有效,给出完全匹配的高分。

一些更通用的建议(考虑数千个图像的数据集,甚至更多的查询):

鉴于数据是图像,我会尝试与某些image feature descriptors匹配。图像中的“地标”被转换为30-60维向量,索引为类似KD树的东西,并有效地搜索和匹配。

我见过的另一种图像补丁匹配方法是cross correlation through FFT。该链接在matlab上,但仍可作为指导。

编辑:对于通用建议感到抱歉,我只是想向OP提示一个好的方向。