在两个目录中搜索具有不同文件名的类似图像

时间:2012-09-29 04:20:56

标签: image graphics imagemagick

我有2个包含大量图片的目录,比如: color / gray / 。在 color / 中,图像命名为:image1.png image2.png等。

我知道 gray / 包含相同的图像,但是灰度级,文件名和文件顺序不同(例如:file_01.png,但这不是相同的图像as image1.png)。

是否可以对两个目录中的图像进行比较,并使用 gray / 文件将 color / 文件复制到结果 /目录名字?

示例:

directory        | directory           | directory
   "color/"      |     "gray/"         |      "results/" 
(color images)   | (grayscale images)  | (color images with gray-scale names)   
-----------------+---------------------+----------------------------------------
color/image1.png | gray/file324.png    | results/file324.png  (in color: ==>
                                       | this and image1.png are the same image)

我希望这不是很混乱,但我不知道如何更好地解释它。

我尝试过使用imagemagick,似乎-compare选项可以用于此,但是我无法创建一个bash脚本或者做得很好的东西。

另一种说法:我希望使用正确匹配的color/*.jpg名称将所有results/*.jpg复制到gray/*.jpg文件夹中。

编辑(一些注释): 这三张图片的大小和内容都是IDENTICAL。唯一的区别是两个是彩色的,一个是灰度的。当然还有文件的名称。 2.我上传了一个带有一个样本图像及其当前名称的zip文件(文件夹“img1”颜色文件夹和文件夹“img2”灰度文件夹)和预期结果(“img3”结果文件夹),这里:http://www.mediafire.com/?9ug944v6h7t3ya8

3 个答案:

答案 0 :(得分:4)

如果我正确理解了要求,我们需要:

  • 找到名为XYZ的每个灰度图像,该图像位于文件夹 gray / ...
  • ...名为ABC的匹配颜色图片位于 color / 文件夹中......
  • ...将ABC复制到新名称XYZ
  • 下的文件夹 results /

所以我建议的基本算法就是:

  1. 将文件夹 color / 中的所有图像转换为灰度,并将结果存储在 gray-reference / 文件夹中。保留原始名称:

    mkdir gray-reference
    convert  color/img123.jpg  -colorspace gray  gray-reference/img123.jpg
    
  2. 对于 reference / 中的每个灰度图像,与 gray / 文件夹中的每个灰度图像进行比较。如果找到匹配项,请将相同名称的相应图像从 color / 复制到 results / 。一个可能的比较命令创建了差异的直观表示:

    compare  gray-reference/img123.jpg  gray/imgABC.jpg  -compose src delta.jpg
    
  3. 真正的技巧是两个灰度图像的比较(如步骤2)。 ImageMagick有一个方便的命令,可以逐个像素地比较两个(相似的)图像,并将结果写入一个' delta'图片:

    compare  reference.png  test.png  -compose src  delta.png
    

    如果比较适用于彩色图像,请在增量图像...

    • ...每个相等的像素都显示为白色,而......
    • ...每个不同的像素都会以高亮颜色显示(默认为红色)。

    有关此技术的说明示例,另请参阅我的回答"ImageMagick: 'Diff' an Image"

    如果我们直接逐个像素地比较灰度图像和彩色图像,我们当然会发现几乎每个像素都不同(导致全红色" delta&#34 ;图片)。因此,我从上面的步骤1提出的建议首先将彩色图像转换为灰度。

    如果我们比较两个灰度图像,则生成的增量图像也是灰度图像。因此,默认的高亮颜色不能为红色。我们最好把它设置为黑色'为了更好地看待它。

    现在,如果我们当前的颜色灰度转换会导致“不同”的颜色变化。比现有灰度图像具有的灰度级(由于应用了不同的颜色配置文件,我们当前生产的灰度可能比现有的灰度图像略微更浅或更暗),它可能仍然发生我们的delta图片全部是 - " red"或者更确切地说是全高亮颜色。但是,我用你的样本图像测试了这个,结果很好:

     convert  color/image1.jpg  -colorspace gray  image1-gray.jpg  
     compare                  \
        gray/file324.jpg      \
        image1-gray.jpg       \
       -highlight-color black \
       -compose src           \
        delta.jpg
    

    delta.jpg 由98%的白色像素组成。我不确定您的数千张灰度图像中的所有其他图像是否在从彩色原稿中派生时使用相同的设置。因此,在运行compare命令时,我们会添加一个小的模糊因子,当比较2个像素时,这会允许颜色出现一些偏差:

    compare  -fuzz 3%  reference.png  test.png  -compose src  delta.png
    

    由于这个算法要被执行数千次(可能是数百万次,考虑到你所谈论的图像数量),我们应该考虑一些性能,我们应该计算compare的持续时间。命令。这尤其令人担忧,因为您的样本图像相当大(3072x2048像素--6兆像素),并且比较可能需要一段时间。

    我在MacBook Pro上的计时结果如下:

    time (convert  color/image1.jpg  -colorspace gray  image1-gray.jpg ;
          compare                   \
             gray/file324.jpg       \
             image1-gray.jpg        \
            -highlight-color black  \
            -fuzz 3%                \
            -compose src            \
             delta100-fuzz.jpg)
    
      real  0m6.085s
      user  0m2.616s
      sys   0m0.598s
    

    6秒:1将大型彩色图像转换为灰度,再加上1个两个大灰度图像的比较。

    你谈到了数千张图片'。假设3000张图像,基于此时间,所有图像的处理将需要(3000*3000)/2比较(450万)和(3000*3000*6)/2秒(2700万秒)。这总共需要312天才能完成所有比较。太长了,如果你问我。

    我们可以做些什么来改善表现?

    嗯,我的第一个想法是缩小图像的大小。如果我们比较较小的图像而不是3072x2048尺寸的图像,则比较应该更快地返回结果。 (但是,我们还会花费额外的时间来首先缩小我们的测试图像 - 但希望比以后在比较较小图像时节省的时间少得多:

    time (convert color/image1.jpg  -colorspace gray  -scale 6.25%  image1-gray.jpg  ;
          convert gray/file324.jpg                    -scale 6.25%  file324-gray.jpg ;
          compare                  \
             file324-gray.jpg      \
             image1-gray.jpg       \
            -highlight-color black \
            -fuzz 3%               \
            -compose src           \
             delta6.25-fuzz.jpg)
    
       real  0m0.670s
       user  0m0.584s
       sys   0m0.074s
    

    那好多了!我们削减了近90%的处理时间,如果您使用MacBook Pro,这可以在35天内完成工作。

    改进是合乎逻辑的:通过将图像尺寸减小到原始尺寸的6.25%,所得图像仅为192x128像素 - 从600万像素减少到24.5万像素,比率为256:1。

    注意: -thumbnail-resize参数的工作速度比-scale快一点。但是,这种速度增加是一种交易 - 质量损失。质量损失可能会使比较更不可靠......)

    我们可以告诉ImageMagick打印出一些统计数据,而不是从比较的图像中创建可视检查的增量图像。要获取不同像素的数量,我们可以使用AE指标。该命令及其结果如下:

    time (convert color/image1.jpg -colorspace gray -scale 6.25% image1-gray.jpg  ;
         convert gray/file324.jpg                   -scale 6.25% file324-gray.jpg ;
         compare -metric AE  file324-gray.jpg image1-gray.jpg -fuzz 3% null: 2>&1 )
    0 
    
      real  0m0.640s
      user  0m0.574s
      sys   0m0.073s
    

    这意味着我们有0个不同的像素 - 这是我们可以在shell脚本中直接使用的结果!

    Shell脚本的构建块

    以下是shell脚本进行自动比较的构建块:

    1. 转换彩色图像' color /'目录到灰度级,将它们缩小到6.25%并将结果保存在" reference-color /'目录:

      # Estimated time required to convert 1000 images of size 3072x2048:
      #   500 seconds
      mkdir reference-color
      for i in color/*.jpg; do
          convert  "${i}"  -colorspace gray  -scale 6.25%  reference-color/$(basename "${i}")
      done
      
    2. 缩小' grey /'目录并将结果保存在< reference-grey /'目录:

      # Estimated time required to convert 1000 images of size 3072x2048:
      #    250 seconds
      mkdir reference-gray
      for i in gray/*.jpg; do
          convert  "${i}"  -scale 6.25%  reference-gray/$(basename "${i}")
      done
      
    3. 比较目录中的每张图片' reference-grey /'使用目录中的图像' reference-color'直到找到匹配项:

      # Estimated time required to compare 1 image with 1000 images:
      #    300 seconds
      # If we have 1000 images, we need to conduct a total of 1000*1000/2
      # comparisons to find all matches;
      #    that is, we need about 2 days to accomplish all.
      # If we have 3000 images, we need a total of 3000*3000/2 comparisons
      # to find all matches;
      #    this requires about 20 days.
      #
      for i in reference-gray/*.jpg ; do
      
          for i in reference-color/*.jpg ; do
      
              # compare the two grayscale reference images
              if [ "x0" == "x$(compare  -metric AE  "${i}"  "${j}" -fuzz 3%  null: 2>&1)" ]; then
      
                  # if we found a match, then create the copy under the required name
                  cp color/$(basename "${j}"  results/$(basename "${i}") ;
      
                  # if we found a match, then remove the respective reference image (we do not want to compare again with this one)
                  rm -rf "${i}"
      
                  # if we found a match, break from within this loop and start the next one
                  break ;
      
              fi
      
          done
      
      done
      
    4. 警告:不要盲目依赖这些积木。他们没有经过考验。我没有可用于测试这个的多个合适图像的目录,我不想仅为此练习创建一个。谨慎行事!

答案 1 :(得分:2)

您应该尝试使用感知哈希技术(例如pHash)为您的具体数据提供一些好的结果。

感知哈希将为您提供可靠的相似性度量,因为基础算法足够强大,可以考虑更改/转换,例如对比度调整或不同的压缩/格式 - 这与标准加密哈希函数(如MD5)不同

此外,您可以在自己的图像上使用方便的基于网络的demo interface验证pHash是否有效。

答案 2 :(得分:1)

经过一些调整和摆弄-fuzz选项后,Kurt的解决方案非常有用! :)最终运作良好的-fuzz的最终值是50%!我尝试了3次,10次,19次,20次,24次,25次,30%和40%没有成功。可能是因为灰色图像是先前用不同的方法生成的,所以灰色是不同的。此外,所有图像都具有不同的大小,其中一些相对较小,因此按百分比的缩放方法会产生不良结果。我使用了-resize 200x,所以所有的参考图像大小都差不多,最后这就是我使用的bash脚本:

    # this bash assumes the existence of two dirs: color/ and gray/ 
    # each one with images to compare

    echo Starting...
    echo Checking directories...
    if [ ! -d color ]; then
        echo Error: the directory color does not exist!
        exit 1;
    fi
    if [ ! -d gray ]; then
        echo Error: the directory gray does not exist!
        exit 1;
    fi

    echo Directories exist. Proceeding...

    mkdir reference-color
    echo creating reference-color...
    for i in color/*.png; do
        convert  "${i}"  -colorspace gray  -resize 200x  reference-color/$(basename "${i}")
    done
    echo reference-color created...

    mkdir reference-gray
    echo creating reference-gray...
    for i in gray/*.png; do
        convert  "${i}"  -resize 200x  reference-gray/$(basename "${i}")
    done
    echo reference-gray created...

    mkdir results
    echo created results directory...

    echo ...ready.

    echo "-------------------------"
    echo "|  starting comparison  |"
    echo "-------------------------"

    for i in reference-gray/*.png; do
        echo comparing image $i 

        for j in reference-color/*.png; do

            # compare the two grayscale reference images

            if [ "x0" == "x$(compare  -metric AE "${i}"  "${j}" -fuzz 50% null: 2>&1)" ]; then

                # if we found a match, then create the copy under the required name
                echo Founded a similar one. Copying and renaming it...
                cp color/$(basename "${j}")  results/$(basename "${i}")

                # if we found a match, then remove the respective reference image (we do not want to compare again with this one)
                echo Deleting references...
                rm -rf "${i}"
                rm -rf "${j}"
                echo "--------------------------------------------------------------"

                # if we found a match, break from within this loop and start the next one
                break ;

            fi

        done

    done
    echo Cleaning...
    rm -rf reference-color
    rm -rf reference-gray
    echo Finished!

时间测量是(对于180张图片,在cygwin中使用imagemagick,所以在本机linux imagemagick中可能更好,我还不知道):

real    5m29.308s
user    2m25.481s
sys     3m1.573s

如果有兴趣的话,我上传了一个包含脚本和测试图像集的文件。 http://www.mediafire.com/?1ez0gs6bw3rqbe4(以7z格式压缩)

再次感谢!