是否可以在shell脚本中区分灰度和(扫描)单色?

时间:2014-12-17 03:07:07

标签: scripting imagemagick

我想要运行各种IM命令的数千张图像取决于它们属于哪三类:

  • 颜色(通常颜色鲜艳)
  • 灰度(从纸上扫描,"白色"通常有淡黄色调)
  • 单色(扫描,带黄色调,如上所述)

可以从shell脚本中整理出来吗?

颜色示例#1

Color Example #1

灰度示例#1

enter image description here

单色示例#1和#2

enter image description here enter image description here

2 个答案:

答案 0 :(得分:2)

首先:你的问题的标题是误导性的。

  

“是否可以在shell脚本中区分灰度与(扫描)单色?”

直截了当identify告诉颜色空间和位深度

这是误导性的,因为您提供的所有示例图像实际上都在8-bit sRGB颜色空间中:

identify http://i.stack.imgur.com/lygAE.png \
         http://i.stack.imgur.com/H7vBP.png \
         http://i.stack.imgur.com/ZOCTK.png

http://i.stack.imgur.com/lygAE.png=>lygAE.png PNG 236x216 236x216+0+0 8-bit sRGB 127KB 0.000u 0:00.000
http://i.stack.imgur.com/H7vBP.png=>H7vBP.png[1] PNG 259x192 259x192+0+0 8-bit sRGB 86.2KB 0.000u 0:00.000
http://i.stack.imgur.com/ZOCTK.png=>ZOCTK.png[2] PNG 264x179 264x179+0+0 8-bit sRGB 86.7KB 0.000u 0:00.000

如您所见,identify命令(ImageMagick命令套件的一部分)可以轻松地告诉您图像的深度和色彩空间。

带有identify参数的

-format告知特定的图片属性

