Tag Archives: Tips

Next Generation User Interfaces How-To: Bildverarbeitung

image Ein eindrucksvolles Beispiel für die Verarbeitung von Videodaten ist Eywriter (http://www.eyewriter.org). Hier war es das Ziel, zu möglichst geringen Kosten ein Eyetracking-System zu schaffen, dass es gelähmten Personen erlaubt, einen Computer mit den Augen zu Bedienen und so beispielsweise Texte zu verfassen oder Bilder zu malen.

Sowohl Flash als auch Silverlight erlauben die Nutzung einer Videokamera. Das gestaltet sich dabei sehr ähnlich zu dem Einsatz eines Mikrofons. Im Falle von Flash erhält man sogar wie beim Sound einen Wert zur Aktivität. Dieser beschreibt hier aber nicht die Lautstärke sondern die Veränderungen im Bild. Sprich: Je mehr man sich vor der Kamera bewegt, desto höher ist der Wert.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var cam:Camera;
var video:Video;
// Ermittle die Standardkamera
cam=Camera.getCamera();
// Erzwinge die Verarbeitung durch den Flash Player
video = new Video();
video.attachCamera(cam);
// Überprüfe bei jedem "Redraw" des Bildschirms...
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
 
// ...die Aktivität vor der Kamera...
function enterFrameHandler(event:Event):void {
	trace(cam.activityLevel);
	// ...und zeichne eine Linie abhängig vom Wert!
	graphics.lineStyle(0);
	graphics.lineTo(500-x,500-cam.activityLevel*4);
	x--;
}

image Natürlich kann man noch einen Schritt weitergehen und die Bildinformationen auswerten. Ähnlich wie bei Sonys EyeToy (http://www.eyetoy.com/) aus dem Jahr 2003 lässt sich so ermitteln, welche Gesten jemand vor der Kamera durchführt. Am einfachsten geht dies, indem die Anwendung auf spezielle Farbwerte – beispielsweise dem Farbton der Hand – reagiert.

image Einen Schritt weiter geht Microsoft bei dem Project Natal, indem dort auch Tiefenmessung per Infrarot zum Einsatz kommen soll (http://www.xbox.com/en-US/live/projectnatal/). Project Natal befindet sich aktuell noch in der Entwicklung und soll zu Weihnachten 2010 verfügbar sein. Speziell für dieses Projekt hat Microsoft übrigens Johnny Chung Lee eingestellt, der durch seine Experimente mit der Wii bekannt geworden ist (http://johnnylee.net/projects/wii/), darunter ein preiswert umsetzbares Finger- und Headtracking sowie ein Multi-Touch Whiteboard.

Eine einfachere Art der Bilderkennung kommt häufig bei Augmented Reality zum Einsatz (http://saqoosha.net/en/flartoolkit/start-up-guide/ ). Hier wird ein in der Regel aus rechteckigen Blöcken aufgebautes Symbol in die Kamera gehalten und dessen Lage im Raum dient dann zur Steuerung eines Gegenstandes im Computer. Diese Form der erweiterten Realität basiert ursprünglich auf dem ARToolKit von Hirokazu Kato aus dem Jahre 1999 (http://sourceforge.net/projects/artoolkit/). Die Portierung für ActionScript 3 nennt sich FLARToolKit (http://www.libspark.org/wiki/saqoosha/FLARToolKit/en), die für Silverlight SLARToolkit (http://slartoolkit.codeplex.com/).

Für das Lesen eines Barcodes gibt es ebenfalls bereits fertige Bibliotheken wie die von Bernd Engelbrecht unter http://www.codeproject.com/KB/graphics/BarcodeImaging3.aspx. Für einen eigenen Barcode-Scanner ist eine Schaltfläche zum Start der Videoaufzeichnung notwendig.

1
2
3
4
5
6
7
8
9
<UserControl x:Class="SilverScanner.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
 
    <Grid x:Name="LayoutRoot" >
        <Button Content="Scan" Name="scanCapturingBtn" HorizontalAlignment="Left" VerticalAlignment="Top" Click="scanCapturingBtn_Click" />
    </Grid>
 
</UserControl>

Die Vorschau des Videobildes wird in der Code-Behind-Datei per CaptureSource erledigt und im Hintegrund dargestellt. Diese CaptureSource dient ebenfalls für das Ermitteln des Barcodes mit Hilfe der Klassen BarcodeImaging und BarcodeCapture aus dem Beispielprojekt für Silverlight unter http://www.silverlight.net/community/samples/silverlight-4/barcode-scanner/.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
 
namespace SilverScanner
{
    public partial class MainPage : UserControl
    {
 
        CaptureSource captureSource;
        BarcodeCapture barcodeCapture;
 
        public MainPage()
        {
            InitializeComponent();
        }
 
        protected void activateCamera()
        {
            if (captureSource == null)
            {
                // Zeige Vorschau des Videobildes
                captureSource = new CaptureSource();
                captureSource.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
                VideoBrush previewBrush = new VideoBrush();
                previewBrush.Stretch = Stretch.Uniform;
                previewBrush.SetSource(captureSource);
                LayoutRoot.Background = previewBrush;
                // Wähle möglichst gutes Videoformat für bessere Scan-Ergebnisse
                VideoFormat desiredFormat = new VideoFormat(PixelFormatType.Format32bppArgb, 640, 480, 12);
                captureSource.VideoCaptureDevice.DesiredFormat = desiredFormat;
                if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess())
                {
                    captureSource.Start();
                }
 
            }
        }
 
        private void scanCapturingBtn_Click(object sender, RoutedEventArgs e)
        {
            activateCamera();
 
            if (barcodeCapture == null)
            {
                // Starte das Erkennen des Barcodes
                barcodeCapture = new BarcodeCapture();
                barcodeCapture.BarcodeDetected += new EventHandler<barcodeeventargs>(onBarcodeDetected);
                barcodeCapture.CaptureSource = captureSource;
            }
        }
 
        private void onBarcodeDetected(object sender, BarcodeEventArgs e)
        {
            // Zeige gefundenen Barcode
            System.Diagnostics.Debug.WriteLine(e.Barcode);
        }
 
    }
}

Next Generation User Interfaces How-To: Spracheingabe

spracherkennung Die Eingabe von Befehlen funktioniert nicht nur per Kommandozeile sondern auch per Sprachsteuerung. In Windows finden sich die Einstellungen dafür in der Systemsteuerung unter „Erleichterte Bedienung -> Spracherkennung“.

Einige Interaktionsformen bekommt man geschenkt, wenn man sie – wie zum Beispiel die Sprachsteuerung – in seinem Betriebssystem einfach nur aktiviert und ein wenig trainiert. Wenn sich die zu bedienende Anwendung dann noch passend ins System integriert, dann funktioniert die Sprachsteuerung bereits. Schaltflächen in HTML-Dokumenten und auch in Silverlight- sowie Flex-Anwendungen werden dann einfach durch das Aufsagen der entsprechenden Beschriftung aktiviert. Wer sich nicht auf die eingebaute Spracherkennung verlassen möchte oder wo diese gar nicht erst verfügbar ist, der kann auf Bibliotheken zu Spracherkennung zurückgreifen. Didier Brun hat unter http://www.bytearray.org/?p=1151 eine solche Bibliothek bereits für den Flash Player 10.1 angekündigt. Oder man sendet die Sprachaufnahme an einen Server, der das dann verarbeitet…

soundactivity Einfacher geht es, wenn man sich nur mit der Lautstärke zufrieden gibt. Denn mit dem Flash Player können die angeschlossenen Audioquellen – auch mehrere gleichzeitig – genutzt werden. Ohne weiteren Aufwand erhält man dort auch die Lautstärke der jeweiligen Klangquelle.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var mic:Microphone;
var sound:SoundTransform;
 
// Verhindere Rückkopplung und stelle die Lautstärke auf 0
sound = new SoundTransform(0);
 
// Ermittle das Standardmikrofon
mic = Microphone.getMicrophone();
// Erzwinge die Verarbeitung durch den Flash Player
mic.setLoopBack(true);
// Verhindere Rückkopplung 
mic.soundTransform = sound;
 
// Überprüfe bei jedem "Redraw" des Bildschirms...
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
 
// ...die Aktivität des Sounds (also die Lautstärke)...
function enterFrameHandler(event:Event):void {
	trace(mic.activityLevel)	
	// ...und zeichne eine Linie abhängig vom Wert!
	graphics.lineStyle(0);
	graphics.lineTo(500-x,500-mic.activityLevel*4);
	x--;
}

Die Lautstärke kann nun für zahlreiche Formen der Eingabe genutzt werden. Vom Applausometer über das Aufblasen von Ballons bis hin zum Vorwärtspusten eines Segelbootes (ja, natürlich zählt hier nur die Lautstärke, aber die Assoziationen in den meisten Gehirnen lassen einen doch eher pusten als das Boot anschreien).

Wem die reine Lautstärke nicht reicht, der kann sowohl mit AIR 2, mit Flash ab Flash Player 10.1 (Microphone SampleDataEvent.SAMPLE_DATA ) als auch mit Silverlight ab Version 4 (AudioSink.OnSamples) den kompletten Sound analysieren. Für den Flash Player 10.1 sieht das dann so aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
            xmlns:s="library://ns.adobe.com/flex/spark" 
            xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
            creationComplete="application_creationCompleteHandler(event)"
            >
 
   <fx:Script>
      <![CDATA[
         import mx.events.FlexEvent;
 
         protected function application_creationCompleteHandler(event:FlexEvent):void
         {
            var m:Microphone = Microphone.getMicrophone();
            m.addEventListener(SampleDataEvent.SAMPLE_DATA, microphone_sampleDate);
            m.setLoopBack(true);            
         }
 
         protected function microphone_sampleDate(event:SampleDataEvent):void {
            // Verarbeite die Bytes des Samples
            trace(event.data.bytesAvailable);
         }         
      ]]>
   </fx:Script>
 
</s:Application>

Next Generation User Interfaces How-To: Kommandozeile

cliDas Beispiel eines unterwürfigen Hühnchens (Subservient Chicken) zeigt, wie die Kommandozeile zur Kommunikation mit dem System genutzt werden kann. Eingaben mit Schlüsselwörtern wie etwas „Dance“ lassen das Hühnchen tanzen.

Die Tastatur kann zur Eingabe ganzer Kommandos in einer Art Kommandozeile (CLIs, Command Line Interfaces) dienen. Diese Anwendungen erscheinen dabei meist intelligenter als Sie sind. Es gibt zwar auch anspruchsvolle Anwendungen, die in einem beschränkten Rahmen Sprache wirklich verstehen, doch meist wird nur nach Schlüsselwörtern und Phrasen Ausschau gehalten. Für einfache Anwendungen reicht dann eine Schleife wie im folgenden Code für Flex 4:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx" >
 
	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;
 
			// Führe Befehl aus
			private function executeCommand():void {
				// Wandle Befehlseingabe in Kleinbuchstaben um
				var lowercasetext:String = ti.text.toLowerCase();
				// Ermittle, ob Befehl zum Einschalten eingegeben wurde...
				if (lowercasetext.indexOf("on")>-1) {
					// ...und aktiviere Kontrollkästchen...
					cb.selected = true;
					// ... überprüfe, ob Befehl zum Ausschalten eingegeben wurde...
				} else if (lowercasetext.indexOf("off")>-1) {
					// ...und deaktiviere Kontrollkästchen...
					cb.selected = false;
				}				
			}			
 
			protected function ti_valueCommitHandler(event:FlexEvent):void {
				executeCommand();
			}
 
			protected function ti_enterHandler(event:FlexEvent):void {
				executeCommand();
			}
		]]>
	</fx:Script>
 
	<s:CheckBox x="10" y="10" label="Aktiviere mich per Kommandozeile" id="cb"/>
	<s:TextInput x="10" y="36" width="209" id="ti" 
				 enter="ti_enterHandler(event)"
				 valueCommit="ti_valueCommitHandler(event)" />
 
</s:Application>