我有一个用例,我想交叉比较2组图像,以了解最好的类似对。
然而,这些集非常大,出于性能目的,我不想一直打开和关闭图像。
所以我的想法是:
std::map<int, Magic::Image> set1;
for(...) { set1[...] = Magic::Image(...);}
std::map<int, int> best;
for(...) {
set2 = Magic::Image(...);
//Compare with all the set1
...
best[...] = set1[...]->first;
}
很明显,我不需要存储所有的设置2,因为我按图像工作。 但无论如何,set1已经非常大,以至于存储32位图像太多了。供参考:15000张图片,300x300 = 5GB
我虽然通过将图像下采样到单色来减少内存(它不会影响我的用例)。但怎么办呢?即使我得到一个颜色通道,Image-Magick仍然会将新图像威胁为32位,即使它只是一个通道。
我的最后一种方法是编写一个自解析器,它按颜色读取颜色,转换它,并创建一个位向量。然后进行异或并计数位。这样可行。 (仅使用170 MB)
但是,不灵活。如果我想在某个时刻使用2位或8位怎么办?是否有可能以任何方式使用Imagemagick自己的类并只调用compare()
?
谢谢!
答案 0 :(得分:1)
我有几点建议 - 也许有些东西可以给你一个想法!
建议1
也许你可以使用Perceptual Hash。不是将所有图像保存在内存中,而是为每个图像一次计算一个哈希值,然后比较哈希值之间的距离。
某些pH值对图像比例不变(或者您可以在散列之前将所有图像缩放到相同的大小),并且大多数对图像格式不变。
以下是Neal Krawetz博士的一篇文章...... Perceptual Hashing。
ImageMagick也可以进行Perceptual Hashing并可以从PHP调用 - 请参阅here。
我还为这类事情写了一些代码... code.
建议2
据我所知,ImageMagick版本7迫在眉睫 - 不知道谁能告诉你更多 - 它支持真正的单通道灰度图像 - 以及多达32通道的多光谱图像。我相信它也可以充当服务器 - 将图像保存在内存中以供后续使用。也许这可以帮助。
建议3
也许你可以从GNU Parallel中获得一些好处 - 它可以保持所有CPU内核并行繁忙,并使用ssh
在多个服务器上分配工作。有很多教程和示例,但只是为了演示将一组命名图像(a,b,c,d)的每个项目与每组图像(1,2)进行比较,你可以这样做:
parallel -k echo {#} compare {1} {2} ::: a b c d ::: 1 2
输出
1 compare a 1
2 compare a 2
3 compare b 1
4 compare b 2
5 compare c 1
6 compare c 2
7 compare d 1
8 compare d 2
显然我已将echo
放在那里,以便您可以看到生成的命令,但您可以将其删除并实际运行compare
。
因此,您的代码可能看起来更像这样:
#!/bin/bash
# Create a bash function that GNU Parallel can call to compare two images
comparethem() {
result=$(convert -metric rmse "$1" "$2" -compare -format "%[distortion]" info:)
echo Job:$3 $1 vs $2 $result
}
export -f comparethem
# Next line effectively uses all cores in parallel to compare pairs of images
parallel comparethem {1} {2} {#} ::: set1/*.png ::: set2/*.png
输出
Job:3 set1/s1i1.png vs set2/s2i3.png 0.410088
Job:4 set1/s1i1.png vs set2/s2i4.png 0.408234
Job:6 set1/s1i2.png vs set2/s2i2.png 0.406902
Job:7 set1/s1i2.png vs set2/s2i3.png 0.408173
Job:8 set1/s1i2.png vs set2/s2i4.png 0.407242
Job:5 set1/s1i2.png vs set2/s2i1.png 0.408123
Job:2 set1/s1i1.png vs set2/s2i2.png 0.408835
Job:1 set1/s1i1.png vs set2/s2i1.png 0.408979
Job:9 set1/s1i3.png vs set2/s2i1.png 0.409011
Job:10 set1/s1i3.png vs set2/s2i2.png 0.407391
Job:11 set1/s1i3.png vs set2/s2i3.png 0.408614
Job:12 set1/s1i3.png vs set2/s2i4.png 0.408228
建议3
我前段时间写了一篇关于使用REDIS缓存图像的答案 - 这些答案也可以在小型服务器池中以分布式方式工作。答案是here。
建议4
您可能会发现通过将第二组图像转换为Magick Pixel Cache格式可以获得更好的性能,这样它们就可以被DMA化为内存而不需要每次都进行解码和解压缩。所以你会这样做:
convert image.png image.mpc
它为您提供了ImageMagick可以快速读取的这两个文件。
-rw-r--r-- 1 mark staff 856 16 Jan 12:13 image.mpc
-rw------- 1 mark staff 80000 16 Jan 12:13 image.cache
请注意,我不建议您将图像永久存储为MPC格式,因为它是ImageMagick独有的,并且可以在不同版本之间进行更改。我建议您在每次运行分析运行之前以该格式生成副本。