Dieser Artikel wurde maschinell übersetzt.
Kinect
Multimodale Kommunikation mit Kinect
In der April-Ausgabe (msdn.microsoft.com/magazine/hh882450) ich Sie eingeführt, um "Lily", ein virtueller Assistent Büroangestellte in ihren täglichen Aufgaben helfen soll.Ich wurde veranschaulicht, wie Verwenden der Microsoft Kinect für Windows SDK zum Erstellen von kontextbezogenen Dialog, Lily zu hören und entsprechend reagieren in Bezug auf die Absichten des Benutzers ermöglicht.
Jetzt nehme ich Sie über den nächsten Schritt bei der Verwirklichung einer natürlichen Benutzeroberflächenautomatisierungs durch die Nutzung des Kinect-Geräts Skelett tracking-Interaktion mit dem Benutzer durch Gesten zu erleichtern.Ich werde dann die beiden Begriffe zusammen binden und demonstrieren multimodale Kommunikation mit Lilys Ausgabe abhängig, nicht nur was Gesten gemacht wurde, sondern auch, welche Sprachbefehl ausgestellt wurde.Durch die Kombination dieser zwei Modi der Kommunikation, der Nutzer kommt Weg mit eine viel reichere Erfahrung und Ruft einen Schritt näher an der allgegenwärtigen Datenverarbeitung.Die Präsentation der Lilie ist in Form einer Windows Presentation Foundation (WPF)-Anwendung.
Initialisieren von Kinect
Der erste Schritt bei der Verwendung des Kinect-Geräts ist eine Laufzeitumgebung, Festlegen von verschiedenen Parametern erstellen.Abbildung 1 zeigt die Konfiguration wählte ich für Lily.
Abbildung 1 Kinect Runtime Bau
// Initialize Kinect
nui = Runtime.Kinects[0];// new Runtime();
nui.Initialize(RuntimeOptions.UseDepthAndPlayerIndex |
RuntimeOptions.UseDepth | RuntimeOptions.UseColor |
RuntimeOptions.UseSkeletalTracking);
nuiInitialized = true; nui.SkeletonEngine.TransformSmooth = true;
nui.SkeletonEngine.SmoothParameters = new TransformSmoothParameters
{
Smoothing = 0.75f,
Correction = 0.0f,
Prediction = 0.0f,
JitterRadius = 0.05f,
MaxDeviationRadius = 0.04f
};
nui.VideoStream.Open(ImageStreamType.Video, 2,
ImageResolution.Resolution640x480, ImageType.Color);
nui.DepthStream.Open(ImageStreamType.Depth, 2,
ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);
Wenn Sie ein Kinect-Gerät einrichten, stehen eine Reihe von Optionen zur Verfügung. Beachten Sie zunächst die erste Zeile des Codes in Abbildung 1. Die Kinect für Windows SDK Beta 2 hat einen anderen Konstruktor für die Common Language Runtime. Durch Verweisen auf einen Index (Runtime.Kinects[0];), es ist einfach, Kinect Triebwagen an die Anwendung anzuhängen. In dieser Anwendung habe ich begrenzt es an einem einzelnen Device Kinect, also per Definition die Common Language Runtime muss an Position [0] sein. Sie können die Auflistung der Runtime.Kinects Kinect Triebwagen ggf. behandeln durchlaufen. Als nächstes muss das Kinect-Gerät sagen, welche Funktionen gehen verwendet werden. Dies geschieht, indem Sie die gewünschten Funktionen an die Initialize-Methode übergeben. Es gibt vier Werte zur Auswahl:
- UseColor ermöglicht die Anwendung die Farbinformationen Bild verarbeiten.
- UseDepth ermöglicht der Anwendung zu verwenden, der die Tiefe Bildinformationen.
- UseDepthAndPlayerIndex ermöglicht die Anwendung verwendet die Tiefeninformationen Bild sowie der Index von der Skelett-Tracking-Engine generiert.
- UseSkeletalTracking ermöglicht der Anwendung das Skelett, die tracking-Daten verwenden.
Übergeben dieser Werte teilt die API gehen welche Subsysteme in das Kinect-Gerät verwendet werden, so dass die entsprechenden Teile der mehrstufigen Pipeline der Runtime gestartet werden können. Es ist wichtig zu beachten, dass Sie nicht Fähigkeiten später in der Anwendung zugreifen können, die während der Initialisierung deklariert sind nicht. Beispielsweise würde nicht wenn die einzige Option, die ausgewählt RuntimeOptions.UseColor war und später mit die Tiefeninformationen erforderlich, es verfügbar sein. Daher habe ich vergangen in alle Werte verfügbar, darauf hinweist, dass ich die gesamte Funktionalität des Geräts Kinect verwenden möchten.
Nachverfolgen von Benutzern
Vor der Diskussion im nächsten Abschnitt im Code, laßt uns anschauen, was das Kinect-Gerät wirklich uns gibt. Wenn Sie das Skelett, die tracking-Funktion verwenden, kann das Kinect-Gerät bis zu zwei aktive Menschen, die Interaktion mit dem System verfolgen. Es erreicht dies durch Erstellen einer Auflistung von 20 Gelenke und jeweils eine ID zuordnen. Abbildung 2 zeigt, welche Gelenke modelliert werden.
Abbildung 2 die 20 Gelenke, werden modelliert in Kinect
Abbildung 3 ist ein Bild der Gelenke wird von zwei separaten Benutzer erfasst.
Abbildung 3 zwei aktive Skelette
In Reihenfolge für ein Skelett, aktiv zu werden muss das Kinect-Gerät können den Benutzer von Kopf bis Fuß zu sehen sein. Sobald ein Skelett aktiv ist, wenn eine gemeinsame Ansicht verlässt versucht das Kinect-Gerät, wo dieser Teil des Skeletts ist zu interpolieren. Wenn du gehst, Kinect-fähige Anwendungen erstellen, empfehlen ich Ihnen zum Erstellen einer einfachen Anwendungs nur auf die Skelett-Streams zu sehen und interagieren mit dem Kinect-Gerät. Stellen Sie sicher, dass mehrere Benutzer teilnehmen, und richten Sie Szenarien kommen Hindernisse zwischen Ihren Benutzern und das Kinect-Gerät-Szenarien, die nachahmen was erleben Ihre Anwendung einmal bereitgestellt. Dies wird Ihnen ein ausgezeichnetes Verständnis davon, wie das Skelett Tracking funktioniert und was es fähig, sowie welche Einschränkungen Sie ist Adresse möchten. Du wirst schnell sehen, wie erstaunlich die Technik ist und wie kreativ es in der Interpolation werden kann.
In einigen Szenarien (wie durch Projekt Lilie dargestellt) können die Geschwindigkeit und Bewegtheit dieser Interpolation störend und unproduktiv sein. Daher macht die API die Fähigkeit zur Steuerung einer Ebene der Glättung. Unter Bezugnahme auf Abbildung 1 wieder, zunächst mithilfe der SkeletonEngine auf die Common Language Runtime die TransformSmooth auf True festgelegt. Dadurch wird das Kinect-Gerät, das Sie die Glätte der gerenderten Daten beeinflussen möchten. Legen Sie dann die SmoothParameters. Hier ist eine kurze Beschreibung der einzelnen der TransformSmoothParameters:
- Korrektur steuert den Grad der Korrektur mit Werten zwischen 0 und 1,0 und einen Standardwert von.5.
- JitterRadius steuert den Jitter-Reduktion-Radius. Der übergebene Wert stellt den Radius in Metern gewünscht. Der Standardwert ist auf 0,05, festgelegt, in 5 cm übersetzt. Alle Jitter, die über diesen Radius hinaus wird auf den Radius geklemmt.
- MaxDeviationRadius-Steuerelemente, die der maximale Radius (in Metern), der Positionen korrigiert die unformatierten Daten abweichen kann. Der Standardwert ist 0,04.
- Vorhersage steuert die Anzahl der vorhergesagte Frames.
- Glättung steuert die Glättung mit einem Bereich von 0 bis 1,0. Die Dokumentation macht einen bestimmten Punkt, dass glätten Auswirkungen auf Wartezeit hat; Erhöhung Glättung Latenz erhöht. Der Standardwert ist 0,5. Wenn der Wert auf 0 bewirkt, dass die unformatierten Daten zurückgegeben werden.
Video und Tiefe Bäche
Sie wollen experimentieren mit diesen Einstellungen in Ihrer eigenen Anwendung, je nach Anforderungen, die Sie zu erfüllen sind. Das letzte, was für diese Anwendung erforderlich ist, den VideoStream und den DepthStream zu öffnen. Dies erleichtert die Videobilder aus der Farbkamera und der Tiefe Bilder aus der Tiefe Kamera, bzw. anzeigen. Später werde ich Ihnen zeigen, wie dies für die WPF-Anwendung verbunden wird.
Die Open-Methode benötigt vier Parameter. Die erste ist StreamType. Es stellt den Typ des Streams, der (z. B. Video) geöffnet wird. Der zweite Parameter ist PoolSize. Dies entspricht der Anzahl von Frames ab, die die Common Language Runtime ist Puffer. Der maximale Wert ist 4. Der dritte Parameter ist die Auflösung, die die Auflösung der gewünschten Bilder darstellt. Die Werte sind 80 x 60, 640 x 480, 320 x 240 und 1280 x 1024, die Ihren Bedürfnissen entsprechen. Und der letzte Parameter gibt den gewünschten Typ des Bildes (z. B. Farbe).
Kinect-Ereignisse
Mit der Laufzeit erfolgreich initialisiert ist es Zeit, die Ereignisse zur Verfügung gestellt von der Laufzeit der Anwendung verbinden. Für Lily dienen die ersten beiden Ereignisse, die behandelt werden einfach an die Endbenutzer eine grafische Ansicht der Bilder Farbe und Tiefe Bilder geben. Zunächst betrachten wir die Methode, die das Runtime.VideoFrameReady-Ereignis behandelt wird. Dieses Ereignis wird eine ImageFrameReadyEventArgs als Ereignisargument übergeben. Die Nui_VideoFrameReady-Methode ist wo Lily, Ereignisbehandlung, wie im folgenden Code gezeigt:
void nui_VideoFrameReady(object sender, ImageFrameReadyEventArgs e)
{
// Pull out the video frame from the eventargs and
// load it into our image object.
PlanarImage image = e.ImageFrame.Image;
BitmapSource source =
BitmapSource.Create(image.Width, image.Height, 96, 96,
PixelFormats.Bgr32, null, image.Bits,
image.Width * image.BytesPerPixel);
colorImage.Source = source;
}
Kinect für Windows-API vereinfacht diese Methode.Die ImageFrameReadyEventArgs enthält eine ImageFrame.Image.Ich in einen BitmapSource konvertieren und dann die BitmapSource an ein Image-Steuerelement in das WPF-Anwendung übergeben.Der Rahmen aus der Kinect Gerät Farb-Kamera erscheint so auf die Anwendung, wie Sie in sehen Abbildung 3.
Das DepthFrameReady-Ereignis, das von Nui_DepthFrameReady behandelt wird, ähnelt aber braucht ein wenig mehr Arbeit, um eine nützliche Präsentation.Können Sie diese Methode im Codedownload, der letzten Monat Artikel identisch ist (msdn.microsoft.com/en-us/magazine/msdnmag0412).Ich nicht schaffen diese Methode selbst, aber gefunden, dass es in eine Reihe von Beispielen online verwendet.
Der Ereignishandler, der wirklich, interessant zu werden beginnt, ist die Nui_SkeletonFrameReady-Methode.Diese Methode behandelt das SkeletonFrameReady-Ereignis und ruft in SkeletonFrameReadyEventArgs, übergeben, wie in gezeigt Abbildung 4.
Abbildung 4 nui_SkeletonFrameReady
void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
renderSkeleton(sender, e);
if (!trackHands)
return;// If the user doesn't want to use the buttons, simply return.
if (e.SkeletonFrame.Skeletons.Count() == 0)
return;// No skeletons, don't bother processing.
SkeletonFrame skeletonSet = e.SkeletonFrame;
SkeletonData firstPerson = (from s in skeletonSet.Skeletons
where s.TrackingState ==
SkeletonTrackingState.Tracked
orderby s.UserIndex descending
select s).FirstOrDefault();
if (firstPerson == null)
return;// If no one is being tracked, no sense in continuing.
JointsCollection joints = firstPerson.Joints;
Joint righthand = joints[JointID.HandRight];
Joint lefthand = joints[JointID.HandLeft];
// Use the height of the hand to figure out which is being used.
Joint joinCursorHand = (righthand.Position.Y > lefthand.Position.Y)
?
righthand
: lefthand;
float posX = joinCursorHand.ScaleTo((int)SystemParameters.PrimaryScreenWidth,
(int)SystemParameters.PrimaryScreenHeight).Position.X;
float posY = joinCursorHand.ScaleTo((int)SystemParameters.PrimaryScreenWidth,
(int)SystemParameters.PrimaryScreenHeight).Position.Y;
Joint scaledCursorJoint = new Joint
{
TrackingState = JointTrackingState.Tracked,
Position = new Microsoft.Research.Kinect.Nui.Vector
{
X = posX,
Y = posY,
Z = joinCursorHand.Position.Z
}
};
OnButtonLocationChanged(kinectButton, buttons,
(int)scaledCursorJoint.Position.X,
(int)scaledCursorJoint.Position.Y);
}
Eine Sache ich notwendig fand, in dieser Anwendung war die erste Bedingung in Abbildung 4. Wenn der Benutzer die Anwendung auf ihre Handbewegungen verfolgen will nicht, gibt es gesprochene Befehle, die die TrackHands gesetzt, die wiederum bestimmt, ob die Hände nachverfolgt werden. Wenn TrackHands auf False festgelegt ist, gibt der Code einfach von dieser Methode zurück. Wenn Lily Hände des Benutzers nachverfolgt, wenn das nicht das gewünschte Verhalten ist, wird es schnell langweilig und ermüdend.
Ebenso, wenn keine Skelette nachverfolgt werden (es gibt keine Benutzer, oder sie sind außerhalb des zulässigen Bereichs der Ansicht des Geräts Kinect) dann es keinen Sinn, gibt weiterhin zum Auswerten der Daten, so dass der Code von der Methode zurückgegeben. Jedoch, wenn es ist ein Skelett und der Benutzer will die Hände verfolgt, dann wird der Code weiterhin. Das HoverButton-Projekt (bit.ly/nUA2RC) kommt mit Beispiel-Code. Die meisten dieser Methode kam aus diesen Beispielen. Eines der interessanten Dinge passiert in dieser Methode ist, dass der Code überprüft, welche Hand auf der Benutzer physisch höher ist. Dann macht es die Annahme, dass die höchste Hand wird verwendet, um möglicherweise eine Schaltfläche auszuwählen. Der Code geht dann zu bestimmen, ob eine Schaltfläche als über schwebte ist und rendert eine "Hand" in den Ort, der Vertreter des Bildschirms in Bezug auf die Lage der Hand des Benutzers wird auf dem Bildschirm. Mit anderen Worten, wie der Benutzer seine Hand bewegt, wird eine grafische Hand um den Schirm in wie Art und Weise verschoben. Dies gibt dem Nutzer eine natürliche Schnittstelle, durch die Schnur der Maus nicht mehr gebunden. Der Benutzer ist der Controller.
Als nächster Punkt von Interesse ist, wenn das System feststellt, dass eine der die HoverButtons geklickt wird. Lily hat insgesamt acht Tasten auf dem Bildschirm. Jeder hat einen On_click-Ereignishandler in verdrahtet. Ich muss an dieser Stelle drei spezielle Klassen decken: ButtonActionEvaluator, LilyContext und MultiModalReactions.
Die Aktion für das Klicken auf eine Schaltfläche hat ein entsprechendes Ereignis zugeordnet, aber Lily nimmt diese einzelne Aktion und prüft, ob es gekoppelt werden kann, um einen entsprechenden audio-Befehl als eine multimodale Kommunikation zu bewerten, die auf einer höheren Ebene der Bedeutung ergreifen würde. Ein Klick auf eine der HoverButtons stellt beispielsweise die Absicht der Auswahl eines Projekts dar. Mit diesen Informationen ist die einzige Aktion, die vom System geforderte zu beachten, dass der Kontext, in Bezug auf das Projekt gearbeitet, geändert hat. Keine weitere Aktion gewünscht wird. Jedoch, wenn der Benutzer zuvor einen unzufrieden Antrag stellte auf "Projektplan öffnen" oder später die gleiche Anforderung macht, muss die Anwendung setzen diese zwei unterschiedliche Stücke von Daten zusammen, um eine höhere Ordnung von Bedeutung (die Kommunikation aus zwei separate Modi macht diese multimodale Kommunikation) zu erstellen und entsprechend reagieren. Dieses auftreten in einer seamless-Fashion, der folgende Entwurf implementiert wurde.
Die ButtonActionEvaluator-Klasse als Singleton implementiert ist und die INotifyPropertyChanged-Schnittstelle implementiert. Diese Klasse macht ein PropertyChanged-Ereignis, das von der LilyContext-Klasse (auch ein Singleton) behandelt ist auch verfügbar. Der folgende Code erfordert wahrscheinlich etwas zu erklären, obwohl es harmlos genug aussieht:
void buttonActionEvaluator_PropertyChanged(
object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (MultiModalReactions.ActOnMultiModalInput(
buttonActionEvaluator.EvaluateCriteria()) ==
PendingActionResult.ClearPendingAction)
buttonActionEvaluator.ActionPending =
PendingAction.NoneOutstanding;
}
Bewertung von Lilys Zustand
Der vorangehende Code ruft zuerst, die EvaluateCriteria-Methode für die ButtonActionEvaluator-Klasse. Diese Methode gibt einfach eine numerische Darstellung für den Staat durch die Eigenschaften ActionPending und SelectedButton definiert. Dies ist das Herzstück des wie die Anwendung Bedeutung durch den Einsatz von multimodalen Kommunikation ableiten kann. In traditionellen Anwendungen wird die gewünschte Aktion ausgewertet, indem Sie auf den Zustand der ein einzelnes Ereignis oder eine Eigenschaft (z. B. button1.clicked). Aber mit Lily, der Staat (aus der multimodalen Sicht) ausgewertet wird ist die Kombination von zwei sonst separaten Eigenschaften. Mit anderen Worten, jede Eigenschaft hat Bedeutung und erfordert Maßnahmen unabhängig, aber wenn zusammen ausgewertet, treffen sie auf eine neue, höhere Ebene der Bedeutung.
Die numerische Darstellung der kombinierte Zustand auf die multimodale dann an die ActOnMultiModalInput-Methode übergeben wirdReaktionen-Klasse. Diese Methode implementiert eine große Switch-Anweisung, die alle der möglichen Permutationen behandelt. (Dies ist eine rudimentäre Implementierung, die verwendet wurde, um den Punkt zu illustrieren. Zukunft Iterationen von Lily ersetzt diese Implementierung mit fortgeschrittenen Techniken wie State-Machines und Maschinelles Lernen, die Erfahrung und die Benutzerfreundlichkeit verbessern.) Wenn diese Methode in der Absicht des Benutzers zufrieden Ergebnisse (z. B. der Benutzer beabsichtigt für das System zu öffnen Sie den Projektplan für Projekt Lilie), der Rückgabetyp ist PendingActionResult.ClearPendingAction. Dies lässt den Kontext des Systems noch in den Bezugsrahmen der Projekt Lilie, aber es ist keine Aktion warten in der Warteschlange ausgeführt werden. Wenn die Absicht des Benutzers noch nicht zufrieden ist, der PendingActionResult.LeavePendingActionInPlace zurückgegeben, sagt dem System, dass jede beliebige Aktion aufgenommen wurde hat nicht noch die Absicht des Benutzers erfüllt, und um somit nicht klar, die ausstehende Aktion.
Im ersten Artikel habe ich gezeigt, wie Grammatiken zu erstellen, die für eine bestimmte Domäne oder Kontext spezifisch sind. Die Kinect-Einheit, Nutzung der Spracherkennungs-Engine, verwendet diese Grammatiken, Be- und entladen sie die Bedürfnisse des Benutzers. Dies erstellt eine Anwendung, die den Benutzer an eine skriptgesteuerte Interaktion nicht erforderlich ist. Der Benutzer kann gehen, in welcher Richtung sie begehrt und Richtungen ändern, ohne die Anwendung neu konfigurieren. Dies erstellt eine natürliche Art und Weise der Dialog zwischen Mensch und Computeranwendung.
Höhere Bedeutung
In diesem Artikel wurde ich gezeigt, wie auf Aktionen, die infolge von kontextsensitiven Grammatiken eines Benutzers physischen Gestikulieren, in Form von Schaltflächen von schwebenden eine Auswahl der hand über eine Schaltfläche. Jedes Ereignis (SpeechDetected und ButtonClicked) kann einzeln und unabhängig voneinander behandelt werden. Aber darüber hinaus können die beiden Ereignisse vom System bringt ein höheres Maß an Bedeutung, um die Ereignisse und handeln entsprechend korreliert.
Ich hoffe, dass Sie so aufgeregt über die Funktionen, die Kinect in unsere Hände legt, wie ich bin. Ich denke, dass Microsoft brachte uns an den Rand wo können Mensch-Computer-Schnittstellen Sprünge nach vorn nehmen. Als Zeugnis dieser wie ich Lily, entwickelt, es gab Zeiten, wenn ich verschiedene Komponenten und Abschnitte des Codes Tests wurden. Wie die Anwendung ausgereift und ich konnte tatsächlich "Lily sprechen", ich finde etwas falsch, auf meinen zweiten Monitor schalten und beginnen, etwas in der Dokumentation oder anderswo. Aber ich würde weiterhin mündlich mit Lily, Fragen sie die auszuführenden Aufgaben oder sogar zum Herunterfahren zu interagieren. Ich fand, dass als Lily nicht verfügbar war, ich beunruhigt wurde weil die Lage zu versetzen, dass Lily vertreten bedeutende war — unter kleinliche Aufgaben aus meinen Händen durch einfache verbale Kommunikation.
Und Einbeziehung der kleinen "Tricks" in der Dialog-Mechanismus (z. B. zufällige aber kontextuell und syntaktisch korrekte Antworten) die Annahme der Anwendung intuitiv und befriedigend. Kinect macht wirklich den Körper des Controllers. Wo Sie mit ist es nur durch Ihre Fantasie begrenzt. Was wirst du Kinect?
Leland Holmquest ist ein Unternehmens-Strategie-Berater bei Microsoft. Zuvor arbeitete er für die Naval Surface Warfare Center Dahlgren. Er arbeitet an seinen Ph.d. in der Informationstechnologie an der George Mason University.
Dank der folgenden technischen Experten für die Überprüfung dieses Artikels: Mark Schwesinger