15 Apr 2011

Practical Algorithms for Image Analysis – Post #1

Blog 1 Comment

I picked up this book, randomly, and I’m enjoying working my way through it. It starts off with the fundamentals, things like scaling and rotating images, but then quickly moves on to more complex stuff.

I thought it might be a fun challenge to work through the book in Flash and Actionscript, not by just porting over the existing code examples, but by analyzing the text and coming up with my own implementation from scratch. Think I’ll learn more from rolling my own than if I’m just replacing calls for calls.

I’m especially excited for everyone to constantly remind me that Flash has helpfully taken care of the whole “rotating an image” thing. I’m definitely not going to be the first, and I most assuredly won’t be the best, but doggone it, it’ll be fun to try.

First example starts easy enough: Histograms! Specifically just, like, looking at them.

So I made my own histogram visualizer, based loosely on the graphs I use for the Pulse project. Click through and I’ll walk you through it.

Chapter 2.1: Intensity Histogram: Global Features

The first lessons are about how to look at the histogram of an image and make some decision about it based just on that.  Things like, if there are two strong peaks in the histogram, they’re probably the foreground and the background.  Or if there’s there’s only one bin filled, then the image is going to be just an entirely featureless gray.

This movie requires Flash Player 9

protected function CreateHistogram(input:Bitmap,scale:Number=1):Bitmap {
	var HistogramData:Vector.<Vector.<Number>> = input.bitmapData.histogram();
	var maxHeight:int = 100;
	var channelCounter:int = 1;
	var Histogram:Bitmap = new Bitmap(new BitmapData(256,maxHeight, false,0x00000000));
	Histogram.bitmapData.lock()
	for (var i:int = 0; i < 4; ++i) {
		var oneChannel:BitmapData = new BitmapData(256,maxHeight,false,0x00000000);
		for (var j:int = 0; j < 256; ++j) {
			var height:int = Math.min(maxHeight,(HistogramData[i][j])/scale);
			oneChannel.fillRect(new Rectangle(j,maxHeight-height,1,height),0xFFFFFFFF);
		}
		Histogram.bitmapData.copyChannel(oneChannel,new Rectangle(0,0,256,maxHeight),new Point(),channelCounter,channelCounter);
		channelCounter *= 2;
	}
	oneChannel.dispose();
	Histogram.bitmapData.unlock();
	return Histogram;
}

First I take a shortcut and use the built-in BitmapData.histogram() function to actually get the data. It gives you back a 4-row Vector, one each for red/green/blue/alpha, each with 256 bins that count up the sum total of the pixels of each of the 256 possible brightness levels for that channel. Then I create the output Bitmap and leave it blacked out.

Then I loop through the histogram data by channel (skipping the alpha because, whatever) and for each of the brightness levels, I draw a single-pixel column for its height onto a temporary BitmapData object, using 0xFFFFFFFF. Then once I’ve gone through all 256 bins, I use BitmapData.copyChannel() to copy only a single color channel over to the final Histogram object. I’ve seen examples that use all sorts of tricky color blending, but whatevs. Pretty sure my way’s easier.

So there you have it. Further steps are going to expand on this, or at least help you make decisions based on how the histogram is shaped. More to follow.

One Response to “Practical Algorithms for Image Analysis – Post #1”

  1. 2.1.1 Histogram Expansion says:

    [...] I’m working my way through the book Practical Algorithms Image Analysis, and documenting my progress here. I remain WELL AWARE that I’m reinventing the wheel, and [...]

Leave a Reply