我有一组以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]
答案 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提示一个好的方向。