How to get image red green blue standard deviation values from gm identify -verbose?

67 views Asked by At

I am trying to get the values given for Standard Deviation in the Red, Green, and Blue channels that you can see in gm identity -verbose but they're not listed in the -format options.

How can I get these from the commandline?

A workaround to list the values using PHP:

    $raw = `gm identify -verbose {$file}|grep -E -e '^ +(Standard Deviation): *[^b]*$'`;
    preg_match_all("/(?<=Standard Deviation:)(?: +)([\d\.]+)/", $raw, $matches);
    $ret = [$matches[1][0], $matches[1][1], $matches[1][2]];

this is the output from gm identify -verbose. Example we need the values from properties under Channel Statistics:

Image: /.../.../img.jpg
  Format: JPEG (Joint Photographic Experts Group JFIF format)
  Geometry: 1064x1600
  Class: DirectClass
  Type: true color
  Depth: 8 bits-per-pixel component
  Channel Depths:
    Red:      8 bits
    Green:    8 bits
    Blue:     8 bits
  Channel Statistics:
    Red:
      Minimum:                     0.00 (0.0000)
      Maximum:                   255.00 (1.0000)
      Mean:                      132.32 (0.5189)
      Standard Deviation:         45.92 (0.1801)
    Green:
      Minimum:                     0.00 (0.0000)
      Maximum:                   255.00 (1.0000)
      Mean:                      104.17 (0.4085)
      Standard Deviation:         55.13 (0.2162)
    Blue:
      Minimum:                     0.00 (0.0000)
      Maximum:                   255.00 (1.0000)
      Mean:                      103.61 (0.4063)
      Standard Deviation:         55.71 (0.2185)
  Filesize: 452.0Ki
  Interlace: No
  Orientation: Unknown
  Background Color: white
  Border Color: #DFDFDF
  Matte Color: #BDBDBD
  Page geometry: 1064x1600+0+0
  Compose: Over
  Dispose: Undefined
  Iterations: 0
  Compression: JPEG
  JPEG-Quality: 95
  JPEG-Colorspace: 2
  JPEG-Colorspace-Name: RGB
  JPEG-Sampling-factors: 2x2,1x1,1x1
  Signature: 136912e901ae9314fd683868418cae1f5d838c6891ddd8c13ce28057fb39365a
  Tainted: False
  User Time: 0.010u
  Elapsed Time: 0m:0.014459s
  Pixels Per Second: 112.3Mi
3

There are 3 answers

9
The fourth bird On

Using GNU Grep, where -o prints only the matched parts and -P for Perl-compatible regular expressions:

grep -oP "\bStandard Deviation:\h+\K\d[\d.]*"

The pattern matches:

  • \bStandard Deviation: Match literally starting with a word boundary
  • \h+ Match 1+ horizontal whitespace characters
  • \K Forget what is matched so far
  • \d[\d.]* Match a single digit followed by optional digits or dots (or [\d.]+ but note that it could also only match dots

You might also use [\d.]+ but that could also match dots only. Using \.?\d[\d.]* could match an optional leading dot, or a more strict format not allowing consecutive dots \.?\d+(?:\.\d+)*\b

See the regex matches.


Or an alternative using sed

sed -n 's/^[[:space:]]\+Standard Deviation:[[:space:]]\+\([[:digit:]][[:digit:].]*\).*/\1/p'
0
yarns On

The solution that worked for me on macos was based on the answer from @thefourthbird. I couldn't install ggrep but had success with pcre2grep from port (macports).

gm identify -verbose img.jpg|\
pcre2grep -o --allow-lookaround-bsk "\b(?:Minimum|Maximum|Mean|Standard Deviation): +\d+\.\d+ \(\K\d+\.\d+"

the --allow-lookaround-bsk option in pcre2grep enabled the \K symbol which was needed to discard the content before each value.

The result is the extracted values I can use from the example in the question:

0.0000
1.0000
0.5189
0.1801
0.0000
1.0000
0.4085
0.2162
0.0000
1.0000
0.4063
0.2185

Note: the number of values varies.

  • monochrome images only have 1 channel
  • color images (see example) have 3 for red, green, and blue.
  • each channel will always have 4 values: Minimum|Maximum|Mean|Standard Deviation
0
Mark Setchell On

If using ImageMagick as opposed to GraphicsMagick is an option - see What's the Difference Between ImageMagick and GraphicsMagick? - then you have more flexibility.

You can print like this:

magick result.png -format "%[fx:standard_deviation.r]\n%[fx:standard_deviation.g]\n%[fx:standard_deviation.b]" info:   
    
0.399446
0.319672
0.213623                

Or you can get ImageMagick to output in JSON and use jq to parse out the fields you want:

magick result.png json: | jq -r '.[].image.channelStatistics | "\(.red.standardDeviation) \(.green.standardDeviation) \(.blue.standardDeviation)"'

101.859 81.5164 54.4738