Page 1 of 1

Mean and SD of opaque pixels

Posted: 2014-02-06T16:53:36-07:00
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 http://www.fmwconcepts.com/imagemagick/ ... 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 ^
  g.png
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:
    Gray:
      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.

Re: Mean and SD of opaque pixels

Posted: 2014-02-06T22:15:21-07:00
by fmw42
Here is an alternate using the method Anthony suggested at http://www.fmwconcepts.com/imagemagick/ ... 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 http://en.wikipedia.org/wiki/Variance


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

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

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

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

Or

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

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

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

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

Note: -function polynomial "1,0,0" computes the square of the image, though perhaps slower than cloning and -compose multiply. see http://www.imagemagick.org/Usage/transf ... polynomial