Posts Tagged ‘ WEBCAM

Create a webcam face detection within OpenLaszlo by using ActionScript3

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 (1602)

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

Take webcam snapshot with OpenLaszlo

Today i have played a bit with my webcam, and tried to make some pictures and save that as jpeg files.

Click here for a demo 😉

At first we must integrate the webcam within a base structure of openlaszlo code. It’s needed to include some ActionScript libraries to realize our little project.
It’s advisable to implement in the base strukture a switch tag for handle the runtime, and also a passthrough tag for including the ActionScript 3 libraries.
This base structure could be look like:

<?xml version="1.0" encoding="UTF-8" ?>
<canvas width="100%" height="100%">
	
	<switch>
		<unless property="$as3">
			<handler name="oninit">
			<![CDATA[
				Debug.error("ActionScript 3 required");
			]]>
			</handler>				
		</unless>
		<otherwise>
		
			<passthrough>				
				import flash.net.*;
				import com.adobe.images.JPGEncoder;
				import flash.utils.ByteArray;
				import flash.display.Bitmap;
				import flash.display.BitmapData;
				import flash.media.Camera;
				import flash.geom.Matrix;
			</passthrough>

		</otherwise>
	</switch>
		
</canvas>

After that we create some views and include a videoview and a camera-tag inside.

<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}">
		<videoview name="video" oninit="this.stream.broadcast()" width="$once{canvas.imageWidth}" height="$once{canvas.imageHeight}">
			<camera name="webcam" show="true" width="$once{canvas.imageWidth}" height="$once{canvas.imageHeight}" bandwidth="0" picturequality="1.0" />
		</videoview>
	</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}" />
	<button text="Save snapshot" onclick="canvas.saveImage();" width="$once{canvas.imageWidth}" />		
</view>

I don’t know what i do wrong, but i have the feeling that the bandwidth and quality changes does not work (using lps 4.9.0). So, i additional change these values within the oninit handler. If you have a tip, or know what’s the problem of that, please contact me 😉
Here now my oninit handler:

<handler name="oninit">
<![CDATA[
	
	// Get the webcam 
	var cam:Camera = Camera.getCamera();
	
	// Specifies the maximum amount of bandwidth that the current outgoing video feed can use, in bytes per second. To specify that Flash Player video can use as much bandwidth as needed to maintain the value of quality , pass 0 for bandwidth . The default value is 16384.
	var bandwidth:int = 0; 
	
	// This value is 0-100 with 1 being the lowest quality. 
	// Pass 0 if you want the quality to vary to keep better framerates
	var quality:int = 100; 
	
	// Set bandwidth and quality
	cam.setQuality(bandwidth, quality);
	
	// Set measurements and framerate
	cam.setMode(canvas.imageWidth, canvas.imageHeight, 30, false); 
	
]]>
</handler>

For taking a snapshot from the webcam, we write a small function:

<method name="takeSnapshot">
<![CDATA[
	// create a new bitmap object
	var tempSnapshot:BitmapData =new BitmapData(canvas.imageWidth, canvas.imageHeight, true, 0x00FFFFFF);
	tempSnapshot.draw(canvas.videoView.videoView.video.getDisplayObject(), new Matrix());
	
	// place the snapshop i a view
	var targetView = canvas.videoView.snapshot.getDisplayObject();
	targetView.addChild(new Bitmap(tempSnapshot));
	
	canvas.setAttribute("shotAvailable", true);	
]]>
</method>	

Further we want save the snapshot at a local machine. Therefore we must convert the snapshot into a image and send it to the client.

In order to convert the snapshot into a image, we need the JPGEncoder ActionScript library from Mike Chambers.
Some days ago i write about, how to integrate this in OpenLaszlo. You will find the article here.
Here now the function for converting the snapshot into a image:

<method name="saveImage">
<![CDATA[
	
	if(canvas.shotAvailable) {
		
		// Take the snapshot movieclip
		var sketch_mc = canvas.videoView.snapshot.getDisplayObject();
		
		// Get the image data from that
		var jpgSource:BitmapData = new BitmapData(sketch_mc.width, sketch_mc.height);
		jpgSource.draw(sketch_mc);
		
		// Create a Jpeg from the image data
		var jpgEncoder:JPGEncoder = new JPGEncoder(85);
		var jpgStream:ByteArray = jpgEncoder.encode(jpgSource);
		
		// Create an URLRequest with the image
		var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
		var jpgURLRequest:URLRequest = new URLRequest("./snapShotHandle.php?name=sketch.jpg");
		jpgURLRequest.requestHeaders.push(header);
		jpgURLRequest.method = URLRequestMethod.POST;
		jpgURLRequest.data = jpgStream;
		
		// Send the image for download
		navigateToURL(jpgURLRequest, "_blank");
	}
	
]]>
</method>	

For saving the image, we use use a small PHP script like:

<?php

// create filename
$filename = date("Y-m-d_H:i:s", time())."_".uniqid(mt_rand(), true).".jpg";

if(isset($GLOBALS["HTTP_RAW_POST_DATA"])) {
	
	// add headers for download dialog-box
	header('Content-Type: image/jpeg');
	header("Content-Disposition: attachment; filename=".$filename);
	echo $GLOBALS["HTTP_RAW_POST_DATA"];

}

?>

That’s all you need…
Click here for a demo 😉

Sourcecode: OpenLaszlo - SnapShot.zip (1035)

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