这是 SlideshowGestures-WPF 示例中的代码,可用于识别滑动手势。我使用 Fizbin 的 ( http://www.exceptontuesdays.com/gestures-with-microsoft-kinect-for-windows-sdk-v1-5/ ) 库在此代码中添加缩放手势。手势被正确识别,代码进入函数“OnGestureRecognised”中的“if”循环。我想做的是,一旦完成,我想放大图像。我在这里尝试使用该解决方案: Kelly 的https://stackoverflow.com/a/927134/1473556。但问题是,RenderTransform 不适用于 BitmapImage 类的对象。那么我该怎么做呢?
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
/// <summary>
/// The recognizer being used.
/// </summary>
private readonly Recognizer activeRecognizer;
// skeleton gesture recognizer
private GestureController gestureController;
/// <summary>
/// The paths of the picture files.
/// </summary>
private readonly string[] picturePaths = CreatePicturePaths();
/// <summary>
/// Array of arrays of contiguous line segements that represent a skeleton.
/// </summary>
private static readonly JointType[][] SkeletonSegmentRuns = new JointType[][]
{
new JointType[]
{
JointType.Head, JointType.ShoulderCenter, JointType.HipCenter
},
new JointType[]
{
JointType.HandLeft, JointType.WristLeft, JointType.ElbowLeft, JointType.ShoulderLeft,
JointType.ShoulderCenter,
JointType.ShoulderRight, JointType.ElbowRight, JointType.WristRight, JointType.HandRight
},
new JointType[]
{
JointType.FootLeft, JointType.AnkleLeft, JointType.KneeLeft, JointType.HipLeft,
JointType.HipCenter,
JointType.HipRight, JointType.KneeRight, JointType.AnkleRight, JointType.FootRight
}
};
/// <summary>
/// The sensor we're currently tracking.
/// </summary>
private KinectSensor nui;
/// <summary>
/// There is currently no connected sensor.
/// </summary>
private bool isDisconnectedField = true;
/// <summary>
/// Any message associated with a failure to connect.
/// </summary>
private string disconnectedReasonField;
/// <summary>
/// Array to receive skeletons from sensor, resize when needed.
/// </summary>
private Skeleton[] skeletons = new Skeleton[0];
/// <summary>
/// Time until skeleton ceases to be highlighted.
/// </summary>
private DateTime highlightTime = DateTime.MinValue;
/// <summary>
/// The ID of the skeleton to highlight.
/// </summary>
private int highlightId = -1;
/// <summary>
/// The ID of the skeleton to be tracked.
/// </summary>
private int nearestId = -1;
/// <summary>
/// The index of the current image.
/// </summary>
private int indexField = 1;
/// <summary>
/// Initializes a new instance of the <see cref="MainWindow" /> class.
/// </summary>
public MainWindow()
{
this.PreviousPicture = this.LoadPicture(this.Index - 1);
this.Picture = this.LoadPicture(this.Index);
this.NextPicture = this.LoadPicture(this.Index + 1);
InitializeComponent();
// initialize the gesture recognizer
gestureController = new GestureController();
gestureController.GestureRecognized += OnGestureRecognized;
// Create the gesture recognizer.
this.activeRecognizer = this.CreateRecognizer();
// Wire-up window loaded event.
Loaded += this.OnMainWindowLoaded;
}
/// <summary>
/// Event implementing INotifyPropertyChanged interface.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Gets a value indicating whether no Kinect is currently connected.
/// </summary>
public bool IsDisconnected
{
get
{
return this.isDisconnectedField;
}
private set
{
if (this.isDisconnectedField != value)
{
this.isDisconnectedField = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("IsDisconnected"));
}
}
}
}
/// <summary>
/// Gets any message associated with a failure to connect.
/// </summary>
public string DisconnectedReason
{
get
{
return this.disconnectedReasonField;
}
private set
{
if (this.disconnectedReasonField != value)
{
this.disconnectedReasonField = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("DisconnectedReason"));
}
}
}
}
/// <summary>
/// Gets or sets the index number of the image to be shown.
/// </summary>
public int Index
{
get
{
return this.indexField;
}
set
{
if (this.indexField != value)
{
this.indexField = value;
// Notify world of change to Index and Picture.
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("Index"));
}
}
}
}
/// <summary>
/// Gets the previous image displayed.
/// </summary>
public BitmapImage PreviousPicture { get; private set; }
/// <summary>
/// Gets the current image to be displayed.
/// </summary>
public BitmapImage Picture { get; private set; }
/// <summary>
/// Gets the next image displayed.
/// </summary>
public BitmapImage NextPicture { get; private set; }
/// <summary>
/// Get list of files to display as pictures.
/// </summary>
/// <returns>Paths to pictures.</returns>
private static string[] CreatePicturePaths()
{
var list = new List<string>();
var commonPicturesPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var newPath = commonPicturesPath + "\\Images";
list.AddRange(Directory.GetFiles(newPath, "*.jpg", SearchOption.AllDirectories));
if (list.Count == 0)
{
list.AddRange(Directory.GetFiles(commonPicturesPath, "*.png", SearchOption.AllDirectories));
}
if (list.Count == 0)
{
var myPicturesPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
list.AddRange(Directory.GetFiles(myPicturesPath, "*.jpg", SearchOption.AllDirectories));
if (list.Count == 0)
{
list.AddRange(Directory.GetFiles(commonPicturesPath, "*.png", SearchOption.AllDirectories));
}
}
return list.ToArray();
}
/// <summary>
/// Load the picture with the given index.
/// </summary>
/// <param name="index">The index to use.</param>
/// <returns>Corresponding image.</returns>
private BitmapImage LoadPicture(int index)
{
BitmapImage value;
if (this.picturePaths.Length != 0)
{
var actualIndex = index % this.picturePaths.Length;
if (actualIndex < 0)
{
actualIndex += this.picturePaths.Length;
}
Debug.Assert(0 <= actualIndex, "Index used will be non-negative");
Debug.Assert(actualIndex < this.picturePaths.Length, "Index is within bounds of path array");
try
{
value = new BitmapImage(new Uri(this.picturePaths[actualIndex]));
}
catch (NotSupportedException)
{
value = null;
}
}
else
{
value = null;
}
return value;
}
/// <summary>
/// Create a wired-up recognizer for running the slideshow.
/// </summary>
/// <returns>The wired-up recognizer.</returns>
private Recognizer CreateRecognizer()
{
// Instantiate a recognizer.
var recognizer = new Recognizer();
// Wire-up swipe right to manually advance picture.
recognizer.SwipeRightDetected += (s, e) =>
{
if (e.Skeleton.TrackingId == nearestId)
{
Index++;
Debug.WriteLine("Swiperight. Your gesture is recognised. Congratulations");
// Setup corresponding picture if pictures are available.
this.PreviousPicture = this.Picture;
this.Picture = this.NextPicture;
this.NextPicture = LoadPicture(Index + 1);
// Notify world of change to Index and Picture.
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("PreviousPicture"));
this.PropertyChanged(this, new PropertyChangedEventArgs("Picture"));
this.PropertyChanged(this, new PropertyChangedEventArgs("NextPicture"));
}
var storyboard = Resources["LeftAnimate"] as Storyboard;
if (storyboard != null)
{
storyboard.Begin();
}
HighlightSkeleton(e.Skeleton);
}
};
// Wire-up swipe left to manually reverse picture.
recognizer.SwipeLeftDetected += (s, e) =>
{
if (e.Skeleton.TrackingId == nearestId)
{
Index--;
Debug.WriteLine("Swipeleft. Your gesture is recognised. Congratulations");
// Setup corresponding picture if pictures are available.
this.NextPicture = this.Picture;
this.Picture = this.PreviousPicture;
this.PreviousPicture = LoadPicture(Index - 1);
// Notify world of change to Index and Picture.
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("PreviousPicture"));
this.PropertyChanged(this, new PropertyChangedEventArgs("Picture"));
this.PropertyChanged(this, new PropertyChangedEventArgs("NextPicture"));
}
var storyboard = Resources["RightAnimate"] as Storyboard;
if (storyboard != null)
{
storyboard.Begin();
}
HighlightSkeleton(e.Skeleton);
}
};
return recognizer;
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e">Gesture event arguments.</param>
private void OnGestureRecognized(object sender, GestureEventArgs e)
{
Debug.WriteLine(e.GestureType);
if (e.GestureType == GestureType.ZoomIn)
{
Debug.WriteLine(" line has been Detected.");
// window.Close();
}
/*switch (e.GestureType)
{
case GestureType.Menu:
Gesture = "Menu";
break;
case GestureType.WaveRight:
Gesture = "Wave Right";
break;
case GestureType.WaveLeft:
Gesture = "Wave Left";
break;
case GestureType.JoinedHands:
Gesture = "Joined Hands";
break;
case GestureType.SwipeLeft:
Gesture = "Swipe Left";
break;
case GestureType.SwipeRight:
Gesture = "Swipe Right";
break;
case GestureType.ZoomIn:
Gesture = "Zoom In";
break;
case GestureType.ZoomOut:
Gesture = "Zoom Out";
break;
default:
break;
}*/
}
/// <summary>
/// Handle insertion of Kinect sensor.
/// </summary>
private void InitializeNui()
{
this.UninitializeNui();
var index = 0;
while (this.nui == null && index < KinectSensor.KinectSensors.Count)
{
try
{
this.nui = KinectSensor.KinectSensors[index];
this.nui.Start();
this.IsDisconnected = false;
this.DisconnectedReason = null;
}
catch (IOException ex)
{
this.nui = null;
this.DisconnectedReason = ex.Message;
}
catch (InvalidOperationException ex)
{
this.nui = null;
this.DisconnectedReason = ex.Message;
}
index++;
}
if (this.nui != null)
{
this.nui.SkeletonStream.Enable();
this.nui.SkeletonFrameReady += this.OnSkeletonFrameReady;
}
}
/// <summary>
/// Handle removal of Kinect sensor.
/// </summary>
private void UninitializeNui()
{
if (this.nui != null)
{
this.nui.SkeletonFrameReady -= this.OnSkeletonFrameReady;
this.nui.Stop();
this.nui = null;
}
this.IsDisconnected = true;
this.DisconnectedReason = null;
}
/// <summary>
/// Window loaded actions to initialize Kinect handling.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The event args.</param>
private void OnMainWindowLoaded(object sender, RoutedEventArgs e)
{
// Start the Kinect system, this will cause StatusChanged events to be queued.
this.InitializeNui();
// Handle StatusChange events to pick the first sensor that connects.
KinectSensor.KinectSensors.StatusChanged += (s, ee) =>
{
switch (ee.Status)
{
case KinectStatus.Connected:
if (nui == null)
{
Debug.WriteLine("New Kinect connected");
InitializeNui();
}
else
{
Debug.WriteLine("Existing Kinect signalled connection");
}
break;
default:
if (ee.Sensor == nui)
{
Debug.WriteLine("Existing Kinect disconnected");
UninitializeNui();
}
else
{
Debug.WriteLine("Other Kinect event occurred");
}
break;
}
};
}
/// <summary>
/// Handler for skeleton ready handler.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The event args.</param>
private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame frame = e.OpenSkeletonFrame())
{
if (frame == null)
return;
// resize the skeletons array if needed
if (skeletons.Length != frame.SkeletonArrayLength)
skeletons = new Skeleton[frame.SkeletonArrayLength];
// get the skeleton data
frame.CopySkeletonDataTo(skeletons);
foreach (var skeleton in skeletons)
{
// skip the skeleton if it is not being tracked
if (skeleton.TrackingState != SkeletonTrackingState.Tracked)
continue;
// update the gesture controller
gestureController.UpdateAllGestures(skeleton);
}
}
// Get the frame.
using (var frame = e.OpenSkeletonFrame())
{
// Ensure we have a frame.
if (frame != null)
{
// Resize the skeletons array if a new size (normally only on first call).
if (this.skeletons.Length != frame.SkeletonArrayLength)
{
this.skeletons = new Skeleton[frame.SkeletonArrayLength];
}
// Get the skeletons.
frame.CopySkeletonDataTo(this.skeletons);
// Assume no nearest skeleton and that the nearest skeleton is a long way away.
var newNearestId = -1;
var nearestDistance2 = double.MaxValue;
// Look through the skeletons.
foreach (var skeleton in this.skeletons)
{
// Only consider tracked skeletons.
if (skeleton.TrackingState == SkeletonTrackingState.Tracked)
{
// Find the distance squared.
var distance2 = (skeleton.Position.X * skeleton.Position.X) +
(skeleton.Position.Y * skeleton.Position.Y) +
(skeleton.Position.Z * skeleton.Position.Z);
// Is the new distance squared closer than the nearest so far?
if (distance2 < nearestDistance2)
{
// Use the new values.
newNearestId = skeleton.TrackingId;
nearestDistance2 = distance2;
}
}
}
if (this.nearestId != newNearestId)
{
this.nearestId = newNearestId;
}
// Pass skeletons to recognizer.
this.activeRecognizer.Recognize(sender, frame, this.skeletons);
this.DrawStickMen(this.skeletons);
}
}
}
}
}
XAML 代码粘贴在此处:
<Window x:Name="window" x:Class="Microsoft.Samples.Kinect.Slideshow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="V'Me v1.0" Height="800" Width="1280" WindowState="Maximized" Background= "#FFD1D6D0">
<Window.Resources>
<SolidColorBrush x:Key="MediumGreyBrush" Color="#ff6e6e6e"/>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<Storyboard x:Key="LeftAnimate">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="previous">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="next">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="current">
<EasingThicknessKeyFrame KeyTime="0" Value="2000,0,-2000,0"/>
<EasingThicknessKeyFrame KeyTime="0:0:0.5" Value="0"/>
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="RightAnimate">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="previous">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="next">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" Storyboard.TargetName="current">
<EasingThicknessKeyFrame KeyTime="0" Value="-2000,0,2000,0"/>
<EasingThicknessKeyFrame KeyTime="0:0:0.5" Value="0"/>
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
<Style TargetType="{x:Type Image}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
</Style>
</Window.Resources>
<Grid DataContext="{Binding ElementName=window}" Margin="10 0 10 0" Height="732" Width="1249">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="20"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Canvas x:Name="StickMen" Width="200" Height="150" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
<DockPanel Margin="0,0,0,15" Height="50"></DockPanel>
<Grid Margin="0,118,0,61" Name="imgBorder" Grid.RowSpan="4" ClipToBounds="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="432*" />
<ColumnDefinition Width="806*" />
</Grid.ColumnDefinitions>
<Image x:Name="next" Source="{Binding NextPicture}" StretchDirection="Both" Stretch="Uniform" ClipToBounds="True"
SnapsToDevicePixels="True" RenderOptions.BitmapScalingMode="HighQuality" RenderTransformOrigin="0.5,0.5" Opacity="0" Grid.ColumnSpan="2" />
<Image x:Name="previous" Source="{Binding PreviousPicture}" StretchDirection="Both" Stretch="Uniform" ClipToBounds="True"
SnapsToDevicePixels="True" RenderOptions.BitmapScalingMode="HighQuality" RenderTransformOrigin="0.5,0.5" Opacity="0" Grid.ColumnSpan="2" />
<Image x:Name="current" Source="{Binding Picture}" StretchDirection="Both" Stretch="Uniform" ClipToBounds="True"
SnapsToDevicePixels="True" RenderOptions.BitmapScalingMode="HighQuality" RenderTransformOrigin="0.5,0.5" Grid.ColumnSpan="2" />
</Grid>
<StatusBar Grid.Row="3" HorizontalAlignment="Stretch" Name="statusBar2" VerticalAlignment="Bottom" Background="White" Foreground="{StaticResource MediumGreyBrush}" FontWeight="UltraBold">
<StatusBarItem Padding="0 0 0 30" Background="#FFD1D6D0"></StatusBarItem>
</StatusBar>
<StatusBar Grid.Row="3" HorizontalAlignment="Stretch" Name="statusBar" VerticalAlignment="Bottom" Background="White" Foreground="Blue" FontSize="14">
<StatusBarItem Padding="0 0 0 30" Background="#FFD1D6D0"></StatusBarItem>
</StatusBar>
<StatusBar Grid.Row="3" Name="statusBar1" VerticalAlignment="Bottom" Background="White" Foreground="{StaticResource MediumGreyBrush}" FontWeight="UltraBold">
<StatusBarItem Padding="0 0 0 20" Background="#FFD1D6D0"></StatusBarItem>
</StatusBar>
<TextBlock Name="statusBarText1" HorizontalAlignment="Center" Text="© Gade Autonomous Systems Pvt. Ltd." Foreground="Black" FontWeight="Normal" TextAlignment="Center" FontStretch="UltraExpanded" Margin="498,74,437,-11" Grid.Row="3" Height="30" Width="303" FontSize="14" />
<TextBlock Name="statusBarText" HorizontalAlignment="Center" Text="Swipe your right arm to the left to move to next slide, swipe your left arm to the right for previous." Height="23" Width="707" VerticalAlignment="Center" FontSize="16" FontWeight="Normal" Grid.Row="3" Foreground="Blue" Margin="271,52,271,18" />
<TextBlock Margin="560,49,564,64" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FF000001" FontFamily="Cambria" FontSize="30" Text="V'Me v1.0" FontWeight="Light" Height="37" />
</Grid>