FLARM and Dependency Injection

I’ve been taking a look at the latest FLAR Manager code with a view to implementing the histogram bias generation for adaptive thresholding I’ve written about previously. Now Eric’s separated out the threshold algorithm, that’s been made easier to achieve without worrying about future changes to the code base.

Eric’s implemented a nice dependency injection method where you declare the class name of the algorithm you plan to use in the config XML and the manager uses flash.utils.getDefinitionByName() to create it. As long as you implement the interface class, everything should work.

The one downside is that you need to define an object of the class you intend to use somewhere in the manager or the class won’t get included in the swf and you’ll get a runtime error when you try and create it.

It would be nice if you could remove any knowledge of the threshold class implementations from the manager source and just use configuration.

I knew Spring would need to do something like this which lead me to this. I decided to try implementing the resource bundle solution.

Here’s what I did:

  • create a locale/en_US folder in my project
  • create a classreferences.properties file in that folder
  • put the following lines in that .properties file:

#locale/en_US/classreferences.properties
Class1 = ClassReference("com.transmote.flar.utils.threshold.DrunkWalkThresholdAdapter") Class2 = ClassReference("com.transmote.flar.utils.threshold.HistogramThresholdAdapter") Class3 = ClassReference("com.transmote.flar.utils.threshold.DrunkWalkHistoThresholdAdapter") Class4 = ClassReference("com.transmote.flar.utils.threshold.IntegralImageThresholdAdapter")
(basically all the threshold adapters)

  • add -source-path locale/{locale} to my compiler additional options (locale defaults to en_US)
  • add the following to FLARManager.as at the Class level:
  • [ResourceBundle("classreferences")]
    private var _classReferences:ResourceBundle;

and now I can swap in whatever adapter I want in the xml config and it gets picked up. I like this solution because it keeps the FLARManager ignorant of the various adapters that are available – as long as you update the resource file, it’ll work – no need to include the adapter classes or create dummy variables for each of them.

The downside is, you’re creating a bigger swf file as you’re including classes you won’t use and you have to do more initial setup.

I’ll post the histogram based class I came up with next.

More Augmented Reality with FLARM

I finally got a chance to work on my idea of automating the adaptive threshold bias by looking at the bitmap data coming in. Basically, you want to set the bias -ve for a dark scene and positive for a lighter scene. What I came up with was using the histogram() method of the bitmapData class and summing the lowest 20 values for the dark number and the highest 20 for the light. Comparing these then tells you if the scene is light or dark. I decided to make the assumption that each colour channel would be roughly even so I only worked on the green channel but it would be trivial to expand it for all three.

I tried timing it getting Date() at the start and end of the function but it always comes back 0 so we can say it takes < 1millisecond.

I have some trace statements in too to check the results it’s coming back with but those were commented out for the timing. I added the method to the FLARManager class and I’ll pass the code on to Eric so he can see if he thinks it’s worth including.

Here’s the method in case you want to play with it:

public function calibrateThreshold():Boolean{
var histo:Vector.<Vector.<Number>> ;
var channel:Vector.<Number>;
var darkSum:Number = 0;
var lightSum:Number = 0;
//var startTime:Date;
//var endTime:Date;


try {
//startTime = new Date();
histo = this.flarRaster.bitmapData.histogram();


//assume even colour spread so use Green
channel = histo[2];


//sum the darkest and lightest values
for (var c:int = 0; c < 20; c++) {
darkSum = darkSum + channel[c];
lightSum = lightSum + channel[c + 235];
}


if (darkSum > lightSum) {
//scene is dark, set threshold bias -ve
this._adaptiveThresholdingBias = -0.5;
//trace("Scene is DARK");
}else if (lightSum > darkSum) {
//scene is light, set threshold bias +ve
this._adaptiveThresholdingBias = 0.5;
//trace("Scene is LIGHT");
}else {
//even - set threshold bias 0
this._adaptiveThresholdingBias = 0;
//trace("Scene is even");
}
} catch (e:Error) {
// this.flarRaster not yet fully initialized
return false;
}
//endTime = new Date();
//trace("calibrate took: " + (endTime.getTime()-startTime.getTime()));
return true;
}

I left the trace statements and date code in but commented out.