Imagemagick C ++:减少内存使用量

时间:2016-01-14 14:16:06

标签: c++ image imagemagick

我有一个用例,我想交叉比较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()

谢谢!

1 个答案:

答案 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独有的,并且可以在不同版本之间进行更改。我建议您在每次运行分析运行之前以该格式生成副本。