您可以在{em>'%escapes'中加入-format参数,以便只获取图片的特定属性:

  • f :用于图片文件名
  • d :用于图片的目录组件
  • z :用于图片深度
  • r :用于图像类和色彩空间

所以试试这个:

identify -format "%f %d :   %z %r\n"        \
         http://i.stack.imgur.com/lygAE.png \
         http://i.stack.imgur.com/H7vBP.png \
         http://i.stack.imgur.com/ZOCTK.png

结果:

lygAE.png //i.stack.imgur.com :   8 DirectClass sRGB 
H7vBP.png //i.stack.imgur.com :   8 DirectClass sRGB 
ZOCTK.png //i.stack.imgur.com :   8 DirectClass sRGB 

将一个图像转换为真实单色

现在向您展示一个真正的“单色”图像,让我们相应地转换您的一个样本:

convert                                    \
       -colorspace gray                    \
        http://i.stack.imgur.com/lygAE.png \
       +dither                             \
       -colors 2                           \
       -depth 1                            \
        bmp3:monochrome.bmp

identify -format "%f :  %z %r\n" monochrome.bmp http://i.stack.imgur.com/lygAE.png
  monochrome.bmp :  1 PseudoClass Gray
       lygAE.png :  8 DirectClass sRGB 

以下是各自的图片:

告诉独特颜色的数量

如果你有(如你所有)sRGB色彩空间中的所有图像都具有8位深度,那么理论上,每个图像可以有多达16.777.216(1600万)种颜色(也称为“TrueColor”) 。但是,大多数实际图像并未使用此频谱的全部范围,而“灰色”出现的图像实际上会使用更少数量的图像。

因此,ImageMagick还有另外两个'%escape'来返回有关图像的信息:

  • %k :返回图片中唯一颜色的数量。这是计算的值。 IM必须处理图像并分析它的每个像素才能得到这个数字。

所以这是一个命令:

identify -format "%f -  number of unique colors: %k\n" \
          http://i.stack.imgur.com/lygAE.png           \
          http://i.stack.imgur.com/H7vBP.png           \
          http://i.stack.imgur.com/ZOCTK.png

结果:

lygAE.png -  number of unique colors: 47583
H7vBP.png -  number of unique colors:  7987
ZOCTK.png -  number of unique colors:  5208

正如您所看到的,具有明显着色的图像使用的uniq颜色大约是“灰色”扫描的6倍。

然而,并非如此。例如,请参见此图片:

8 different colors

是颜色,不是吗?

我使用此命令生成它:

convert -size 100x100 \
         xc:red       \
         xc:green     \
         xc:blue      \
         xc:white     \
         xc:black     \
         xc:cyan      \
         xc:magenta   \
         xc:yellow    \
        +append       \
         out.png

您甚至可以通过简单地查看它来计算独特颜色的数量:8。

现在identify告诉了我们什么?

identify \
  -format "%f:\n \
            -- number of unique colors: %k\n \
            -- depth: %z\n \
            -- class/space: %r\n \
            -- image type: %[type]\n" \
   out.png

结果:

out.png:
             -- number of unique colors: 8
             -- depth: 8
             -- class/space: PseudoClass sRGB 
             -- image type: Palette

因此,少量的独特颜色并不一定证明图像是“灰色的”!

你必须稍微使用这些参数,看看你是否能想出一个能够帮助你正确分类现实世界“成千上万张图片”的组合。

也考虑图像统计

借助identify -format %... filename.suffix

,您可以查看更多值
  • %[gamma] :图片伽玛值
  • %[entropy] :已计算:图像熵
  • %[kurtosis] :已计算:图像的峰度值统计
  • %[max] :已计算:图片的最大值统计信息
  • %[mean] :已计算:图片的平均值统计
  • %[min] :已计算:图片的最小值统计
  • %[profile:icc] :ICC个人资料信息
  • %[profile:icm] :ICM个人资料信息

最后提示:查看元数据!

以防您的图像被设备扫描,该设备留下了自己的识别元数据:检查它们!

命令行工具exiftool是一个很好的实用工具。

答案 1 :(得分:2)

我会说色调和饱和度对于彩色图像尤其具有良好的判别力。单色或灰度图像非常不饱和,因此其平均饱和度往往较低,而对于彩色图像则较高。此外,彩色图像的色调(基本上是颜色)在不同颜色之间倾向于变化很大,而色调对于灰色或单色图像往往是相当恒定的值,因此色调的变化量应该是一个很好的衡量标准 - 即标准差。

我们可以使用ImageMagick计算平均饱和度,如下所示:

convert image.png -colorspace HSL -channel S -separate -format "%[mean]" info:

和Hue的标准偏差如下:

convert image.png -colorspace HSL -channel H -separate -format "%[standard-deviation]" info:

所以,如果我们把所有这些放在一个bash脚本中并在你的图像上运行它我们得到这个:

#!/bin/bash
for i in colour.png grey.png mono.png; do
   SatMean=$(convert $i -colorspace HSL -channel S -separate -format "%[mean]" info:)
   HueStdDev=$(convert $i -colorspace HSL -channel H -separate -format "%[standard-deviation]" info:)
   echo $i: Mean saturation: $SatMean, Hue Std-Dev: $HueStdDev
done

<强>输出

colour.png: Mean saturation: 17,807.9, Hue Std-Dev: 16,308.3
grey.png: Mean saturation: 7,019.67, Hue Std-Dev: 2,649.01
mono.png: Mean saturation: 14,606.1, Hue Std-Dev: 1,097.36

它看起来相当不同 - 为了清晰起见,我添加了千位分隔符。这些值的范围基于您的IM量化级别 - 我的是Q16,因此范围是0-65535。

mono grey 区分开来比较困难。基本上,在 mono 图像中,您有一个更加明显的双模态直方图,而在灰色图像中,您有一个更多的连续直方图。我们可以像这样绘制直方图:

convert colour.png histogram:colorhist.png
convert grey.png histogram:greyhist.png
convert mono.png histogram:monohist.png

colour

grey

mono

<强>更新

要区分灰度单声道,我想查看直方图中间的像素,基本上忽略黑色(和黑色附近)和白色(和白人附近)。所以我可以做到这一点,将所有黑人和近黑人和白人以及白人附近设置成全黑:

convert image.png                                \
  -colorspace gray                               \
  -contrast-stretch 1%                           \
  -black-threshold 20%                           \
  -white-threshold 80% -fill black -opaque white \
  out.png

enter image description here

如果我现在克隆该图像并将克隆中的所有像素设置为黑色,那么我可以计算直方图斩波图像与黑色图像之间的差异

convert image.png                                     \
   -colorspace gray                                   \
   -contrast-stretch 1%                               \
   -black-threshold 20%                               \
   -white-threshold 80% -fill black -opaque white     \
   \( +clone -evaluate set 0 \)                       \
   -metric ae -compare -format "%[distortion]" info:

现在,如果我计算图像中的像素总数,我可以推导出中间色调中像素的百分比,并用它来衡量图像是非常灰色还是缺少中间色调。

#!/bin/bash
for i in colour.png grey.png mono.png; do
   SatMean=$(convert $i -colorspace HSL -channel S -separate -format "%[mean]" info:)
   HueStdDev=$(convert $i -colorspace HSL -channel H -separate -format "%[standard-deviation]" info:)
   NumMidTones=$(convert $i -colorspace gray -contrast-stretch 1% -black-threshold 20% -white-threshold 80% -fill black -opaque white \( +clone -evaluate set 0 \) -metric ae -compare -format "%[distortion]" info:)
   NumPixels=$(convert $i -ping -format "%[fx:w*h]" info:)
   PctMidTones=$((NumMidTones*100/NumPixels))
   echo $i: Mean saturation: $SatMean, Hue Std-Dev: $HueStdDev, PercentMidTones: $PctMidTones
done

<强>输出

colour.png: Mean saturation: 17807.9, Hue Std-Dev: 16308.3, PercentMidTones: 70
grey.png: Mean saturation: 7019.67, Hue Std-Dev: 2649.01, PercentMidTones: 39
mono.png: Mean saturation: 14606.1, Hue Std-Dev: 1097.36, PercentMidTones: 27