Chernoff Face

Author

S. Dickson
Wolfram Research, Inc.
1993

This notebook downloaded from http://mathworld.wolfram.com/notebooks/Statistics/ChernoffFace.nb.

For more information, see Eric's MathWorld entry http://mathworld.wolfram.com/ChernoffFace.html.

©2010 Wolfram Research, Inc. except for portions noted otherwise

Author

Example

Discussion

Human beings have a highly developed ability to perceive subtle changes in facial expressions.  Even in a very simplified drawing of a face a small difference is registered as a different emotion.  Some have proposed applying this ability to pattern recognition in lists of large dimensional data.

The function face defined in the Implementation section below produces a simplified drawing of a face.  It takes a list of 10 numbers as an argument.  Each number must be between 0 and 10 and controls a part of the face.  For example,  the first argument controls the shape of the head, the second argument controls the size of the eyes, etc.  Each face thus encodes or represents 10 numerical values, or alternatively, a point in 10-dimensional space.  Assuming that an integer difference is the threshold of human discrimination, there are 10^10 different faces available.

The graphic above was generated using 9 randomly generated lists, each containing 10 numbers.

More Examples

After you have evaluated the input cells in the Implementation section below, try evaluating the next  two samples.

Show[face[{7, 7, 3, 2, 5, 4, 5, 10, 5, 0}] ]

Show[face[{4, 9, 5, 5, 3, 7, 5, 2, 7, 3}] ]

The following cell defines a function which uses 10 randomly-selected numbers to generate one of 10^10 unique faces.

rpix := face[Table[Random[Real , {0, 10}], {10}]]

Each time the next cell is evaluated it will produce a different random array of faces. The picture at the top of the Notebook was one such example.

Show[GraphicsArray[ Table[rpix, {3}, {3}]]]

Implementation

Off[General::spell1]

face::usage = "face[{headecc_, eyesize_, eyespacing_, 
		eyeeccent_, pupsize_, browslant_, nozesize_,
		mouthshape_, mouthsize_, mouthopening_}]";

face[{headecc_, eyesize_, eyespacing_, eyeeccent_, 
	  pupsize_, browslant_, nozesize_, mouthshape_,
	  mouthsize_, mouthopening_}] :=
    Graphics[Flatten[
       {head[headecc],
        eyes[eyesize, eyespacing, eyeeccent, 
        	 pupsize],
        brows[browslant], nose[nozesize],
        mouth[mouthshape, mouthsize, mouthopening]}], 
                    AspectRatio -> Automatic,  
                    PlotRange-> {{-1.5, 1.5}, 
                    			 {-1.5, 1.5}}]

head[eccent_] := Block[
 		{xrad = 1 + (eccent - 5) / 25, 
  		 yrad = 1 - (eccent - 5) / 25},
         	Circle[{0, 0}, (1 + Abs[eccent - 5]/20)
         	    {xrad, yrad}]
         	          ]

eyes[size_, spacing_, eccent_, pupsize_] := Block[
        {xcenter = (1/3) + (spacing - 5) / 30,
         xrad = (1/6) + ((size - 5) + (eccent - 5)) 
         				  / 70,
         yrad = (1/6) + ((size - 5) - (eccent - 5)) 
         				  / 70},
  {Circle[{xcenter, 1/3},  {xrad, yrad}],
    PointSize[(pupsize + 1) / 200], 
    Point[{xcenter, 1/3}],
    Circle[{-xcenter, 1/3},  {xrad, yrad}],
    PointSize[(pupsize + 1) / 200], 
    Point[{-xcenter, 1/3}]}
                                                  ]

brows[slant_] :=  Block[
       {xstart = (1/3) - (1/6) Cos[(slant - 5) Pi 
       							    / 20],
        ystart = (2/3) - (1/6) Sin[(slant - 5) Pi 
        							/ 20],
        xend = (1/3) + (1/6) Cos[(slant - 5) Pi 
        						  / 20],
        yend =  (2/3) + (1/6) Sin[(slant - 5) Pi 
        						   / 20]},
    {Line[{{xstart, ystart}, {xend, yend}}],
     Line[{{-xstart, ystart}, {-xend, yend}}]}
                       ]

nose[size_] := Block[
        {scale = 1 + (size - 5) / 13},
 Line[scale {{0, 1/6}, {-1/6, -1/6}, 
 			 {1/6, -1/6}, {0, 1/6}}]
                    ]

mouth[shape_, size_, opening_] := Block[
  {fx, gx, xstart, xend, ystart, ymin, ymax, xstep },
 xstart = -1/3 - (size - 5) / 15; 
 xend = 1/3 + (size - 5) / 15;
 ystart = -1/2 + (shape - 5) * size / 150;
 ymax = -1/2 + (.9 opening - 1) / 27;
 ymin = -1/2 - (.9 opening - 1) / 30;
 fx = Fit[{{xstart, ystart}, {0, ymax}, 
 		   {xend, ystart}}, {1, x, x^2}, x];
 gx = Fit[{{xstart, ystart}, {0, ymin},
 		   {xend, ystart}}, {1, x, x^2}, x];
 xstep = (xend - xstart) / 10;
    {Line[Table[{x, fx}, {x, xstart, xend, xstep}]],
     Line[Table[{x, gx}, {x, xstart, xend, xstep}]]}
                                        ]

On[General::spell1]

Credits

By S. Dickson after H. Chernov.