Fitting gaussian to image histogram

by makc3d
♥0 | Line 100 | Modified 2010-10-14 07:44:20 | MIT License
play

ActionScript3 source code

/**
 * Copyright makc3d ( http://wonderfl.net/user/makc3d )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/3NvK
 */

package {
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.ColorMatrixFilter;
	import flash.geom.Rectangle;
	import flash.media.Camera;
	import flash.media.Video;
	/**
	 * Fitting gaussian to image histogram.
	 * @author makc
	 */
	[SWF(width=465,height=465,backgroundColor='#003F00')]
	public class BellCurveFitting extends Sprite {
		public var video:Video;
		public var frame:BitmapData;
		public var grayscale:ColorMatrixFilter;
		public var rectangle:Rectangle;
		public var rectSprite:Sprite;
		public function BellCurveFitting () {
			video = new Video; addChild (video);
			video.attachCamera (Camera.getCamera ());
			frame = new BitmapData (320, 240, false, 0);
			grayscale = new ColorMatrixFilter (
				[ 0.299, 0.587, 0.114, 0, 0,
				  0.299, 0.587, 0.114, 0, 0,
				  0.299, 0.587, 0.114, 0, 0,
				  0,     0,     0,     1, 0 ]
			);
			rectangle = frame.rect;
			addChild (rectSprite = new Sprite);
			stage.addEventListener (Event.ENTER_FRAME, loop);
			stage.addEventListener (MouseEvent.MOUSE_DOWN, rectStart);
		}
		public function loop (e:Event):void {
			frame.draw (video);
			frame.applyFilter (frame, frame.rect, frame.rect.topLeft, grayscale);
			var h:Vector.<Number> = frame.histogram (getPositiveRect (rectangle)) [0];
			// try lloyd-like process
			var mean:Number = 128, sigma2:Number = 64;
			for (var i:int = 0; i < 7; i++) {
				// calculate raw moments
				var m1:Number = 0, m2:Number = 0, n:Number = 1;
				var from:int = Math.max (0, mean - 2 * sigma2);
				var to:int = Math.min (256, mean + 2 * sigma2);
				for (var j:int = from; j < to; j++) {
					var j_hj:Number = j * h [j];
					m1 += j_hj;
					m2 += j_hj * j;
					n += h [j];
				}
				m1 /= n; m2 /= n;
				// re-estimate
				mean = m1; sigma2 = m2 - m1 * m1;
			}
			// find max
			var h_max:Number = 0;
			for (i = 0; i < 256; i++) {
				if (h [i] > h_max) h_max = h [i];
			}
			// graph
			graphics.clear ();
			for (i = 0; i < 256; i++) {
				var v:int = 200 * h [i] / h_max;
				graphics.beginFill (0x10101 * i);
				graphics.drawRect (i, 465 - v, 1, v);
			}
			graphics.endFill ();
			graphics.lineStyle (1, 0xFF0000);
			var area:Number = Math.abs (rectangle.width * rectangle.height);
			for (i = 0; i < 256; i++) {
				var f:Number = area * Math.exp ( -(i - mean) * (i - mean) / (2 * sigma2)) / Math.sqrt (2 * Math.PI * sigma2);
				v = 200 * f / h_max;
				graphics [(i < 1) ? "moveTo" : "lineTo"] (i, 465 - v);
			}
			// rect
			rectSprite.graphics.clear ();
			rectSprite.graphics.lineStyle (1, 0xFF0000);
			rectSprite.graphics.drawRect (rectangle.x, rectangle.y, rectangle.width, rectangle.height);
		}
		public function rectStart (e:MouseEvent):void {
			rectangle.x = Math.min (320, Math.max (0, mouseX)); rectangle.width = 0;
			rectangle.y = Math.min (240, Math.max (0, mouseY)); rectangle.height = 0;
			stage.addEventListener (MouseEvent.MOUSE_MOVE, rectDrag);
			stage.addEventListener (MouseEvent.MOUSE_UP, rectEnd);
		}
		public function rectDrag (e:MouseEvent):void {
			rectangle.right = Math.min (320, Math.max (0, mouseX));
			rectangle.bottom = Math.min (240, Math.max (0, mouseY));
		}
		public function rectEnd (e:MouseEvent):void {
			stage.removeEventListener (MouseEvent.MOUSE_MOVE, rectDrag);
			stage.removeEventListener (MouseEvent.MOUSE_UP, rectEnd);
			rectangle = getPositiveRect (rectangle);
		}
		public function getPositiveRect (rectangle:Rectangle):Rectangle {
			var r:Rectangle = rectangle;
			if ((r.width < 0) || (r.height < 0)) {
				r = new Rectangle (
					Math.min (rectangle.x, rectangle.right),
					Math.min (rectangle.y, rectangle.bottom),
					Math.abs (rectangle.width),
					Math.abs (rectangle.height)
				);
			}
			return r;
		}
	}
}

Forked