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);
        }
 
    }
}