Quantcast
Channel: THOMAS.DEULING.ORG » SWF10
Viewing all articles
Browse latest Browse all 7

Create a webcam face detection within OpenLaszlo by using ActionScript3

$
0
0

Today i found a smart script for a webcam face detection on www.quasimondo.com.
Now i will try to do this within OpenLaszlo, thus post based also on this sample.. ;)

Click here for a quick demo ;)

First of all, we have to download the sourcecode in the Marilena_mod10.zip from www.quasimondo.com and extract it.

To be able to use the source code, we have to compile the ActionScript files into a SWC file. Therefore we need a Flex SDK. If you not already installed it, read here how do you do this under Ubuntu Linux.
When you have the Flex SDK available, navigate into the src directory from the extracted sourcecode and compile the SWC with the following action:

compc -source-path ./ -include-sources ./ -optimize -output ../faceDetection.swc

 
The result is the faceDetection.swc file, which must now be provided to OpenLaszlo. How you can do this, read it here in detail. In short, copy it into your flexlib directory within your OpenLaszlo WEB-INF directory.

Now you can import the required base libaries into a self implemented class by using a passthrough tag:

<class name="faceDetector" width="480" height="640">
	
	<switch>
		<unless property="$as3">
			<handler name="oninit">
			<![CDATA[
				Debug.error("ActionScript 3 required");
			]]>
			</handler>				
		</unless>
		<otherwise>
			<passthrough>
				import com.quasimondo.bitmapdata.CameraBitmap;
				import jp.maaash.ObjectDetection.ObjectDetector;
				import jp.maaash.ObjectDetection.ObjectDetectorEvent;
				import jp.maaash.ObjectDetection.ObjectDetectorOptions;
				...
			</passthrough>

			...

 
The first great step is now done and we will further implement a complete class for using the face detection, so that we in future just have include a tag for using it.
We will do this also on our base sample. The result is a port to OpenLaszlo of these, with just a few differences:

<!---	Object Variables -->
<attribute name="detector" type="expression"/>
<attribute name="camera" type="expression"/>
<attribute name="faceRectContainer" type="expression"/>
<attribute name="detectionMap" type="expression"/>
<attribute name="drawMatrix" type="expression"/>

<!---	Scale factor of the image -->
<attribute name="scaleFactor" type="number" value="4"/>

<!---	Is currently a face detected?! -->
<attribute name="faceDetected" type="boolean" value="false" />
	
<!---	Weight of the face rect -->
<attribute name="rectLineWeight" type="number" value="2"/>

<!---	Starting the initiation -->
<handler name="oninit">
<![CDATA[

	if(this.scaleFactor==0) {
		Debug.error("scaleFactor must be greater 0");
	}

	this.initUI();
	this.initDetector();
]]>
</handler>				

<!---	Init the UI -->
<method name="initUI" args="" returns="void">
<![CDATA[
	var view = new Sprite();
	this.getDisplayObject().addChild(view);

	this.camera = new CameraBitmap(this.width, this.height, 15);
	this.camera.addEventListener(Event.RENDER, this.cameraReadyHandler);
	view.addChild( new Bitmap(this.camera.bitmapData) );
			
	this.detectionMap = new BitmapData(this.width/this.scaleFactor, this.height/this.scaleFactor, false, 0);
	this.drawMatrix = new Matrix(1/this.scaleFactor, 0, 0, 1/this.scaleFactor);
		
	this.faceRectContainer = new Sprite();
	view.addChild(this.faceRectContainer);
]]>
</method>


<!---	Is called when the camera is ready -->
<method name="cameraReadyHandler" args="event:Event" returns="void">
<![CDATA[
	this.detectionMap.draw(this.camera.bitmapData, this.drawMatrix, null, "normal", null, true);
	this.detector.detect(this.detectionMap);
]]>
</method>


<!---	Init the detector -->
<method name="initDetector" args="" returns="void">
<![CDATA[

	// Creat a new ObjectDetector
	this.detector = new ObjectDetector();
	
	// ..and give them the required options 
	var options:ObjectDetectorOptions = new ObjectDetectorOptions();
	options.min_size  = 30;
	this.detector.options = options;
	this.detector.addEventListener(ObjectDetectorEvent.DETECTION_COMPLETE, this.detectionHandler);
]]>
</method>


<!---	Is called at every detection -->
<method name="detectionHandler" args="e:ObjectDetectorEvent" returns="void">
<![CDATA[				

	var g :Graphics = this.faceRectContainer.graphics;
	g.clear();
	if(e.rects) {
		g.lineStyle(this.rectLineWeight);
		e.rects.forEach( function( r :Rectangle, idx :int, arr :Array ) :void {
			
			// Set face detected
			if(!faceDetector.faceDetected) faceDetector.setAttribute("faceDetected", true);
										
			// Timer when face deteced is reset
			if(typeof this.resetDetectionDelegate == "undefined") {
				this.resetDetectionDelegate = new LzDelegate(faceDetector, "resetDetection");
				lz.Timer.addTimer(this.resetDetectionDelegate, 500);
			}
			else {
				lz.Timer.resetTimer(this.resetDetectionDelegate, 500);
			}
			g.drawRect( r.x * faceDetector.scaleFactor, r.y * faceDetector.scaleFactor, r.width * faceDetector.scaleFactor, r.height * faceDetector.scaleFactor );
		});
	}
						
]]>
</method>

<!---	Is called when no face is anymore detected -->
<method name="resetDetection" args="something" returns="void">
<![CDATA[
	if(this.faceDetected) this.setAttribute("faceDetected", false);
]]>
</method>	

 
After finishing the impĺementation of the face detection class, just have to include the new class and place the tag on the required target. We do the as sample in the source code from the snapShot article i have written some days ago:

<simplelayout axis="y" spacing="0" />
<view name="videoView" width="$once{canvas.imageWidth*2}" height="$once{canvas.imageHeight}">
	<simplelayout axis="x" spacing="0" />
	<view name="videoView" width="$once{canvas.imageWidth}" height="$once{canvas.imageHeight}">
		<faceDetector name="faceDetector" id="faceDetector" scaleFactor="2" rectLineWeight="1"
					  width="$once{canvas.imageWidth}" height="$once{canvas.imageHeight}">
			<handler name="onfaceDetected">
			<![CDATA[
				Debug.write(this, "onfaceDetected("+this.faceDetected+")")
			]]>
			</handler>
		</faceDetector>
	</view>
	
	<view name="snapshot" width="$once{canvas.imageWidth}" height="$once{canvas.imageHeight}" />
</view>
			
<view layout="axis: x; spacing:0">
	<button text="Take a snapshot" onclick="canvas.takeSnapshot();" width="$once{canvas.imageWidth}" enabled="${faceDetector.faceDetected}" />
	<button text="Save snapshot" onclick="canvas.saveImage();" width="$once{canvas.imageWidth}" enabled="${canvas.shotAvailable}" />		
</view>	

 
How you see, we just exchange the videoview-tag with the faceDetection-tag, and add the faceDetected-constraint to the enabled attribute of the snapshot button.
This was very easy, or?! And the result pretty nice.. :)
Thanks in this place to Mario Klingemann and all other they have optimize and work on this code.

Click here for a demo ;)

Sourcecode: OpenLaszlo - FaceDetection.zip (1243)

If you found some bugs or have some Tips, please contact me.


Viewing all articles
Browse latest Browse all 7

Trending Articles