Mean and SD of opaque pixels

Discuss digital image processing techniques and algorithms. We encourage its application to ImageMagick but you can discuss any software solutions here.
Posts: 13034
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Mean and SD of opaque pixels

Post by snibgo »

As part of general photographic processing with masks, I wanted to find the mean and standard deviation of the opaque pixels in an image. Here are two methods.

The first extracts the opaque pixels into a new image, then uses simple IM facilities on that new image. The new image has dimensions (n)x1 where (n) is the number of opaque pixels.

An alternative method is to use a single (but complex) convert command. This is inspired by fmw42's ... shape_mean . It implements the formula: SD = sqrt (average ((u-umean)^2)). Windows syntax.

Code: Select all

convert ^
  %INFILE% ^
  -write mpr:TRANS ^
  -format "raw mean: %%[fx:mean]\nraw SD: %%[fx:standard_deviation]\n" -write info: ^
  ( +clone ^
    -scale "1x1^!" ^
    -alpha off ^
    -format "mean of opaque: %%[fx:u]\n" ^
    -write info: ^
    -write mpr:MEAN ^
    +delete ^
  ) ^
  ( +clone ^
    -tile mpr:MEAN -draw "color 0,0 reset" ^
  ) ^
  -compose Difference -composite ^
  -evaluate Pow 2 ^
  mpr:TRANS ^
  -compose CopyOpacity -composite ^
  -scale "1x1^!" ^
  -alpha off ^
  -format "SD of opaque: %%[fx:sqrt(u)]\n" info:
We can compare the methods. Sample image, a circle with grayscale gradient, against a transparent background:

Code: Select all

convert ^
  -size 200x300 gradient: -rotate 90 ^
  ( +clone -fill Black -colorize 100 ^
    +antialias ^
    -fill White -draw "circle 100,100 50,100" ) ^
  -alpha off ^
  -compose CopyOpacity -composite ^
Extracting the opaque pixels into another image:

Code: Select all

  Geometry: 8021x1+0+0
  Units: Undefined
  Type: Grayscale
  Base type: Grayscale
  Endianess: Undefined
  Colorspace: Gray
  Depth: 16-bit
  Channel depth:
    gray: 16-bit
  Channel statistics:
      min: 10959 (0.167224)
      max: 32877 (0.501671)
      mean: 21918.1 (0.334448)
      standard deviation: 5537.44 (0.0844959)
The single convert command above:

Code: Select all

raw mean: 0.5
raw SD: 0.289639
mean of opaque: 0.334447
SD of opaque: 0.0845058
The difference in SD is slightly over 1 part in 10,000, which is close enough for me.

(Fred: feel free to add this to your tidbits page, if you want.)

EDIT: removed a debugging "-write mean.png" from the single-command convert.

EDIT2: if the input image is fully opaque for the single-command convert, the "CopyOpacity" is wrong so the "SD of opaque" is wrong. If "convert %INFILE% -format "%[opaque]" info:" returns "true", don't use this to find the SD of opaque pixels.
snibgo's IM pages:

User avatar
Posts: 26383
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Mean and SD of opaque pixels

Post by fmw42 »

Here is an alternate using the method Anthony suggested at ... shape_mean where scaling to 1 pixel ignores the transparent pixels to compute the mean value. I use it with the formula for the variance and the fact that std=sqrt(variance); namely, std = sqrt ( ave(x^2) - ave(x)^2 ), where ave=mean. see

meanx=`convert g.png -scale 1x1! -format "%[fx:mean]" info:`

meanx2=`convert g.png -function polynomial "1,0,0" -scale 1x1! -format "%[fx:mean]" info:`

convert xc: -format "%[fx:quantumrange*sqrt($meanx2 - $meanx*$meanx)]" info:

convert xc: -format "%[fx:sqrt($meanx2 - $meanx*$meanx)]" info:


meanx=`convert g.png -scale 1x1! -format "%[mean]" info:`

meanx2=`convert g.png -function polynomial "1,0,0" -scale 1x1! -format "%[mean]" info:`

convert xc: -format "%[fx:sqrt(quantumrange*$meanx2 - $meanx*$meanx)]" info:

convert xc: -format "%[fx:sqrt(quantumrange*$meanx2 - $meanx*$meanx)/quantumrange]" info:

Note: -function polynomial "1,0,0" computes the square of the image, though perhaps slower than cloning and -compose multiply. see ... polynomial