cleaned adatum + initial commit for alpine contoso fabrikam woodgrove

This commit is contained in:
Leo Leong 2017-12-07 15:22:18 -08:00
Родитель 261b22aa83
Коммит 08453889ab
228 изменённых файлов: 12364 добавлений и 1 удалений

Просмотреть файл

@ -188,7 +188,6 @@
<Content Include="Images\intro-bg.jpg" />
<Content Include="Images\ipad.png" />
<Content Include="Images\mouse.jpg" />
<Content Include="readme.txt" />
<Content Include="Scripts\AdatumTaxCorp.Main.js" />
<Content Include="Scripts\bootstrap.bundle.js" />
<Content Include="Scripts\bootstrap.bundle.min.js" />

Просмотреть файл

@ -0,0 +1,117 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IntelligentKioskSample", "IntelligentKioskSample.csproj", "{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceHelpers", "ServiceHelpers\ServiceHelpers.csproj", "{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EmotionAPI_Test", "EmotionAPI_Test\EmotionAPI_Test.csproj", "{688FD938-16ED-4EBB-A0E3-0801D9461823}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
CNDebug|Any CPU = CNDebug|Any CPU
CNDebug|ARM = CNDebug|ARM
CNDebug|x64 = CNDebug|x64
CNDebug|x86 = CNDebug|x86
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.CNDebug|Any CPU.ActiveCfg = Release|x64
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.CNDebug|Any CPU.Build.0 = Release|x64
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.CNDebug|Any CPU.Deploy.0 = Release|x64
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.CNDebug|ARM.ActiveCfg = Debug|ARM
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.CNDebug|ARM.Build.0 = Debug|ARM
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.CNDebug|ARM.Deploy.0 = Debug|ARM
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.CNDebug|x64.ActiveCfg = Debug|x64
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.CNDebug|x64.Build.0 = Debug|x64
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.CNDebug|x64.Deploy.0 = Debug|x64
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.CNDebug|x86.ActiveCfg = Debug|x86
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.CNDebug|x86.Build.0 = Debug|x86
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.CNDebug|x86.Deploy.0 = Debug|x86
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Debug|Any CPU.ActiveCfg = Debug|x86
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Debug|Any CPU.Build.0 = Debug|x86
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Debug|Any CPU.Deploy.0 = Debug|x86
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Debug|ARM.ActiveCfg = Debug|ARM
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Debug|ARM.Build.0 = Debug|ARM
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Debug|ARM.Deploy.0 = Debug|ARM
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Debug|x64.ActiveCfg = Debug|x64
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Debug|x64.Build.0 = Debug|x64
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Debug|x64.Deploy.0 = Debug|x64
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Debug|x86.ActiveCfg = Debug|x86
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Debug|x86.Build.0 = Debug|x86
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Debug|x86.Deploy.0 = Debug|x86
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Release|Any CPU.ActiveCfg = Release|x86
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Release|ARM.ActiveCfg = Release|ARM
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Release|ARM.Build.0 = Release|ARM
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Release|ARM.Deploy.0 = Release|ARM
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Release|x64.ActiveCfg = Release|x64
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Release|x64.Build.0 = Release|x64
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Release|x64.Deploy.0 = Release|x64
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Release|x86.ActiveCfg = Release|x86
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Release|x86.Build.0 = Release|x86
{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}.Release|x86.Deploy.0 = Release|x86
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.CNDebug|Any CPU.ActiveCfg = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.CNDebug|Any CPU.Build.0 = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.CNDebug|ARM.ActiveCfg = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.CNDebug|ARM.Build.0 = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.CNDebug|x64.ActiveCfg = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.CNDebug|x64.Build.0 = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.CNDebug|x86.ActiveCfg = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.CNDebug|x86.Build.0 = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Debug|ARM.ActiveCfg = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Debug|ARM.Build.0 = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Debug|x64.ActiveCfg = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Debug|x64.Build.0 = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Debug|x86.ActiveCfg = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Debug|x86.Build.0 = Debug|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Release|Any CPU.Build.0 = Release|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Release|ARM.ActiveCfg = Release|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Release|ARM.Build.0 = Release|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Release|x64.ActiveCfg = Release|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Release|x64.Build.0 = Release|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Release|x86.ActiveCfg = Release|Any CPU
{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}.Release|x86.Build.0 = Release|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.CNDebug|Any CPU.ActiveCfg = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.CNDebug|Any CPU.Build.0 = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.CNDebug|ARM.ActiveCfg = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.CNDebug|ARM.Build.0 = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.CNDebug|x64.ActiveCfg = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.CNDebug|x64.Build.0 = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.CNDebug|x86.ActiveCfg = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.CNDebug|x86.Build.0 = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Debug|Any CPU.Build.0 = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Debug|ARM.ActiveCfg = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Debug|ARM.Build.0 = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Debug|x64.ActiveCfg = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Debug|x64.Build.0 = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Debug|x86.ActiveCfg = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Debug|x86.Build.0 = Debug|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Release|Any CPU.ActiveCfg = Release|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Release|Any CPU.Build.0 = Release|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Release|ARM.ActiveCfg = Release|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Release|ARM.Build.0 = Release|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Release|x64.ActiveCfg = Release|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Release|x64.Build.0 = Release|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Release|x86.ActiveCfg = Release|Any CPU
{688FD938-16ED-4EBB-A0E3-0801D9461823}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0D40B7A4-F52A-4794-A524-0C30F838E002}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,23 @@
<Application
x:Class="IntelligentKioskSample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="using:IntelligentKioskSample.Common"
RequestedTheme="Dark"
xmlns:local="using:IntelligentKioskSample">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="StatusTextBrush" Color="LightYellow"/>
<x:String x:Key="TextStatus_Hi">Hi, how are you doing?</x:String>
<x:String x:Key="TextStatus_Still">Please stand still...</x:String>
<x:String x:Key="TextStatus_Thanks">Thanks!</x:String>
</ResourceDictionary>
</Application.Resources>
</Application>

Просмотреть файл

@ -0,0 +1,185 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Navigation;
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=402347&clcid=0x409
namespace IntelligentKioskSample
{
using ServiceHelpers;
using System.Diagnostics;
using Views;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
#if DEBUG
if (System.Diagnostics.Debugger.IsAttached)
{
// This just gets in the way.
//this.DebugSettings.EnableFrameRateCounter = true;
}
#endif
AppShell shell = Window.Current.Content as AppShell;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (shell == null)
{
// propogate settings to the core library
SettingsHelper.Instance.SettingsChanged += (target, args) =>
{
EmotionServiceHelper.ApiKey = SettingsHelper.Instance.EmotionApiKey;
CoreUtil.MinDetectableFaceCoveragePercentage = SettingsHelper.Instance.MinDetectableFaceCoveragePercentage;
};
// callbacks for core library
EmotionServiceHelper.Throttled = () => ShowThrottlingToast("Emotion");
ErrorTrackingHelper.TrackException = (ex, msg) => LogException(ex, msg);
ErrorTrackingHelper.GenericApiCallExceptionHandler = Util.GenericApiCallExceptionHandler;
SettingsHelper.Instance.Initialize();
// Create a AppShell to act as the navigation context and navigate to the first page
shell = new AppShell();
// Set the default language
shell.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
shell.AppFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Set the TitleBar to Dark Theme
var appView = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView();
var titleBar = appView.TitleBar;
titleBar.BackgroundColor = Windows.UI.Colors.Black;
titleBar.ForegroundColor = Windows.UI.Colors.White;
titleBar.ButtonBackgroundColor = Windows.UI.Colors.Black;
titleBar.ButtonForegroundColor = Windows.UI.Colors.White;
}
// Place our app shell in the current Window
Window.Current.Content = shell;
if (shell.AppFrame.Content == null)
{
// When the navigation stack isn't restored, navigate to the first page
// suppressing the initial entrance animation.
shell.AppFrame.Navigate(typeof(EmotionRecognitionPage), e.Arguments, new Windows.UI.Xaml.Media.Animation.SuppressNavigationTransitionInfo());
}
// Ensure the current window is active
Window.Current.Activate();
}
private static void ShowThrottlingToast(string api)
{
ToastTemplateType toastTemplate = ToastTemplateType.ToastText02;
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);
XmlNodeList toastTextElements = toastXml.GetElementsByTagName("text");
toastTextElements[0].AppendChild(toastXml.CreateTextNode("Alpine Ski House Happiness Meter"));
toastTextElements[1].AppendChild(toastXml.CreateTextNode("The " + api + " API is throttling your requests. Consider upgrading to a Premium Key."));
ToastNotification toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier().Show(toast);
}
private static void LogException(Exception ex, string message)
{
Debug.WriteLine("Error detected! Exception: \"{0}\", More info: \"{1}\".", ex.Message, message);
}
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
private void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//Save application state and stop any background activity
//var currentView = (Window.Current.Content as AppShell)?.AppFrame?.Content;
//if (currentView != null && currentView.GetType() == typeof(RealTimeDemo))
//{
// await (currentView as RealTimeDemo).HandleApplicationShutdownAsync();
//}
deferral.Complete();
}
}
}

Просмотреть файл

@ -0,0 +1,114 @@
<Page x:Name="Root"
x:Class="IntelligentKioskSample.AppShell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IntelligentKioskSample"
xmlns:controls="using:IntelligentKioskSample.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
KeyDown="AppShell_KeyDown"
TabNavigation="Cycle"
mc:Ignorable="d">
<!-- Using a Page as the root for the app provides a design time experience as well as ensures that
when it runs on Mobile the app content won't appear under the system's StatusBar which is visible
by default with a transparent background. It will also take into account the presence of software
navigation buttons if they appear on a device. An app can opt-out by switching to UseCoreWindow.
-->
<Page.Resources>
<DataTemplate x:Key="NavMenuItemTemplate" x:DataType="local:NavMenuItem">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- Showing a ToolTip and the Label is redundant. We put the ToolTip on the icon.
It appears when the user hovers over the icon, but not the label which provides
value when the SplitView is 'Compact' while reducing the likelihood of showing
redundant information when the label is shown.-->
<FontIcon x:Name="Glyph" FontSize="16" Glyph="{x:Bind SymbolAsChar}" VerticalAlignment="Center" HorizontalAlignment="Center" ToolTipService.ToolTip="{x:Bind Label}"/>
<TextBlock x:Name="Text" Grid.Column="1" Text="{x:Bind Label}" />
</Grid>
</DataTemplate>
</Page.Resources>
<Grid>
<!-- Adaptive triggers -->
<!--<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="RootSplitView.DisplayMode" Value="CompactInline"/>
<Setter Target="RootSplitView.IsPaneOpen" Value="True"/>
</VisualState.Setters>
</VisualState>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="RootSplitView.DisplayMode" Value="Overlay"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>-->
<!-- Top-level navigation menu + app content -->
<SplitView x:Name="RootSplitView"
DisplayMode="Overlay"
OpenPaneLength="256"
IsTabStop="False">
<SplitView.Pane>
<!-- A custom ListView to display the items in the pane. The automation Name is set in the ContainerContentChanging event. -->
<controls:NavMenuListView x:Name="NavMenuList"
TabIndex="3"
Margin="0,48,0,0"
ContainerContentChanging="NavMenuItemContainerContentChanging"
ItemContainerStyle="{StaticResource NavMenuItemContainerStyle}"
ItemTemplate="{StaticResource NavMenuItemTemplate}"
ItemInvoked="NavMenuList_ItemInvoked">
<controls:NavMenuListView.Header>
<!-- Using this custom back navigation button until the system-provided back button is enabled. -->
<Button x:Name="BackButton"
TabIndex="2"
Style="{StaticResource NavigationBackButtonStyle}"
IsEnabled="{Binding AppFrame.CanGoBack, ElementName=Root}"
Width="{Binding ItemsPanelRoot.Width, ElementName=NavMenuList}"
HorizontalAlignment="{Binding ItemsPanelRoot.HorizontalAlignment, ElementName=NavMenuList}"
Click="BackButton_Click"/>
</controls:NavMenuListView.Header>
</controls:NavMenuListView>
</SplitView.Pane>
<!-- OnNavigatingToPage we synchronize the selected item in the nav menu with the current page.
OnNavigatedToPage we move keyboard focus to the first item on the page after it's loaded. -->
<Frame x:Name="frame"
Navigating="OnNavigatingToPage"
Navigated="OnNavigatedToPage">
<Frame.ContentTransitions>
<TransitionCollection>
<NavigationThemeTransition>
<NavigationThemeTransition.DefaultNavigationTransitionInfo>
<EntranceNavigationTransitionInfo/>
</NavigationThemeTransition.DefaultNavigationTransitionInfo>
</NavigationThemeTransition>
</TransitionCollection>
</Frame.ContentTransitions>
</Frame>
</SplitView>
<!-- Declared last to have it rendered above everything else, but it needs to be the first item in the tab sequence. -->
<ToggleButton x:Name="TogglePaneButton"
TabIndex="1"
Style="{StaticResource SplitViewTogglePaneButtonStyle}"
Tapped="TogglePaneButton_Tapped"
Unchecked="TogglePaneButton_Checked"
AutomationProperties.Name="Menu"
ToolTipService.ToolTip="Menu" />
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,362 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using IntelligentKioskSample.Controls;
using IntelligentKioskSample.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using Windows.Devices.Input;
using Windows.Foundation;
using Windows.Foundation.Metadata;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Navigation;
namespace IntelligentKioskSample
{
/// <summary>
/// The "chrome" layer of the app that provides top-level navigation with
/// proper keyboarding navigation.
/// </summary>
public sealed partial class AppShell : Page
{
// Declare the top level nav items
private List<NavMenuItem> navlist = new List<NavMenuItem>(
new NavMenuItem[]
{
new NavMenuItem()
{
Symbol = Symbol.Favorite,
Label = "Emotion",
DestPage = typeof(EmotionRecognitionPage)
},
new NavMenuItem()
{
Symbol = Symbol.Setting,
Label = "Settings",
DestPage = typeof(SettingsPage)
}
});
public static AppShell Current = null;
/// <summary>
/// Initializes a new instance of the AppShell, sets the static 'Current' reference,
/// adds callbacks for Back requests and changes in the SplitView's DisplayMode, and
/// provide the nav menu list with the data to display.
/// </summary>
public AppShell()
{
this.InitializeComponent();
this.Loaded += (sender, args) =>
{
Current = this;
this.TogglePaneButton.Focus(FocusState.Programmatic);
this.NavigateToStartingPage();
};
this.RootSplitView.RegisterPropertyChangedCallback(
SplitView.DisplayModeProperty,
(s, a) =>
{
// Ensure that we update the reported size of the TogglePaneButton when the SplitView's
// DisplayMode changes.
this.CheckTogglePaneButtonSizeChanged();
});
SystemNavigationManager.GetForCurrentView().BackRequested += SystemNavigationManager_BackRequested;
// If on a phone device that has hardware buttons then we hide the app's back button.
if (ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons"))
{
this.BackButton.Visibility = Visibility.Collapsed;
}
NavMenuList.ItemsSource = navlist;
}
public void NavigateToStartingPage()
{
NavigateToPage(typeof(EmotionRecognitionPage));
}
public void NavigateToPage(Type destPage)
{
if (this.AppFrame.CurrentSourcePageType != destPage)
{
AppFrame.Navigate(destPage, string.Empty, new Windows.UI.Xaml.Media.Animation.SuppressNavigationTransitionInfo());
}
}
public Frame AppFrame { get { return this.frame; } }
/// <summary>
/// Default keyboard focus movement for any unhandled keyboarding
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AppShell_KeyDown(object sender, KeyRoutedEventArgs e)
{
FocusNavigationDirection direction = FocusNavigationDirection.None;
switch (e.Key)
{
case Windows.System.VirtualKey.Left:
case Windows.System.VirtualKey.GamepadDPadLeft:
case Windows.System.VirtualKey.GamepadLeftThumbstickLeft:
case Windows.System.VirtualKey.NavigationLeft:
direction = FocusNavigationDirection.Left;
break;
case Windows.System.VirtualKey.Right:
case Windows.System.VirtualKey.GamepadDPadRight:
case Windows.System.VirtualKey.GamepadLeftThumbstickRight:
case Windows.System.VirtualKey.NavigationRight:
direction = FocusNavigationDirection.Right;
break;
case Windows.System.VirtualKey.Up:
case Windows.System.VirtualKey.GamepadDPadUp:
case Windows.System.VirtualKey.GamepadLeftThumbstickUp:
case Windows.System.VirtualKey.NavigationUp:
direction = FocusNavigationDirection.Up;
break;
case Windows.System.VirtualKey.Down:
case Windows.System.VirtualKey.GamepadDPadDown:
case Windows.System.VirtualKey.GamepadLeftThumbstickDown:
case Windows.System.VirtualKey.NavigationDown:
direction = FocusNavigationDirection.Down;
break;
}
if (direction != FocusNavigationDirection.None)
{
var control = FocusManager.FindNextFocusableElement(direction) as Control;
if (control != null)
{
control.Focus(FocusState.Programmatic);
e.Handled = true;
}
}
}
#region BackRequested Handlers
private void SystemNavigationManager_BackRequested(object sender, BackRequestedEventArgs e)
{
bool handled = e.Handled;
this.BackRequested(ref handled);
e.Handled = handled;
}
private void BackButton_Click(object sender, RoutedEventArgs e)
{
bool ignored = false;
this.BackRequested(ref ignored);
}
private void BackRequested(ref bool handled)
{
// Get a hold of the current frame so that we can inspect the app back stack.
if (this.AppFrame == null)
return;
// Check to see if this is the top-most page on the app back stack.
if (this.AppFrame.CanGoBack && !handled)
{
// If not, set the event to handled and go back to the previous page in the app.
handled = true;
this.AppFrame.GoBack();
}
}
#endregion
#region Navigation
/// <summary>
/// Navigate to the Page for the selected <paramref name="listViewItem"/>.
/// </summary>
/// <param name="sender"></param>
/// <param name="listViewItem"></param>
private void NavMenuList_ItemInvoked(object sender, ListViewItem listViewItem)
{
var item = (NavMenuItem)((NavMenuListView)sender).ItemFromContainer(listViewItem);
if (item != null)
{
if (item.DestPage != null &&
item.DestPage != this.AppFrame.CurrentSourcePageType)
{
this.AppFrame.Navigate(item.DestPage, item.Arguments);
}
}
}
/// <summary>
/// Ensures the nav menu reflects reality when navigation is triggered outside of
/// the nav menu buttons.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnNavigatingToPage(object sender, NavigatingCancelEventArgs e)
{
if (e.NavigationMode == NavigationMode.Back)
{
var item = (from p in this.navlist where p.DestPage == e.SourcePageType select p).SingleOrDefault();
if (item == null && this.AppFrame.BackStackDepth > 0)
{
// In cases where a page drills into sub-pages then we'll highlight the most recent
// navigation menu item that appears in the BackStack
foreach (var entry in this.AppFrame.BackStack.Reverse())
{
item = (from p in this.navlist where p.DestPage == entry.SourcePageType select p).SingleOrDefault();
if (item != null)
break;
}
}
var container = (ListViewItem)NavMenuList.ContainerFromItem(item);
// While updating the selection state of the item prevent it from taking keyboard focus. If a
// user is invoking the back button via the keyboard causing the selected nav menu item to change
// then focus will remain on the back button.
if (container != null) container.IsTabStop = false;
NavMenuList.SetSelectedItem(container);
if (container != null) container.IsTabStop = true;
}
}
private void OnNavigatedToPage(object sender, NavigationEventArgs e)
{
// After a successful navigation set keyboard focus to the loaded page
if (e.Content is Page && e.Content != null)
{
var control = (Page)e.Content;
control.Loaded += Page_Loaded;
}
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
((Page)sender).Focus(FocusState.Programmatic);
((Page)sender).Loaded -= Page_Loaded;
this.CheckTogglePaneButtonSizeChanged();
}
#endregion
public Rect TogglePaneButtonRect
{
get;
private set;
}
/// <summary>
/// An event to notify listeners when the hamburger button may occlude other content in the app.
/// The custom "PageHeader" user control is using this.
/// </summary>
public event TypedEventHandler<AppShell, Rect> TogglePaneButtonRectChanged;
/// <summary>
/// Callback when the SplitView's Pane is toggled open or close. When the Pane is not visible
/// then the floating hamburger may be occluding other content in the app unless it is aware.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TogglePaneButton_Checked(object sender, RoutedEventArgs e)
{
this.CheckTogglePaneButtonSizeChanged();
}
/// <summary>
/// Check for the conditions where the navigation pane does not occupy the space under the floating
/// hamburger button and trigger the event.
/// </summary>
private void CheckTogglePaneButtonSizeChanged()
{
if (this.RootSplitView.DisplayMode == SplitViewDisplayMode.Inline ||
this.RootSplitView.DisplayMode == SplitViewDisplayMode.Overlay)
{
var transform = this.TogglePaneButton.TransformToVisual(this);
var rect = transform.TransformBounds(new Rect(0, 0, this.TogglePaneButton.ActualWidth, this.TogglePaneButton.ActualHeight));
this.TogglePaneButtonRect = rect;
}
else
{
this.TogglePaneButtonRect = new Rect();
}
var handler = this.TogglePaneButtonRectChanged;
if (handler != null)
{
// handler(this, this.TogglePaneButtonRect);
handler.DynamicInvoke(this, this.TogglePaneButtonRect);
}
}
/// <summary>
/// Enable accessibility on each nav menu item by setting the AutomationProperties.Name on each container
/// using the associated Label of each item.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void NavMenuItemContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (!args.InRecycleQueue && args.Item != null && args.Item is NavMenuItem)
{
args.ItemContainer.SetValue(AutomationProperties.NameProperty, ((NavMenuItem)args.Item).Label);
}
else
{
args.ItemContainer.ClearValue(AutomationProperties.NameProperty);
}
}
private void TogglePaneButton_Tapped(object sender, TappedRoutedEventArgs e)
{
RootSplitView.IsPaneOpen = !RootSplitView.IsPaneOpen;
TogglePaneButton.IsChecked = !TogglePaneButton.IsChecked;
}
}
}

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/BingNewsAnalytics.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.1 MiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/BingVisualSearch.jpg Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 234 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/CustomVisionExplorer.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 8.0 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/EmotionRecognition.PNG Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 333 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/FaceAPI.PNG Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 351 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/GreetingKiosk.JPG Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/ImageCollectionInsights.JPG Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 16 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/Mall.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 903 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/RealTime.PNG Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/RealTimeFromVideo.PNG Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 14 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/RealtimeDriverMonitoring.jpg Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 11 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/StoreLogo.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.0 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/StoreLogo.scale-10.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 429 B

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/VisionAPI.jpg Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 304 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/camera.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.9 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/female.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.3 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/male.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/male_blue.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.4 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/new-splash-sdk - Copy.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 6.4 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/new-splash-sdk.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 11 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/oxford-face.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 481 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/smalltile-sdk.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 363 B

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/splash-sdk - Copy.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/splash-sdk.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 9.5 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/splash-sdk.scale-100.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 11 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/squaretile-sdk-44.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.0 KiB

Двоичные данные
AlpineSkiHouseHappinessMeter/Assets/squaretile-sdk.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.0 KiB

Просмотреть файл

@ -0,0 +1,25 @@
<UserControl
x:Class="IntelligentKioskSample.Controls.CameraControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IntelligentKioskSample.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Name="cameraControl"
d:DesignHeight="300"
d:DesignWidth="400"
FlowDirection="RightToLeft">
<Grid FlowDirection="LeftToRight">
<CaptureElement x:Name="webCamCaptureElement" FlowDirection="{Binding ElementName=cameraControl, Path=FlowDirection}" />
<Canvas x:Name="FaceTrackingVisualizationCanvas" FlowDirection="{Binding ElementName=cameraControl, Path=FlowDirection}" />
<Grid x:Name="commandBar" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="2" >
<Button Opacity="0.8" HorizontalAlignment="Right" VerticalAlignment="Bottom" Background="#FF222222" BorderBrush="Transparent" Click="CameraControlButtonClick" >
<SymbolIcon x:Name="cameraControlSymbol" Margin="6" Symbol="Camera"></SymbolIcon>
</Button>
</Grid>
</Grid>
</UserControl>

Просмотреть файл

@ -0,0 +1,563 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Microsoft.ProjectOxford.Common.Contract;
using Microsoft.ProjectOxford.Face.Contract;
using ServiceHelpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Graphics.Imaging;
using Windows.Media;
using Windows.Media.Capture;
using Windows.Media.Devices;
using Windows.Media.FaceAnalysis;
using Windows.Media.MediaProperties;
using Windows.System.Threading;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace IntelligentKioskSample.Controls
{
public enum AutoCaptureState
{
WaitingForFaces,
WaitingForStillFaces,
ShowingCountdownForCapture,
ShowingCapturedPhoto
}
public interface IRealTimeDataProvider
{
EmotionScores GetLastEmotionForFace(BitmapBounds faceBox);
Face GetLastFaceAttributesForFace(BitmapBounds faceBox);
}
public sealed partial class CameraControl : UserControl
{
public event EventHandler<ImageAnalyzer> ImageCaptured;
public event EventHandler<AutoCaptureState> AutoCaptureStateChanged;
public event EventHandler CameraRestarted;
public event EventHandler CameraAspectRatioChanged;
public static readonly DependencyProperty ShowDialogOnApiErrorsProperty =
DependencyProperty.Register(
"ShowDialogOnApiErrors",
typeof(bool),
typeof(CameraControl),
new PropertyMetadata(true)
);
public bool ShowDialogOnApiErrors
{
get { return (bool)GetValue(ShowDialogOnApiErrorsProperty); }
set { SetValue(ShowDialogOnApiErrorsProperty, (bool)value); }
}
public bool FilterOutSmallFaces
{
get;
set;
}
private bool enableAutoCaptureMode;
public bool EnableAutoCaptureMode
{
get
{
return enableAutoCaptureMode;
}
set
{
this.enableAutoCaptureMode = value;
this.commandBar.Visibility = this.enableAutoCaptureMode ? Visibility.Collapsed : Visibility.Visible;
}
}
public double CameraAspectRatio { get; set; }
public int CameraResolutionWidth { get; private set; }
public int CameraResolutionHeight { get; private set; }
public int NumFacesOnLastFrame { get; set; }
public CameraStreamState CameraStreamState { get { return captureManager != null ? captureManager.CameraStreamState : CameraStreamState.NotStreaming; } }
private MediaCapture captureManager;
private VideoEncodingProperties videoProperties;
private FaceTracker faceTracker;
private ThreadPoolTimer frameProcessingTimer;
private SemaphoreSlim frameProcessingSemaphore = new SemaphoreSlim(1);
private AutoCaptureState autoCaptureState;
private IEnumerable<DetectedFace> detectedFacesFromPreviousFrame;
private DateTime timeSinceWaitingForStill;
private DateTime lastTimeWhenAFaceWasDetected;
private IRealTimeDataProvider realTimeDataProvider;
public CameraControl()
{
this.InitializeComponent();
}
#region Camera stream processing
public async Task StartStreamAsync(bool isForRealTimeProcessing = false)
{
try
{
if (captureManager == null ||
captureManager.CameraStreamState == CameraStreamState.Shutdown ||
captureManager.CameraStreamState == CameraStreamState.NotStreaming)
{
if (captureManager != null)
{
captureManager.Dispose();
}
captureManager = new MediaCapture();
MediaCaptureInitializationSettings settings = new MediaCaptureInitializationSettings();
var allCameras = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
var selectedCamera = allCameras.FirstOrDefault(c => c.Name == SettingsHelper.Instance.CameraName);
if (selectedCamera != null)
{
settings.VideoDeviceId = selectedCamera.Id;
}
await captureManager.InitializeAsync(settings);
await SetVideoEncodingToHighestResolution(isForRealTimeProcessing);
this.webCamCaptureElement.Source = captureManager;
}
if (captureManager.CameraStreamState == CameraStreamState.NotStreaming)
{
if (this.faceTracker == null)
{
this.faceTracker = await FaceTracker.CreateAsync();
}
this.videoProperties = this.captureManager.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties;
await captureManager.StartPreviewAsync();
if (this.frameProcessingTimer != null)
{
this.frameProcessingTimer.Cancel();
frameProcessingSemaphore.Release();
}
TimeSpan timerInterval = TimeSpan.FromMilliseconds(66); //15fps
this.frameProcessingTimer = ThreadPoolTimer.CreatePeriodicTimer(new TimerElapsedHandler(ProcessCurrentVideoFrame), timerInterval);
this.cameraControlSymbol.Symbol = Symbol.Camera;
this.webCamCaptureElement.Visibility = Visibility.Visible;
}
}
catch (Exception ex)
{
await Util.GenericApiCallExceptionHandler(ex, "Error starting the camera.");
}
}
private async Task SetVideoEncodingToHighestResolution(bool isForRealTimeProcessing = false)
{
VideoEncodingProperties highestVideoEncodingSetting;
// Sort the available resolutions from highest to lowest
var availableResolutions = this.captureManager.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview).Cast<VideoEncodingProperties>().OrderByDescending(v => v.Width * v.Height * (v.FrameRate.Numerator / v.FrameRate.Denominator));
if (isForRealTimeProcessing)
{
uint maxHeightForRealTime = 720;
// Find the highest resolution that is 720p or lower
highestVideoEncodingSetting = availableResolutions.FirstOrDefault(v => v.Height <= maxHeightForRealTime);
if (highestVideoEncodingSetting == null)
{
// Since we didn't find 720p or lower, look for the first up from there
highestVideoEncodingSetting = availableResolutions.LastOrDefault();
}
}
else
{
// Use the highest resolution
highestVideoEncodingSetting = availableResolutions.FirstOrDefault();
}
if (highestVideoEncodingSetting != null)
{
this.CameraAspectRatio = (double)highestVideoEncodingSetting.Width / (double)highestVideoEncodingSetting.Height;
this.CameraResolutionHeight = (int)highestVideoEncodingSetting.Height;
this.CameraResolutionWidth = (int)highestVideoEncodingSetting.Width;
await this.captureManager.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview, highestVideoEncodingSetting);
if (this.CameraAspectRatioChanged != null)
{
this.CameraAspectRatioChanged(this, EventArgs.Empty);
}
}
}
private async void ProcessCurrentVideoFrame(ThreadPoolTimer timer)
{
if (captureManager.CameraStreamState != Windows.Media.Devices.CameraStreamState.Streaming
|| !frameProcessingSemaphore.Wait(0))
{
return;
}
try
{
IEnumerable<DetectedFace> faces = null;
// Create a VideoFrame object specifying the pixel format we want our capture image to be (NV12 bitmap in this case).
// GetPreviewFrame will convert the native webcam frame into this format.
const BitmapPixelFormat InputPixelFormat = BitmapPixelFormat.Nv12;
using (VideoFrame previewFrame = new VideoFrame(InputPixelFormat, (int)this.videoProperties.Width, (int)this.videoProperties.Height))
{
await this.captureManager.GetPreviewFrameAsync(previewFrame);
// The returned VideoFrame should be in the supported NV12 format but we need to verify this.
if (FaceDetector.IsBitmapPixelFormatSupported(previewFrame.SoftwareBitmap.BitmapPixelFormat))
{
faces = await this.faceTracker.ProcessNextFrameAsync(previewFrame);
if (this.FilterOutSmallFaces)
{
// We filter out small faces here.
faces = faces.Where(f => CoreUtil.IsFaceBigEnoughForDetection((int)f.FaceBox.Height, (int)this.videoProperties.Height));
}
this.NumFacesOnLastFrame = faces.Count();
if (this.EnableAutoCaptureMode)
{
this.UpdateAutoCaptureState(faces);
}
// Create our visualization using the frame dimensions and face results but run it on the UI thread.
var previewFrameSize = new Windows.Foundation.Size(previewFrame.SoftwareBitmap.PixelWidth, previewFrame.SoftwareBitmap.PixelHeight);
var ignored = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
this.ShowFaceTrackingVisualization(previewFrameSize, faces);
});
}
}
}
catch (Exception)
{
}
finally
{
frameProcessingSemaphore.Release();
}
}
private void ShowFaceTrackingVisualization(Windows.Foundation.Size framePixelSize, IEnumerable<DetectedFace> detectedFaces)
{
this.FaceTrackingVisualizationCanvas.Children.Clear();
double actualWidth = this.FaceTrackingVisualizationCanvas.ActualWidth;
double actualHeight = this.FaceTrackingVisualizationCanvas.ActualHeight;
if (captureManager.CameraStreamState == Windows.Media.Devices.CameraStreamState.Streaming &&
detectedFaces != null && actualWidth != 0 && actualHeight != 0)
{
double widthScale = framePixelSize.Width / actualWidth;
double heightScale = framePixelSize.Height / actualHeight;
foreach (DetectedFace face in detectedFaces)
{
System.Diagnostics.Debug.WriteLine("ShowFaceTrackingVisualization(...) FACE DETECTED!!!");
RealTimeFaceIdentificationBorder faceBorder = new RealTimeFaceIdentificationBorder();
this.FaceTrackingVisualizationCanvas.Children.Add(faceBorder);
faceBorder.ShowFaceRectangle((uint)(face.FaceBox.X / widthScale), (uint)(face.FaceBox.Y / heightScale), (uint)(face.FaceBox.Width / widthScale), (uint)(face.FaceBox.Height / heightScale));
if (this.realTimeDataProvider != null)
{
EmotionScores lastEmotion = this.realTimeDataProvider.GetLastEmotionForFace(face.FaceBox);
if (lastEmotion != null)
{
faceBorder.ShowRealTimeEmotionData(lastEmotion);
}
}
if (SettingsHelper.Instance.ShowDebugInfo)
{
this.FaceTrackingVisualizationCanvas.Children.Add(new TextBlock
{
Text = string.Format("Coverage: {0:0}%", 100 * ((double)face.FaceBox.Height / this.videoProperties.Height)),
Margin = new Thickness((uint)(face.FaceBox.X / widthScale), (uint)(face.FaceBox.Y / heightScale), 0, 0)
});
}
}
}
}
private async void UpdateAutoCaptureState(IEnumerable<DetectedFace> detectedFaces)
{
const int IntervalBeforeCheckingForStill = 500;
const int IntervalWithoutFacesBeforeRevertingToWaitingForFaces = 3;
if (!detectedFaces.Any())
{
if (this.autoCaptureState == AutoCaptureState.WaitingForStillFaces &&
(DateTime.Now - this.lastTimeWhenAFaceWasDetected).TotalSeconds > IntervalWithoutFacesBeforeRevertingToWaitingForFaces)
{
this.autoCaptureState = AutoCaptureState.WaitingForFaces;
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
this.OnAutoCaptureStateChanged(this.autoCaptureState);
});
}
return;
}
this.lastTimeWhenAFaceWasDetected = DateTime.Now;
switch (this.autoCaptureState)
{
case AutoCaptureState.WaitingForFaces:
// We were waiting for faces and got some... go to the "waiting for still" state
this.detectedFacesFromPreviousFrame = detectedFaces;
this.timeSinceWaitingForStill = DateTime.Now;
this.autoCaptureState = AutoCaptureState.WaitingForStillFaces;
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
this.OnAutoCaptureStateChanged(this.autoCaptureState);
});
break;
case AutoCaptureState.WaitingForStillFaces:
// See if we have been waiting for still faces long enough
if ((DateTime.Now - this.timeSinceWaitingForStill).TotalMilliseconds >= IntervalBeforeCheckingForStill)
{
// See if the faces are still enough
if (this.AreFacesStill(this.detectedFacesFromPreviousFrame, detectedFaces))
{
this.autoCaptureState = AutoCaptureState.ShowingCountdownForCapture;
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
this.OnAutoCaptureStateChanged(this.autoCaptureState);
// CAPTURE THE PHOTO DUDE!!!!
//this.TakeAutoCapturePhoto();
this.CameraControlButtonClick(this, new RoutedEventArgs());
//// AFTER 10s RESET
//var delay = Task.Delay(10000).ContinueWith(async _ =>
//{
// await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
// {
// this.CameraControlButtonClick(this, new RoutedEventArgs());
// this.RestartAutoCaptureCycle();
// });
//});
});
}
else
{
// Faces moved too much, update the baseline and keep waiting
this.timeSinceWaitingForStill = DateTime.Now;
this.detectedFacesFromPreviousFrame = detectedFaces;
}
}
break;
case AutoCaptureState.ShowingCountdownForCapture:
break;
case AutoCaptureState.ShowingCapturedPhoto:
break;
default:
break;
}
}
public void RestartAutoCaptureCycle()
{
CameraControlButtonClick(this, new RoutedEventArgs());
this.autoCaptureState = AutoCaptureState.WaitingForFaces;
this.OnAutoCaptureStateChanged(this.autoCaptureState);
}
private bool AreFacesStill(IEnumerable<DetectedFace> detectedFacesFromPreviousFrame, IEnumerable<DetectedFace> detectedFacesFromCurrentFrame)
{
int horizontalMovementThreshold = (int)(videoProperties.Width * 0.02);
int verticalMovementThreshold = (int)(videoProperties.Height * 0.02);
int numStillFaces = 0;
int totalFacesInPreviousFrame = detectedFacesFromPreviousFrame.Count();
foreach (DetectedFace faceInPreviousFrame in detectedFacesFromPreviousFrame)
{
if (numStillFaces > 0 && numStillFaces >= totalFacesInPreviousFrame / 2)
{
// If half or more of the faces in the previous frame are considered still we can stop. It is still enough.
break;
}
// If there is a face in the current frame that is located close enough to this one in the previous frame, we
// assume it is the same face and count it as a still face.
if (detectedFacesFromCurrentFrame.Any(f => Math.Abs((int)faceInPreviousFrame.FaceBox.X - (int)f.FaceBox.X) <= horizontalMovementThreshold &&
Math.Abs((int)faceInPreviousFrame.FaceBox.Y - (int)f.FaceBox.Y) <= verticalMovementThreshold))
{
numStillFaces++;
}
}
if (numStillFaces > 0 && numStillFaces >= totalFacesInPreviousFrame / 2)
{
// If half or more of the faces in the previous frame are considered still we consider the group as still
return true;
}
return false;
}
public async Task StopStreamAsync()
{
try
{
if (this.frameProcessingTimer != null)
{
this.frameProcessingTimer.Cancel();
}
if (captureManager != null && captureManager.CameraStreamState != Windows.Media.Devices.CameraStreamState.Shutdown)
{
this.FaceTrackingVisualizationCanvas.Children.Clear();
await this.captureManager.StopPreviewAsync();
this.FaceTrackingVisualizationCanvas.Children.Clear();
this.webCamCaptureElement.Visibility = Visibility.Collapsed;
}
}
catch (Exception)
{
//await Util.GenericApiCallExceptionHandler(ex, "Error stopping the camera.");
}
}
public async Task<ImageAnalyzer> CaptureFrameAsync()
{
try
{
if (!(await this.frameProcessingSemaphore.WaitAsync(250)))
{
return null;
}
// Capture a frame from the preview stream
var videoFrame = new VideoFrame(BitmapPixelFormat.Bgra8, CameraResolutionWidth, CameraResolutionHeight);
using (var currentFrame = await captureManager.GetPreviewFrameAsync(videoFrame))
{
using (SoftwareBitmap previewFrame = currentFrame.SoftwareBitmap)
{
ImageAnalyzer imageWithFace = new ImageAnalyzer(await Util.GetPixelBytesFromSoftwareBitmapAsync(previewFrame));
imageWithFace.ShowDialogOnFaceApiErrors = this.ShowDialogOnApiErrors;
imageWithFace.FilterOutSmallFaces = this.FilterOutSmallFaces;
imageWithFace.UpdateDecodedImageSize(this.CameraResolutionHeight, this.CameraResolutionWidth);
return imageWithFace;
}
}
}
catch (Exception ex)
{
if (this.ShowDialogOnApiErrors)
{
await Util.GenericApiCallExceptionHandler(ex, "Error capturing photo.");
}
}
finally
{
this.frameProcessingSemaphore.Release();
}
return null;
}
private void OnImageCaptured(ImageAnalyzer imageWithFace)
{
if (this.ImageCaptured != null)
{
this.ImageCaptured(this, imageWithFace);
}
}
private void OnAutoCaptureStateChanged(AutoCaptureState state)
{
if (this.AutoCaptureStateChanged != null)
{
this.AutoCaptureStateChanged(this, state);
}
}
#endregion
private async void CameraControlButtonClick(object sender, RoutedEventArgs e)
{
if (this.cameraControlSymbol.Symbol == Symbol.Camera)
{
var img = await CaptureFrameAsync();
if (img != null)
{
this.cameraControlSymbol.Symbol = Symbol.Refresh;
this.OnImageCaptured(img);
}
}
else
{
this.cameraControlSymbol.Symbol = Symbol.Camera;
await StartStreamAsync();
this.CameraRestarted?.Invoke(this, EventArgs.Empty);
}
}
}
}

Просмотреть файл

@ -0,0 +1,19 @@
<UserControl x:Class="IntelligentKioskSample.Controls.EmotionEmojiControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
>
<Grid Background="#FF1F1F1F" HorizontalAlignment="Left" VerticalAlignment="Top" MinWidth="60" >
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock x:Name="emotionEmoji" FontSize="17" FontFamily="Segoe UI Emoji" HorizontalAlignment="Center" VerticalAlignment="Center">&#x1f604;</TextBlock>
<TextBlock x:Name="emotionText" Margin="2,0,2,3" Grid.Row="1" Style="{StaticResource CaptionTextBlockStyle}" Foreground="LightGray" Opacity="0.5" FontFamily="Segoe UI Semilight" HorizontalAlignment="Center" VerticalAlignment="Top">Happy</TextBlock>
</Grid>
</UserControl>

Просмотреть файл

@ -0,0 +1,98 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Microsoft.ProjectOxford.Common.Contract;
using ServiceHelpers;
using System.Linq;
using Windows.UI.Xaml.Controls;
namespace IntelligentKioskSample.Controls
{
/// <summary>
/// Interaction logic for EmotionEmojiControl.xaml
/// </summary>
public partial class EmotionEmojiControl : UserControl
{
public EmotionEmojiControl()
{
InitializeComponent();
}
public void UpdateEmotion(EmotionScores scores)
{
EmotionData topEmotion = EmotionServiceHelper.ScoresToEmotionData(scores).OrderByDescending(d => d.EmotionScore).First();
string label = "", emoji = "";
switch (topEmotion.EmotionName)
{
case "Anger":
label = "Angry";
emoji = "\U0001f620";
break;
case "Contempt":
label = "Contemptuous";
emoji = "\U0001f612";
break;
case "Disgust":
label = "Disgusted";
emoji = "\U0001f627";
break;
case "Fear":
label = "Afraid";
emoji = "\U0001f628";
break;
case "Happiness":
label = "Happy";
emoji = "\U0001f60a";
break;
case "Neutral":
label = "Neutral";
emoji = "\U0001f614";
break;
case "Sadness":
label = "Sad";
emoji = "\U0001f622";
break;
case "Surprise":
label = "Surprised";
emoji = "\U0001f632";
break;
default:
break;
}
this.emotionEmoji.Text = emoji;
this.emotionText.Text = label;
}
}
}

Просмотреть файл

@ -0,0 +1,21 @@
<UserControl
x:Class="IntelligentKioskSample.Controls.EmotionMeterControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IntelligentKioskSample.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
VerticalAlignment="Center"
x:Name="userControl">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Width="60" Foreground="{Binding ElementName=userControl, Path=MeterForeground}" FontFamily="Segoe UI Semilight" Text="{Binding ElementName=userControl, Path=EmotionName}" HorizontalAlignment="Left" Style="{StaticResource CaptionTextBlockStyle}"/>
<ProgressBar Grid.Column="1" Foreground="{Binding ElementName=userControl, Path=MeterForeground}" Height="5" Value="{Binding ElementName=userControl, Path=EmotionValue}" Minimum="0" Maximum="1" Width="60" HorizontalAlignment="Left" VerticalAlignment="Center"/>
</Grid>
</UserControl>

Просмотреть файл

@ -0,0 +1,108 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Microsoft.ProjectOxford.Emotion.Contract;
using Microsoft.ProjectOxford.Face.Contract;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Shapes;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace IntelligentKioskSample.Controls
{
public sealed partial class EmotionMeterControl : UserControl
{
public EmotionMeterControl()
{
this.InitializeComponent();
//this.DataContext = this;
}
public static readonly DependencyProperty EmotionNameProperty =
DependencyProperty.Register(
"EmotionName",
typeof(string),
typeof(EmotionMeterControl),
new PropertyMetadata("")
);
public static readonly DependencyProperty EmotionValueProperty =
DependencyProperty.Register(
"EmotionValue",
typeof(float),
typeof(EmotionMeterControl),
new PropertyMetadata(0)
);
public static readonly DependencyProperty MeterForegroundProperty =
DependencyProperty.Register(
"MeterForeground",
typeof(SolidColorBrush),
typeof(EmotionMeterControl),
new PropertyMetadata(new SolidColorBrush(Colors.White))
);
public SolidColorBrush MeterForeground
{
get { return (SolidColorBrush)GetValue(MeterForegroundProperty); }
set { SetValue(MeterForegroundProperty, (SolidColorBrush)value); }
}
public string EmotionName
{
get { return (string)GetValue(EmotionNameProperty); }
set { SetValue(EmotionNameProperty, (string)value); }
}
public float EmotionValue
{
get { return (float)GetValue(EmotionValueProperty); }
set { SetValue(EmotionValueProperty, (float)value); }
}
}
}

Просмотреть файл

@ -0,0 +1,84 @@
<UserControl
x:Class="IntelligentKioskSample.Controls.FaceIdentificationBorder"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IntelligentKioskSample.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Name="userControl"
>
<Grid x:Name="hostGrid" >
<Rectangle x:Name="faceRectangle" Stroke="White" Visibility="Visible" HorizontalAlignment="Left" VerticalAlignment="Top" />
<Grid FlowDirection="LeftToRight" VerticalAlignment="Top" x:Name="captionCanvas" Visibility="Collapsed" HorizontalAlignment="Left" SizeChanged="OnCaptionSizeChanged" >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid x:Name="genderAgeGrid" Height="43" MinWidth="50" Background="{Binding BalloonBackground}" VerticalAlignment="Top" HorizontalAlignment="Center" Opacity="0.8" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image x:Name="genderIcon" Margin="5,3,3,3"/>
<Viewbox Grid.Column="1" >
<TextBlock Foreground="{Binding BalloonForeground}" Margin="3,2,3,2" VerticalAlignment="Center"
Text="{Binding CaptionText}"
FontFamily="Segoe UI Semilight"/>
</Viewbox>
</Grid>
<Grid x:Name="emotionGrid" Visibility="Collapsed" MinWidth="50" VerticalAlignment="Top" HorizontalAlignment="Center" >
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid x:Name="emotionGridBackground" Opacity="0.8" Background="{Binding BalloonBackground}" Grid.RowSpan="2"/>
<Grid Height="120" Width="120" Margin="0,2,0,0" Visibility="Collapsed" x:Name="emotionFeedbackGrid">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="0.2*"/>
</Grid.RowDefinitions>
<Image x:Name="emotionFeedbackImage" Grid.RowSpan="2">
<Image.Source>
<BitmapImage x:Name="emotionFeedbackBitmap" />
</Image.Source>
</Image>
<Grid Grid.Row="1">
<Grid x:Name="emotionFeedbackTextBackground" Background="White" Opacity="0.4"/>
<Viewbox>
<TextBlock x:Name="emotionFeedbackText" Margin="4,0,4,0" Foreground="{Binding BalloonForeground}" FontFamily="Segoe UI Semilight" HorizontalAlignment="Center"/>
</Viewbox>
</Grid>
</Grid>
<!--The grid below used to be a ListView with an ItemsSource bound to a collection plus a template, but a bug in Windows would make it crash during layout
when executed outside the debugger. -->
<Grid Grid.Row="1" Margin="2" >
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<local:EmotionMeterControl EmotionName="{Binding EmotionData[0].EmotionName}" EmotionValue="{Binding EmotionData[0].EmotionScore}" MeterForeground="{Binding BalloonForeground}" />
<local:EmotionMeterControl Grid.Row="1" EmotionName="{Binding EmotionData[1].EmotionName}" EmotionValue="{Binding EmotionData[1].EmotionScore}" MeterForeground="{Binding BalloonForeground}"/>
<local:EmotionMeterControl Grid.Row="2" EmotionName="{Binding EmotionData[2].EmotionName}" EmotionValue="{Binding EmotionData[2].EmotionScore}" MeterForeground="{Binding BalloonForeground}"/>
</Grid>
</Grid>
<Polyline x:Name="emotionPolyline" StrokeThickness="0" Grid.Row="1" Opacity="0.8"
VerticalAlignment="Top"
HorizontalAlignment="Center"
Points="0,0,10,10,20,0" Fill="{Binding BalloonBackground}" />
</Grid>
</Grid>
</UserControl>

Просмотреть файл

@ -0,0 +1,125 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using ServiceHelpers;
using Microsoft.ProjectOxford.Emotion.Contract;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Shapes;
using Microsoft.ProjectOxford.Face.Contract;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace IntelligentKioskSample.Controls
{
public sealed partial class FaceIdentificationBorder : UserControl
{
public static readonly DependencyProperty BalloonBackgroundProperty =
DependencyProperty.Register(
"BalloonBackground",
typeof(SolidColorBrush),
typeof(FaceIdentificationBorder),
new PropertyMetadata(null)
);
public SolidColorBrush BalloonBackground
{
get { return (SolidColorBrush)GetValue(BalloonBackgroundProperty); }
set { SetValue(BalloonBackgroundProperty, (SolidColorBrush)value); }
}
public static readonly DependencyProperty BalloonForegroundProperty =
DependencyProperty.Register(
"BalloonForeground",
typeof(SolidColorBrush),
typeof(FaceIdentificationBorder),
new PropertyMetadata(null)
);
public SolidColorBrush BalloonForeground
{
get { return (SolidColorBrush)GetValue(BalloonForegroundProperty); }
set { SetValue(BalloonForegroundProperty, (SolidColorBrush)value); }
}
public string CaptionText { get; set; }
public EmotionData[] EmotionData { get; set; }
public FaceIdentificationBorder()
{
this.InitializeComponent();
}
public void ShowFaceRectangle(double width, double height)
{
this.faceRectangle.Width = width;
this.faceRectangle.Height = height;
this.faceRectangle.Visibility = Visibility.Visible;
}
public void ShowEmotionData(Emotion emotion)
{
this.EmotionData = EmotionServiceHelper.ScoresToEmotionData(emotion.Scores).OrderByDescending(e => e.EmotionScore).ToArray();
this.DataContext = this;
this.genderAgeGrid.Visibility = Visibility.Collapsed;
this.emotionGrid.Visibility = Visibility.Visible;
this.captionCanvas.Visibility = Visibility.Visible;
}
private void OnCaptionSizeChanged(object sender, SizeChangedEventArgs e)
{
this.captionCanvas.Margin = new Thickness(this.faceRectangle.Margin.Left - (this.captionCanvas.ActualWidth - this.faceRectangle.ActualWidth) / 2,
-this.captionCanvas.ActualHeight, 0, 0);
}
}
}

Просмотреть файл

@ -0,0 +1,27 @@
<UserControl
x:Class="IntelligentKioskSample.Controls.ImageWithFaceBorderUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IntelligentKioskSample.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
DataContextChanged="OnDataContextChanged"
x:Name="userControl">
<Grid>
<Grid x:Name="hostGrid" SizeChanged="OnImageSizeChanged" >
<Image x:Name="imageControl" SizeChanged="OnImageSizeChanged" FlowDirection="{Binding FlowDirection, ElementName=userControl}" >
<Image.Source>
<BitmapImage x:Name="bitmapImage" ImageOpened="OnBitmapImageOpened" ></BitmapImage>
</Image.Source>
</Image>
</Grid>
<local:EmotionEmojiControl x:Name="emotionEmojiControl" VerticalAlignment="Top" />
<!--<ProgressRing x:Name="progressIndicator" />-->
<ProgressBar x:Name="progressIndicator" IsIndeterminate="False" Visibility="Collapsed" Height="32" ></ProgressBar>
</Grid>
</UserControl>

Просмотреть файл

@ -0,0 +1,332 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Microsoft.ProjectOxford.Emotion.Contract;
using Microsoft.ProjectOxford.Face.Contract;
using System;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using System.Collections.Generic;
using System.IO;
using ServiceHelpers;
using Newtonsoft.Json.Linq;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace IntelligentKioskSample.Controls
{
public sealed partial class ImageWithFaceBorderUserControl : UserControl
{
private ImageAnalyzer currentImage;
public event EventHandler EmotionDetecting;
public event EventHandler EmotionDetected;
public ImageWithFaceBorderUserControl()
{
this.InitializeComponent();
}
public static readonly DependencyProperty DetectFacesOnLoadProperty =
DependencyProperty.Register(
"DetectFacesOnLoad",
typeof(bool),
typeof(ImageWithFaceBorderUserControl),
new PropertyMetadata(false)
);
public static readonly DependencyProperty ShowMultipleFacesProperty =
DependencyProperty.Register(
"ShowMultipleFaces",
typeof(bool),
typeof(ImageWithFaceBorderUserControl),
new PropertyMetadata(false)
);
public static readonly DependencyProperty PerformRecognitionProperty =
DependencyProperty.Register(
"PerformRecognition",
typeof(bool),
typeof(ImageWithFaceBorderUserControl),
new PropertyMetadata(false)
);
public static readonly DependencyProperty ShowRecognitionResultsProperty =
DependencyProperty.Register(
"ShowRecognitionResults",
typeof(bool),
typeof(ImageWithFaceBorderUserControl),
new PropertyMetadata(false)
);
public static readonly DependencyProperty ShowDialogOnApiErrorsProperty =
DependencyProperty.Register(
"ShowDialogOnApiErrors",
typeof(bool),
typeof(ImageWithFaceBorderUserControl),
new PropertyMetadata(false)
);
public static readonly DependencyProperty ShowEmotionRecognitionProperty =
DependencyProperty.Register(
"ShowEmotionRecognition",
typeof(bool),
typeof(ImageWithFaceBorderUserControl),
new PropertyMetadata(false)
);
public static readonly DependencyProperty BalloonBackgroundProperty =
DependencyProperty.Register(
"BalloonBackground",
typeof(SolidColorBrush),
typeof(ImageWithFaceBorderUserControl),
new PropertyMetadata(null)
);
public static readonly DependencyProperty BalloonForegroundProperty =
DependencyProperty.Register(
"BalloonForeground",
typeof(SolidColorBrush),
typeof(ImageWithFaceBorderUserControl),
new PropertyMetadata(null)
);
public static readonly DependencyProperty DetectFaceLandmarksProperty =
DependencyProperty.Register(
"DetectFaceLandmarks",
typeof(bool),
typeof(ImageWithFaceBorderUserControl),
new PropertyMetadata(false)
);
public SolidColorBrush BalloonBackground
{
get { return (SolidColorBrush)GetValue(BalloonBackgroundProperty); }
set { SetValue(BalloonBackgroundProperty, (SolidColorBrush)value); }
}
public SolidColorBrush BalloonForeground
{
get { return (SolidColorBrush)GetValue(BalloonForegroundProperty); }
set { SetValue(BalloonForegroundProperty, (SolidColorBrush)value); }
}
public bool ShowEmotionRecognition
{
get { return (bool)GetValue(ShowEmotionRecognitionProperty); }
set { SetValue(ShowEmotionRecognitionProperty, (bool)value); }
}
public bool ShowMultipleFaces
{
get { return (bool)GetValue(ShowMultipleFacesProperty); }
set { SetValue(ShowMultipleFacesProperty, (bool)value); }
}
public bool DetectFacesOnLoad
{
get { return (bool)GetValue(DetectFacesOnLoadProperty); }
set { SetValue(DetectFacesOnLoadProperty, (bool)value); }
}
public bool PerformRecognition
{
get { return (bool)GetValue(PerformRecognitionProperty); }
set { SetValue(PerformRecognitionProperty, (bool)value); }
}
public bool ShowRecognitionResults
{
get { return (bool)GetValue(ShowRecognitionResultsProperty); }
set { SetValue(ShowRecognitionResultsProperty, (bool)value); }
}
public bool ShowDialogOnApiErrors
{
get { return (bool)GetValue(ShowDialogOnApiErrorsProperty); }
set { SetValue(ShowDialogOnApiErrorsProperty, (bool)value); }
}
public bool DetectFaceLandmarks
{
get { return (bool)GetValue(DetectFaceLandmarksProperty); }
set { SetValue(DetectFaceLandmarksProperty, (bool)value); }
}
private async void OnDataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
{
ImageAnalyzer dataContext = this.DataContext as ImageAnalyzer;
if (this.currentImage != dataContext)
{
this.currentImage = dataContext;
}
else
{
// Windows sometimes fires multiple DataContextChanged events.
// If we are here that is one of those cases, and since we already set
// the data context to this value we can ignore it
return;
}
foreach (var child in this.hostGrid.Children.Where(c => !(c is Image)).ToArray())
{
this.hostGrid.Children.Remove(child);
}
// remove the current source
this.bitmapImage.UriSource = null;
if (dataContext != null)
{
try
{
if (dataContext.ImageUrl != null)
{
this.bitmapImage.UriSource = new Uri(dataContext.ImageUrl);
}
else if (dataContext.GetImageStreamCallback != null)
{
await this.bitmapImage.SetSourceAsync((await dataContext.GetImageStreamCallback()).AsRandomAccessStream());
}
}
catch (Exception ex)
{
// If we fail to load the image we will just not display it
this.bitmapImage.UriSource = null;
if (this.ShowDialogOnApiErrors)
{
await Util.GenericApiCallExceptionHandler(ex, "Error loading captured image.");
}
}
}
}
private void HideProgressBar()
{
this.progressIndicator.Visibility = Visibility.Collapsed;
this.progressIndicator.IsIndeterminate = false;
}
private void ShowProgressBar()
{
this.progressIndicator.Visibility = Visibility.Visible;
this.progressIndicator.IsIndeterminate = true;
}
private async Task DetectAndShowEmotion()
{
ShowProgressBar();
foreach (var child in this.hostGrid.Children.Where(c => !(c is Image)).ToArray())
{
this.hostGrid.Children.Remove(child);
}
ImageAnalyzer imageWithFace = this.DataContext as ImageAnalyzer;
if (imageWithFace != null)
{
if (imageWithFace.DetectedEmotion == null)
{
EmotionDetecting?.Invoke(this, new EventArgs());
await imageWithFace.DetectEmotionAsync();
EmotionDetected?.Invoke(this, new EventArgs());
}
double renderedImageXTransform = this.imageControl.RenderSize.Width / this.bitmapImage.PixelWidth;
double renderedImageYTransform = this.imageControl.RenderSize.Height / this.bitmapImage.PixelHeight;
foreach (Emotion emotion in imageWithFace.DetectedEmotion)
{
FaceIdentificationBorder faceUI = new FaceIdentificationBorder();
faceUI.Margin = new Thickness((emotion.FaceRectangle.Left * renderedImageXTransform) + ((this.ActualWidth - this.imageControl.RenderSize.Width) / 2),
(emotion.FaceRectangle.Top * renderedImageYTransform) + ((this.ActualHeight - this.imageControl.RenderSize.Height) / 2), 0, 0);
faceUI.BalloonBackground = this.BalloonBackground;
faceUI.BalloonForeground = this.BalloonForeground;
faceUI.ShowFaceRectangle(emotion.FaceRectangle.Width * renderedImageXTransform, emotion.FaceRectangle.Height * renderedImageYTransform);
faceUI.ShowEmotionData(emotion);
this.emotionEmojiControl.UpdateEmotion(emotion.Scores);
this.hostGrid.Children.Add(faceUI);
if (!this.ShowMultipleFaces)
{
break;
}
}
}
//this.progressIndicator.IsActive = false;
HideProgressBar();
}
private async Task PreviewImageFaces()
{
if (!this.DetectFacesOnLoad || this.progressIndicator.Visibility != Visibility.Collapsed)
{
return;
}
ImageAnalyzer img = this.DataContext as ImageAnalyzer;
if (img != null)
{
img.UpdateDecodedImageSize(this.bitmapImage.PixelHeight, this.bitmapImage.PixelWidth);
}
if (this.ShowEmotionRecognition)
{
await this.DetectAndShowEmotion();
}
}
private async void OnBitmapImageOpened(object sender, RoutedEventArgs e)
{
await this.PreviewImageFaces();
}
private async void OnImageSizeChanged(object sender, SizeChangedEventArgs e)
{
await this.PreviewImageFaces();
}
}
}

Просмотреть файл

@ -0,0 +1,179 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.System;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
namespace IntelligentKioskSample.Controls
{
/// <summary>
/// A specialized ListView to represent the items in the navigation menu.
/// </summary>
/// <remarks>
/// This class handles the following:
/// 1. Sizes the panel that hosts the items so they fit in the hosting pane. Otherwise, the keyboard
/// may appear cut off on one side b/c the Pane clips instead of affecting layout.
/// 2. Provides a single selection experience where keyboard focus can move without changing selection.
/// Both the 'Space' and 'Enter' keys will trigger selection. The up/down arrow keys can move
/// keyboard focus without triggering selection. This is different than the default behavior when
/// SelectionMode == Single. The default behavior for a ListView in single selection requires using
/// the Ctrl + arrow key to move keyboard focus without triggering selection. Users won't expect
/// this type of keyboarding model on the nav menu.
/// </remarks>
public class NavMenuListView : ListView
{
private SplitView splitViewHost;
public NavMenuListView()
{
this.SelectionMode = ListViewSelectionMode.Single;
this.IsItemClickEnabled = true;
this.ItemClick += ItemClickedHandler;
// Locate the hosting SplitView control
this.Loaded += (s, a) =>
{
var parent = VisualTreeHelper.GetParent(this);
while (parent != null && !(parent is SplitView))
{
parent = VisualTreeHelper.GetParent(parent);
}
if (parent != null)
{
this.splitViewHost = parent as SplitView;
splitViewHost.RegisterPropertyChangedCallback(SplitView.IsPaneOpenProperty, (sender, args) =>
{
this.OnPaneToggled();
});
// Call once to ensure we're in the correct state
this.OnPaneToggled();
}
};
}
/// <summary>
/// Mark the <paramref name="item"/> as selected and ensures everything else is not.
/// If the <paramref name="item"/> is null then everything is unselected.
/// </summary>
/// <param name="item"></param>
public void SetSelectedItem(ListViewItem item)
{
int index = -1;
if (item != null)
{
index = this.IndexFromContainer(item);
}
for (int i = 0; i < this.Items.Count; i++)
{
var lvi = (ListViewItem)this.ContainerFromIndex(i);
if (i != index)
{
lvi.IsSelected = false;
}
else if (i == index)
{
lvi.IsSelected = true;
}
}
}
/// <summary>
/// Occurs when an item has been selected
/// </summary>
public event EventHandler<ListViewItem> ItemInvoked;
/// <summary>
/// This method is a work-around until the bug in FocusManager.TryMoveFocus is fixed.
/// </summary>
/// <param name="direction"></param>
private void ItemClickedHandler(object sender, ItemClickEventArgs e)
{
// Triggered when the item is selected using something other than a keyboard
var item = this.ContainerFromItem(e.ClickedItem);
this.InvokeItem(item);
}
private void InvokeItem(object focusedItem)
{
this.SetSelectedItem(focusedItem as ListViewItem);
this.ItemInvoked(this, focusedItem as ListViewItem);
if (this.splitViewHost.IsPaneOpen && (
this.splitViewHost.DisplayMode == SplitViewDisplayMode.CompactOverlay ||
this.splitViewHost.DisplayMode == SplitViewDisplayMode.Overlay))
{
this.splitViewHost.IsPaneOpen = false;
if (focusedItem is ListViewItem)
{
((ListViewItem)focusedItem).Focus(FocusState.Programmatic);
}
}
}
/// <summary>
/// Re-size the ListView's Panel when the SplitView is compact so the items
/// will fit within the visible space and correctly display a keyboard focus rect.
/// </summary>
private void OnPaneToggled()
{
if (this.splitViewHost.IsPaneOpen)
{
this.ItemsPanelRoot.ClearValue(FrameworkElement.WidthProperty);
this.ItemsPanelRoot.ClearValue(FrameworkElement.HorizontalAlignmentProperty);
}
else if (this.splitViewHost.DisplayMode == SplitViewDisplayMode.CompactInline ||
this.splitViewHost.DisplayMode == SplitViewDisplayMode.CompactOverlay)
{
this.ItemsPanelRoot.SetValue(FrameworkElement.WidthProperty, this.splitViewHost.CompactPaneLength);
this.ItemsPanelRoot.SetValue(FrameworkElement.HorizontalAlignmentProperty, HorizontalAlignment.Left);
}
}
}
}

Просмотреть файл

@ -0,0 +1,28 @@
<UserControl
x:Name="Root"
x:Class="IntelligentKioskSample.Controls.PageHeader"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IntelligentKioskSample.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
VerticalAlignment="Top"
VerticalContentAlignment="Top"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Background="{ThemeResource SystemControlBackgroundChromeMediumBrush}"
Height="48"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid x:Name="grid" Background="{x:Bind Background}">
<Grid x:Name="titleBar">
<ContentPresenter x:Name="content"
VerticalAlignment="{x:Bind VerticalContentAlignment}"
HorizontalAlignment="{x:Bind HorizontalContentAlignment}"
Margin="{x:Bind Padding}"
Content="{x:Bind HeaderContent}"/>
</Grid>
</Grid>
</UserControl>

Просмотреть файл

@ -0,0 +1,82 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using IntelligentKioskSample.Views;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace IntelligentKioskSample.Controls
{
public sealed partial class PageHeader : UserControl
{
public PageHeader()
{
this.InitializeComponent();
this.Loaded += (s, a) =>
{
AppShell.Current.TogglePaneButtonRectChanged += Current_TogglePaneButtonSizeChanged;
this.titleBar.Margin = new Thickness(AppShell.Current.TogglePaneButtonRect.Right, 0, 0, 0);
};
}
private void Current_TogglePaneButtonSizeChanged(AppShell sender, Rect e)
{
this.titleBar.Margin = new Thickness(e.Right, 0, 0, 0);
}
public UIElement HeaderContent
{
get { return (UIElement)GetValue(HeaderContentProperty); }
set { SetValue(HeaderContentProperty, value); }
}
// Using a DependencyProperty as the backing store for HeaderContent. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HeaderContentProperty =
DependencyProperty.Register("HeaderContent", typeof(UIElement), typeof(PageHeader), new PropertyMetadata(DependencyProperty.UnsetValue));
}
}

Просмотреть файл

@ -0,0 +1,28 @@
<UserControl
x:Class="IntelligentKioskSample.Controls.RealTimeFaceIdentificationBorder"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IntelligentKioskSample.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Name="userControl"
>
<Grid>
<Rectangle x:Name="faceRectangle" Stroke="White" Visibility="Visible" HorizontalAlignment="Left" VerticalAlignment="Top" />
<Border x:Name="captionBorder" Visibility="Collapsed" VerticalAlignment="Top" HorizontalAlignment="Left" Width="300" Height="40" >
<StackPanel Orientation="Horizontal" FlowDirection="LeftToRight" HorizontalAlignment="Center">
<Border Background="#FF1F1F1F">
<StackPanel Orientation="Vertical" VerticalAlignment="Center" >
<TextBlock x:Name="captionTextHeader" Margin="6,0,6,0" Foreground="LightGray" FontFamily="Segoe UI Semilight" />
<TextBlock x:Name="captionTextSubHeader" Margin="6,0,6,0" Foreground="LightGray" Opacity="0.5" Style="{StaticResource CaptionTextBlockStyle}" FontFamily="Segoe UI Semilight" />
</StackPanel>
</Border>
<local:EmotionEmojiControl x:Name="emotionEmojiControl" VerticalAlignment="Center" />
</StackPanel>
</Border>
</Grid>
</UserControl>

Просмотреть файл

@ -0,0 +1,64 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Microsoft.ProjectOxford.Common.Contract;
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace IntelligentKioskSample.Controls
{
public sealed partial class RealTimeFaceIdentificationBorder : UserControl
{
public RealTimeFaceIdentificationBorder()
{
this.InitializeComponent();
}
public void ShowFaceRectangle(double left, double top, double width, double height)
{
this.faceRectangle.Margin = new Thickness(left, top, 0, 0);
this.faceRectangle.Width = width;
this.faceRectangle.Height = height;
this.faceRectangle.Visibility = Visibility.Visible;
}
public void ShowRealTimeEmotionData(EmotionScores scores)
{
this.emotionEmojiControl.UpdateEmotion(scores);
}
}
}

Просмотреть файл

@ -0,0 +1,21 @@
<UserControl
x:Class="IntelligentKioskSample.Controls.UpDownVerticalBarControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IntelligentKiosk.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
x:Name="userControl">
<Grid x:Name="graph" Background="{Binding ElementName=userControl, Path=Background}">
<Grid.RowDefinitions>
<RowDefinition x:Name="topRowDefinition"/>
<RowDefinition x:Name="upBarRowDefinition"/>
<RowDefinition x:Name="downBarRowDefinition"/>
<RowDefinition x:Name="bottomRowDefinition"/>
</Grid.RowDefinitions>
</Grid>
</UserControl>

Просмотреть файл

@ -0,0 +1,106 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Linq;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace IntelligentKioskSample.Controls
{
public sealed partial class UpDownVerticalBarControl : UserControl
{
static SolidColorBrush BackgroundColor = new SolidColorBrush(Colors.Transparent);
public UpDownVerticalBarControl()
{
this.InitializeComponent();
}
public void DrawDataPoint(double value, Brush barColor, Image toolTip = null)
{
if (value > 0)
{
value *= 0.5;
topRowDefinition.Height = new GridLength(0.5 - value, GridUnitType.Star);
upBarRowDefinition.Height = new GridLength(value, GridUnitType.Star);
downBarRowDefinition.Height = new GridLength(0);
bottomRowDefinition.Height = new GridLength(0.5, GridUnitType.Star);
}
else
{
value *= -0.5;
topRowDefinition.Height = new GridLength(0.5, GridUnitType.Star);
upBarRowDefinition.Height = new GridLength(0);
downBarRowDefinition.Height = new GridLength(value, GridUnitType.Star);
bottomRowDefinition.Height = new GridLength(0.5 - value, GridUnitType.Star);
}
Border slice = new Border { Background = BackgroundColor };
Grid.SetRow(slice, 0);
graph.Children.Add(slice);
slice = new Border { Background = barColor };
Grid.SetRow(slice, 1);
graph.Children.Add(slice);
slice = new Border { Background = barColor };
Grid.SetRow(slice, 2);
graph.Children.Add(slice);
slice = new Border { Background = BackgroundColor };
Grid.SetRow(slice, 3);
graph.Children.Add(slice);
AddFlyoutToElement(graph, toolTip);
}
private void AddFlyoutToElement(FrameworkElement element, Image toolTip)
{
if (toolTip != null)
{
FlyoutBase.SetAttachedFlyout(element, new Flyout { Content = toolTip });
element.PointerReleased += (s, e) =>
{
FlyoutBase.ShowAttachedFlyout(element);
};
}
}
}
}

Просмотреть файл

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="apiKey" value="Replace with your API key from PBI1" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Просмотреть файл

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{688FD938-16ED-4EBB-A0E3-0801D9461823}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>EmotionAPI_Test</RootNamespace>
<AssemblyName>EmotionAPI_Test</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.ProjectOxford.Common, Version=1.0.324.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.ProjectOxford.Common.1.0.324\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\Microsoft.ProjectOxford.Common.dll</HintPath>
</Reference>
<Reference Include="Microsoft.ProjectOxford.Emotion, Version=1.0.336.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.ProjectOxford.Emotion.1.0.336\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\Microsoft.ProjectOxford.Emotion.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Primitives, Version=4.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,150 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.ProjectOxford.Emotion;
using Microsoft.ProjectOxford.Common.Contract;
namespace EmotionAPI_Test
{
public class Program
{
static string _apiKey;
static string ApiKey
{
get
{
if (String.IsNullOrEmpty(_apiKey))
_apiKey = ConfigurationManager.AppSettings["apiKey"];
return _apiKey;
}
}
static void Main(string[] args)
{
// Get the image path
Console.WriteLine("JPEG image file path:");
string imageFilePath = Console.ReadLine();
// Make the Emotion API call
CallEmotionAPI(imageFilePath);
// Make the Emotion API call by using Project Oxford Libraries
CallProjectOxford(imageFilePath);
Console.ReadKey();
}
/// <summary>
/// Read the image from the passed Path and return it as a byte Array
/// </summary>
/// <param name="imageFilePath"></param>
/// <returns></returns>
static byte[] GetImageAsByteArray(string imageFilePath)
{
using (FileStream stream = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read))
{
using (BinaryReader reader = new BinaryReader(stream))
{
return reader.ReadBytes((int)stream.Length);
}
}
}
static async void CallEmotionAPI(string imageFilePath)
{
// Declare a new HttpClient to communicate with the Emotion API
HttpClient client = new HttpClient();
// Add the API Key to the request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", ApiKey);
// This url will have to match the region where the cognitive services API was created
string url = "https://westus.api.cognitive.microsoft.com/emotion/v1.0/recognize?";
// Get the image as a byte array
byte[] byteData = GetImageAsByteArray(imageFilePath);
HttpResponseMessage JsonResponse;
string responseContent;
// Prepare the image and the request to query the Emotion API
using (ByteArrayContent imageBytes = new ByteArrayContent(byteData))
{
// Add the proper media type
imageBytes.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
// Call the emotion API by using the URL and the image content so it can analyze our image
JsonResponse = await client.PostAsync(url, imageBytes);
// Store the Emotion API result, this will be a JSON string that will contain the
// identified face (A rectangle surrounding the face) and a emotion score array
responseContent = JsonResponse.Content.ReadAsStringAsync().Result;
}
// Show the raw JSON string
Console.WriteLine();
Console.WriteLine("JSON Response:");
Console.WriteLine(responseContent);
// Use the JSON result string and get the first and second array (face rectangle and emotion score)
JToken root = JArray.Parse(responseContent).First;
JToken faceDimension = root.First();
JToken scores = root.Last();
Console.WriteLine();
Console.WriteLine("Face Rectangle");
// Navigate through each face rectangle coordinate
foreach (JToken size in faceDimension.First.Children())
{
Console.WriteLine(size);
}
Console.WriteLine();
Console.WriteLine("Emotion Score");
// Navigate through each emotion
foreach (JToken score in scores.First.Children())
{
Console.WriteLine(score);
}
}
static async void CallProjectOxford(string imageFilePath)
{
// Declare an EmotionServiceClient object, we will use this object to communicate with our Emotion API
EmotionServiceClient client = new EmotionServiceClient(ApiKey);
// Convert the Image file to a MemoryStream
MemoryStream mem = new MemoryStream(GetImageAsByteArray(imageFilePath));
// Store the result in an emotion list
// With this 3 lines we already make all the communications with the API and store the result
// ProjectOxford libraries help us to work easier with cognitive services APIs.
IEnumerable<Emotion> emotionList = await client.RecognizeAsync(mem);
// Print all the dimensions and emotion scores
foreach (Emotion emotion in emotionList)
{
Console.WriteLine("Face");
Console.WriteLine($"Top: {emotion.FaceRectangle.Top.ToString()}, Width: {emotion.FaceRectangle.Width.ToString()}" +
$"Left: {emotion.FaceRectangle.Left.ToString()}, Height: {emotion.FaceRectangle.Height.ToString()}");
Console.WriteLine();
Console.WriteLine("Emotion");
Console.WriteLine($"Anger: {emotion.Scores.Anger.ToString()}," +
$"Contempt: {emotion.Scores.Contempt.ToString()}," +
$"Disgust: {emotion.Scores.Disgust.ToString()}," +
$"Fear: {emotion.Scores.Fear.ToString()}," +
$"Happiness: {emotion.Scores.Happiness.ToString()}," +
$"Neutral: {emotion.Scores.Neutral.ToString()}," +
$"Sadness: {emotion.Scores.Sadness.ToString()}," +
$"Surprise: {emotion.Scores.Surprise.ToString()}");
}
}
}
}

Просмотреть файл

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("EmotionAPI_Test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("EmotionAPI_Test")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("688fd938-16ed-4ebb-a0e3-0801d9461823")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="net461" />
<package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="net461" />
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net461" />
<package id="Microsoft.ProjectOxford.Common" version="1.0.324" targetFramework="net461" />
<package id="Microsoft.ProjectOxford.Emotion" version="1.0.336" targetFramework="net461" />
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
</packages>

Просмотреть файл

@ -0,0 +1,256 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<ProjectGuid>{B08D337A-AF9F-4705-B8C1-C7F07FACD8C5}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>IntelligentKioskSample</RootNamespace>
<AssemblyName>IntelligentKioskSample</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<EnableDotNetNativeCompatibleProfile>true</EnableDotNetNativeCompatibleProfile>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
<AppxBundle>Always</AppxBundle>
<AppxBundlePlatforms>x86|x64|arm</AppxBundlePlatforms>
<PackageCertificateThumbprint>AFA97E8E34493A24325844C55BC66D56D9F3595C</PackageCertificateThumbprint>
<PackageCertificateKeyFile>IntelligentKioskSample_TemporaryKey.pfx</PackageCertificateKeyFile>
<ApplicationInsightsResourceId />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<ItemGroup>
<None Include="IntelligentKioskSample_TemporaryKey.pfx" />
<None Include="packages.config" />
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\FaceIdentificationBorder.xaml.cs">
<DependentUpon>FaceIdentificationBorder.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\UpDownVerticalBarControl.xaml.cs">
<DependentUpon>UpDownVerticalBarControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\EmotionEmojiControl.xaml.cs">
<DependentUpon>EmotionEmojiControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\CameraControl.xaml.cs">
<DependentUpon>CameraControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\RealTimeFaceIdentificationBorder.xaml.cs">
<DependentUpon>RealTimeFaceIdentificationBorder.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\EmotionMeterControl.xaml.cs">
<DependentUpon>EmotionMeterControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\ImageWithFaceBorderUserControl.xaml.cs">
<DependentUpon>ImageWithFaceBorderUserControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\NavMenuListView.cs" />
<Compile Include="Controls\PageHeader.xaml.cs">
<DependentUpon>PageHeader.xaml</DependentUpon>
</Compile>
<Compile Include="NavMenuItem.cs" />
<Compile Include="SettingsHelper.cs" />
<Compile Include="Util.cs" />
<Compile Include="Views\EmotionRecognitionPage.xaml.cs">
<DependentUpon>EmotionRecognitionPage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPage.xaml.cs">
<DependentUpon>SettingsPage.xaml</DependentUpon>
</Compile>
<Compile Include="AppShell.xaml.cs">
<DependentUpon>AppShell.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<Content Include="Assets\BingNewsAnalytics.png" />
<Content Include="Assets\BingVisualSearch.jpg" />
<Content Include="Assets\camera.png" />
<Content Include="Assets\CustomVisionExplorer.png" />
<Content Include="Assets\female.png" />
<Content Include="Assets\GreetingKiosk.JPG" />
<Content Include="Assets\ImageCollectionInsights.JPG" />
<Content Include="Assets\male_blue.png" />
<Content Include="Assets\EmotionRecognition.PNG" />
<Content Include="Assets\FaceAPI.PNG" />
<Content Include="Assets\male.png" />
<Content Include="Assets\Mall.png" />
<Content Include="Assets\new-splash-sdk - Copy.png" />
<Content Include="Assets\new-splash-sdk.png" />
<Content Include="Assets\oxford-face.png" />
<Content Include="Assets\RealTime.PNG" />
<Content Include="Assets\RealtimeDriverMonitoring.jpg" />
<Content Include="Assets\RealTimeFromVideo.PNG" />
<Content Include="Assets\smalltile-sdk.png" />
<Content Include="Assets\splash-sdk - Copy.png" />
<Content Include="Assets\splash-sdk.png" />
<Content Include="Assets\splash-sdk.scale-100.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\squaretile-sdk.png" />
<Content Include="Assets\squaretile-sdk-44.png" />
<Content Include="Assets\VisionAPI.jpg" />
<Content Include="Properties\Default.rd.xml">
<SubType>Designer</SubType>
</Content>
<Content Include="Assets\StoreLogo.scale-10.png" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="Controls\FaceIdentificationBorder.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\CameraControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\UpDownVerticalBarControl.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Controls\RealTimeFaceIdentificationBorder.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Controls\EmotionMeterControl.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Controls\ImageWithFaceBorderUserControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\PageHeader.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\EmotionEmojiControl.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Styles\Styles.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Page>
<Page Include="Views\EmotionRecognitionPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\SettingsPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="AppShell.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="ServiceHelpers\ServiceHelpers.csproj">
<Project>{5d9320af-a9e4-48e3-89bc-9f7f0954b298}</Project>
<Name>ServiceHelpers</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,106 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Collections.Generic;
using Windows.Foundation.Collections;
using Windows.Graphics.DirectX.Direct3D11;
using Windows.Graphics.Imaging;
using Windows.Media.Effects;
using Windows.Media.MediaProperties;
namespace KioskRuntimeComponent
{
public sealed class FrameRelayVideoEffect : IBasicVideoEffect
{
public static SoftwareBitmap LatestSoftwareBitmap { get; private set; }
public bool IsReadOnly
{
get
{
return true;
}
}
public IReadOnlyList<VideoEncodingProperties> SupportedEncodingProperties
{
get
{
return new List<VideoEncodingProperties>();
}
}
public MediaMemoryTypes SupportedMemoryTypes
{
get
{
return MediaMemoryTypes.Cpu;
}
}
public bool TimeIndependent
{
get
{
return true;
}
}
public void Close(MediaEffectClosedReason reason)
{
}
public void DiscardQueuedFrames()
{
LatestSoftwareBitmap = null;
}
public static void ResetState()
{
LatestSoftwareBitmap = null;
}
public void ProcessFrame(ProcessVideoFrameContext context)
{
LatestSoftwareBitmap = context.InputFrame.SoftwareBitmap;
}
public void SetEncodingProperties(VideoEncodingProperties encodingProperties, IDirect3DDevice device)
{
}
public void SetProperties(IPropertySet configuration)
{
}
}
}

Просмотреть файл

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FC5A0250-B742-40A8-82CA-BEC2DF66982F}</ProjectGuid>
<OutputType>winmdobj</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>KioskRuntimeComponent</RootNamespace>
<AssemblyName>KioskRuntimeComponent</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<AllowCrossPlatformRetargeting>false</AllowCrossPlatformRetargeting>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="FrameRelayVideoEffect.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,62 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("KioskRuntimeComponent")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("KioskRuntimeComponent")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]

Просмотреть файл

@ -0,0 +1,16 @@
{
"dependencies": {
"Microsoft.NETCore.UniversalWindowsPlatform": "5.1.0"
},
"frameworks": {
"uap10.0": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {},
"win10-x86": {},
"win10-x86-aot": {},
"win10-x64": {},
"win10-x64-aot": {}
}
}

Просмотреть файл

@ -0,0 +1,61 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;
namespace IntelligentKioskSample
{
/// <summary>
/// Data to represent an item in the nav menu.
/// </summary>
public class NavMenuItem
{
public string Label { get; set; }
public Symbol Symbol { get; set; }
public char SymbolAsChar
{
get
{
return (char)this.Symbol;
}
}
public Type DestPage { get; set; }
public object Arguments { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
<Identity Name="IntelligentKioskSample" Publisher="CN=Kiosk" Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="bdf9127b-7e32-469b-a6ed-f57a0a80ae23" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Properties>
<DisplayName>Intelligent Kiosk Sample</DisplayName>
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.10240.0" MaxVersionTested="10.0.10240.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate" />
</Resources>
<Applications>
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="IntelligentKioskSample.App">
<uap:VisualElements DisplayName="Alpine Ski House Happiness Meter" Square44x44Logo="Assets\squaretile-sdk-44.png" Square150x150Logo="Assets\squaretile-sdk.png" Description="Alpine Ski House Happiness Meter" BackgroundColor="#00B2F0">
<uap:SplashScreen Image="Assets\splash-sdk.png" BackgroundColor="#00B2F0" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<uap:Capability Name="picturesLibrary" />
<DeviceCapability Name="webcam" />
<DeviceCapability Name="microphone" />
</Capabilities>
</Package>

Просмотреть файл

@ -0,0 +1,62 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("IntelligentKioskSample")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("IntelligentKioskSample")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]

Просмотреть файл

@ -0,0 +1,31 @@
<!--
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
developers. However, you can modify these parameters to modify the behavior of the .NET Native
optimizer.
Runtime Directives are documented at http://go.microsoft.com/fwlink/?LinkID=391919
To fully enable reflection for App1.MyClass and all of its public/private members
<Type Name="App1.MyClass" Dynamic="Required All"/>
To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
Using the Namespace directive to apply reflection policy to all the types in a particular namespace
<Namespace Name="DataClasses.ViewModels" Seralize="All" />
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!--
An Assembly element with Name="*Application*" applies to all assemblies in
the application package. The asterisks are not wildcards.
-->
<Assembly Name="*Application*" Dynamic="Required All" />
<!-- Add your application specific runtime directives here. -->
</Application>
</Directives>

Просмотреть файл

@ -0,0 +1,85 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Microsoft.ProjectOxford.Common;
using Microsoft.ProjectOxford.Face.Contract;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ServiceHelpers
{
public class CoreUtil
{
public static uint MinDetectableFaceCoveragePercentage = 0;
public static bool IsFaceBigEnoughForDetection(int faceHeight, int imageHeight)
{
if (imageHeight == 0)
{
// sometimes we don't know the size of the image, so we assume the face is big enough
return true;
}
double faceHeightPercentage = 100 * ((double)faceHeight / imageHeight);
return faceHeightPercentage >= MinDetectableFaceCoveragePercentage;
}
public static bool AreFacesPotentiallyTheSame(Rectangle face1, FaceRectangle face2)
{
return AreFacesPotentiallyTheSame((int)face1.Left, (int)face1.Top, (int)face1.Width, (int)face1.Height, face2.Left, face2.Top, face2.Width, face2.Height);
}
public static bool AreFacesPotentiallyTheSame(int face1X, int face1Y, int face1Width, int face1Height,
int face2X, int face2Y, int face2Width, int face2Height)
{
double distanceThresholdFactor = 1;
double sizeThresholdFactor = 0.5;
// See if faces are close enough from each other to be considered the "same"
if (Math.Abs(face1X - face2X) <= face1Width * distanceThresholdFactor &&
Math.Abs(face1Y - face2Y) <= face1Height * distanceThresholdFactor)
{
// See if faces are shaped similarly enough to be considered the "same"
if (Math.Abs(face1Width - face2Width) <= face1Width * sizeThresholdFactor &&
Math.Abs(face1Height - face2Height) <= face1Height * sizeThresholdFactor)
{
return true;
}
}
return false;
}
}
}

Просмотреть файл

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ServiceHelpers
{
public class EmotionData
{
public string EmotionName { get; set; }
public float EmotionScore { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,152 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Microsoft.ProjectOxford.Common;
using Microsoft.ProjectOxford.Common.Contract;
using Microsoft.ProjectOxford.Emotion;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace ServiceHelpers
{
public static class EmotionServiceHelper
{
#region Fill Properties
#endregion
public static int RetryCountOnQuotaLimitError = 6;
public static int RetryDelayOnQuotaLimitError = 500;
//Implement : You should declare a property, Task 4, Step 1
private static EmotionServiceClient emotionClient { get; set; }
static EmotionServiceHelper()
{
InitializeEmotionService();
}
public static Action Throttled;
// Implement: PBI 2, Task 3, Step 2
// Create an ApiKey property
private static string apiKey;
public static string ApiKey
{
get { return apiKey; }
set
{
var changed = apiKey != value;
apiKey = value;
if (changed)
{
InitializeEmotionService();
}
}
}
private static void InitializeEmotionService()
{
// Implement: PBI 2, Task 3, Step 3
// Instatiate the EmotionServiceClient object and pass the API key to it so we can communicate with the emotion API.
emotionClient = new EmotionServiceClient(ApiKey);
}
private static async Task<TResponse> RunTaskWithAutoRetryOnQuotaLimitExceededError<TResponse>(Func<Task<TResponse>> action)
{
// Optional Task, Implement: PBI 2, Task 3, Step 5
int retriesLeft = 6;
int delay = 500;
TResponse response = default(TResponse);
while (true)
{
try
{
response = await action();
break;
}
catch (ClientException exception) when (exception.HttpStatus == (System.Net.HttpStatusCode)429 && retriesLeft > 0)
{
ErrorTrackingHelper.TrackException(exception, "Emotion API throttling error");
if (retriesLeft == 1 && Throttled != null)
{
Throttled();
}
await Task.Delay(delay);
retriesLeft--;
delay *= 2;
continue;
}
}
return response;
}
public static async Task<Emotion[]> RecognizeAsync(Func<Task<Stream>> imageStreamCallback)
{
// Implement: PBI 2, Task 3, Step 5
// You should make a call to the EmotionServiceClient object that support a Stream as parameter to identify emotions
return await RunTaskWithAutoRetryOnQuotaLimitExceededError<Emotion[]>(async () => await emotionClient.RecognizeAsync(await imageStreamCallback()));
}
public static async Task<Emotion[]> RecognizeAsync(string url)
{
// Implement: PBI 2, Task 3, Step 5
// You should make a call to the EmotionServiceClient object that support an URL as parameter to identify emotions
return await RunTaskWithAutoRetryOnQuotaLimitExceededError<Emotion[]>(async () => await emotionClient.RecognizeAsync(url));
}
public static IEnumerable<EmotionData> ScoresToEmotionData(EmotionScores scores)
{
// Implement: PBI 2, Task 3, Step 4
// Create a list of emotions and emotion scores to return as a results.
// Use the JSON object result of the EmotionAPI_Test project to undestand how to build this list.
List<EmotionData> result = new List<EmotionData>();
result.Add(new EmotionData { EmotionName = "Anger", EmotionScore = scores.Anger });
result.Add(new EmotionData { EmotionName = "Contempt", EmotionScore = scores.Contempt });
result.Add(new EmotionData { EmotionName = "Disgust", EmotionScore = scores.Disgust });
result.Add(new EmotionData { EmotionName = "Fear", EmotionScore = scores.Fear });
result.Add(new EmotionData { EmotionName = "Happiness", EmotionScore = scores.Happiness });
result.Add(new EmotionData { EmotionName = "Neutral", EmotionScore = scores.Neutral });
result.Add(new EmotionData { EmotionName = "Sadness", EmotionScore = scores.Sadness });
result.Add(new EmotionData { EmotionName = "Surprise", EmotionScore = scores.Surprise });
return result;
}
}
}

Просмотреть файл

@ -0,0 +1,52 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ServiceHelpers
{
public static class ErrorTrackingHelper
{
// callbacks for exception tracking
public static Action<Exception, string> TrackException { get; set; }
= (exception, message) => { };
// callbacks for blocking UI error message
public static Func<Exception, string, Task> GenericApiCallExceptionHandler { get; set; }
= (ex, errorTitle) => Task.FromResult(0);
}
}

Просмотреть файл

@ -0,0 +1,128 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Microsoft.ProjectOxford.Common.Contract;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace ServiceHelpers
{
public class ImageAnalyzer
{
public event EventHandler EmotionRecognitionCompleted;
public Func<Task<Stream>> GetImageStreamCallback { get; set; }
public string ImageUrl { get; set; }
//Implement : You should declare a property, Task 4, Step 1
public IEnumerable<Emotion> DetectedEmotion { get; set; }
// Default to no errors, since this could trigger a stream of popup errors since we might call this
// for several images at once while auto-detecting the Bing Image Search results.
public bool ShowDialogOnFaceApiErrors { get; set; } = false;
public bool FilterOutSmallFaces { get; set; } = false;
public int DecodedImageHeight { get; private set; }
public int DecodedImageWidth { get; private set; }
public byte[] Data { get; set; }
public ImageAnalyzer(string url)
{
this.ImageUrl = url;
}
public ImageAnalyzer(byte[] data)
{
this.Data = data;
this.GetImageStreamCallback = () => Task.FromResult<Stream>(new MemoryStream(this.Data));
}
public void UpdateDecodedImageSize(int height, int width)
{
this.DecodedImageHeight = height;
this.DecodedImageWidth = width;
}
public async Task DetectEmotionAsync()
{
try
{
// Implement #1: If there is ImageUrl you should call the proper EmotionServiceHelper method to detect emotions
if (this.ImageUrl != null)
{
this.DetectedEmotion = await EmotionServiceHelper.RecognizeAsync(this.ImageUrl);
}
// Implement #2: If GetImageStreamCallback is not null, you should call the proper EmotionServiceHelper method to detect emotions
else if (this.GetImageStreamCallback != null)
{
this.DetectedEmotion = await EmotionServiceHelper.RecognizeAsync(this.GetImageStreamCallback);
}
// Implement #3: If FilterOutSmallFaces is enabled, filter the DetectedEmotion using the CoreUtil IsFaceBigEnoughForDetection method results
if (this.FilterOutSmallFaces)
{
this.DetectedEmotion = this.DetectedEmotion.Where(f => CoreUtil.IsFaceBigEnoughForDetection(f.FaceRectangle.Height, this.DecodedImageHeight));
}
}
catch (Exception e)
{
// Implement #4: If there is an error, call the ErrorTrackingHelper helper class to record the issue.
// and return an empty emotion list
ErrorTrackingHelper.TrackException(e, "Emotion API RecognizeAsync error");
this.DetectedEmotion = Enumerable.Empty<Emotion>();
if (this.ShowDialogOnFaceApiErrors)
{
await ErrorTrackingHelper.GenericApiCallExceptionHandler(e, "Emotion detection failed.");
}
}
finally
{
// Implement #5: Call the event OnEmotionRecognitionCompleted
this.OnEmotionRecognitionCompleted();
}
}
private void OnEmotionRecognitionCompleted()
{
if (this.EmotionRecognitionCompleted != null)
{
this.EmotionRecognitionCompleted(this, EventArgs.Empty);
}
}
}
}

Просмотреть файл

@ -0,0 +1,63 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Resources;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ServiceHelpers")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ServiceHelpers")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Просмотреть файл

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{5D9320AF-A9E4-48E3-89BC-9F7F0954B298}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ServiceHelpers</RootNamespace>
<AssemblyName>ServiceHelpers</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Compile Include="CoreUtil.cs" />
<Compile Include="EmotionData.cs" />
<Compile Include="EmotionServiceHelper.cs" />
<Compile Include="ErrorTrackingHelper.cs" />
<Compile Include="ImageAnalyzer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.ProjectOxford.Common, Version=1.0.324.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.ProjectOxford.Common.1.0.324\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\Microsoft.ProjectOxford.Common.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.ProjectOxford.Emotion, Version=1.0.336.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.ProjectOxford.Emotion.1.0.336\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\Microsoft.ProjectOxford.Emotion.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.ProjectOxford.Face, Version=1.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.ProjectOxford.Face.1.2.5\lib\portable-net45+wp80+win8+wpa81+aspnetcore50\Microsoft.ProjectOxford.Face.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\portable-net45+win8\System.Net.Http.Extensions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Net.Http.Primitives, Version=4.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\portable-net45+win8\System.Net.Http.Primitives.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.ProjectOxford.Common" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.324.0" newVersion="1.0.324.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

Просмотреть файл

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="portable45-net45+win8" />
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="portable45-net45+win8" />
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="portable45-net45+win8" />
<package id="Microsoft.ProjectOxford.Common" version="1.0.324" targetFramework="portable45-net45+win8" />
<package id="Microsoft.ProjectOxford.Emotion" version="1.0.341" targetFramework="portable45-net45+win8" />
<package id="Microsoft.ProjectOxford.Face" version="1.3.0" targetFramework="portable45-net45+win8" />
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="portable45-net45+win8" />
</packages>

Просмотреть файл

@ -0,0 +1,197 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using IntelligentKioskSample.Views;
using System;
using System.ComponentModel;
using System.IO;
using Windows.Storage;
namespace IntelligentKioskSample
{
internal class SettingsHelper : INotifyPropertyChanged
{
public event EventHandler SettingsChanged;
public event PropertyChangedEventHandler PropertyChanged;
private static SettingsHelper instance;
static SettingsHelper()
{
instance = new SettingsHelper();
}
public void Initialize()
{
LoadRoamingSettings();
Windows.Storage.ApplicationData.Current.DataChanged += RoamingDataChanged;
}
private void RoamingDataChanged(ApplicationData sender, object args)
{
LoadRoamingSettings();
instance.OnSettingsChanged();
}
private void OnSettingsChanged()
{
if (instance.SettingsChanged != null)
{
instance.SettingsChanged(instance, EventArgs.Empty);
}
}
private async void OnSettingChanged(string propertyName, object value)
{
if (propertyName == "MallKioskDemoCustomSettings")
{
// save to file as the content is too big to be saved as a string-like setting
StorageFile file = await ApplicationData.Current.RoamingFolder.CreateFileAsync(
"MallKioskDemoCustomSettings.xml",
CreationCollisionOption.ReplaceExisting);
using (Stream stream = await file.OpenStreamForWriteAsync())
{
using (StreamWriter writer = new StreamWriter(stream))
{
await writer.WriteAsync(value.ToString());
}
}
}
else
{
ApplicationData.Current.RoamingSettings.Values[propertyName] = value;
}
instance.OnSettingsChanged();
instance.OnPropertyChanged(propertyName);
}
private void OnPropertyChanged(string propertyName)
{
if (instance.PropertyChanged != null)
{
instance.PropertyChanged(instance, new PropertyChangedEventArgs(propertyName));
}
}
public static SettingsHelper Instance
{
get
{
return instance;
}
}
private async void LoadRoamingSettings()
{
object value;
value = ApplicationData.Current.RoamingSettings.Values["EmotionApiKey"];
if (value != null)
{
this.EmotionApiKey = value.ToString();
}
value = ApplicationData.Current.RoamingSettings.Values["CameraName"];
if (value != null)
{
this.CameraName = value.ToString();
}
value = ApplicationData.Current.RoamingSettings.Values["MinDetectableFaceCoveragePercentage"];
if (value != null)
{
uint size;
if (uint.TryParse(value.ToString(), out size))
{
this.MinDetectableFaceCoveragePercentage = size;
}
}
value = ApplicationData.Current.RoamingSettings.Values["ShowDebugInfo"];
if (value != null)
{
bool booleanValue;
if (bool.TryParse(value.ToString(), out booleanValue))
{
this.ShowDebugInfo = booleanValue;
}
}
}
private string emotionApiKey = string.Empty;
public string EmotionApiKey
{
get { return this.emotionApiKey; }
set
{
this.emotionApiKey = value;
this.OnSettingChanged("EmotionApiKey", value);
}
}
private string cameraName = string.Empty;
public string CameraName
{
get { return cameraName; }
set
{
this.cameraName = value;
this.OnSettingChanged("CameraName", value);
}
}
private uint minDetectableFaceCoveragePercentage = 7;
public uint MinDetectableFaceCoveragePercentage
{
get { return this.minDetectableFaceCoveragePercentage; }
set
{
this.minDetectableFaceCoveragePercentage = value;
this.OnSettingChanged("MinDetectableFaceCoveragePercentage", value);
}
}
private bool showDebugInfo = false;
public bool ShowDebugInfo
{
get { return showDebugInfo; }
set
{
this.showDebugInfo = value;
this.OnSettingChanged("ShowDebugInfo", value);
}
}
}
}

Просмотреть файл

@ -0,0 +1,134 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IntelligentKioskSample">
<Style x:Key="SplitViewTogglePaneButtonStyle" TargetType="ToggleButton">
<Setter Property="FontSize" Value="20" />
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
<Setter Property="MinHeight" Value="48" />
<Setter Property="MinWidth" Value="48" />
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
<Setter Property="Content" Value="&#xE700;" />
<Setter Property="AutomationProperties.Name" Value="Menu" />
<Setter Property="UseSystemFocusVisuals" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid Background="{TemplateBinding Background}" x:Name="LayoutRoot">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(Grid.Background)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListLowBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(Grid.Background)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListMediumBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="(TextBlock.Foreground)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Checked"/>
<VisualState x:Name="CheckedPointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(Grid.Background)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListLowBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedPressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="(Grid.Background)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListMediumBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedDisabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="(TextBlock.Foreground)">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="ContentPresenter"
Content="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="PageTitleTextBlockStyle" TargetType="TextBlock" BasedOn="{StaticResource BodyTextBlockStyle}">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="CharacterSpacing" Value="75"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="Margin" Value="12, 14, 12, 4"/>
</Style>
<Style x:Key="NavigationBackButtonStyle" TargetType="Button" BasedOn="{StaticResource NavigationBackButtonNormalStyle}">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Height" Value="48"/>
<Setter Property="Width" Value="NaN"/>
<Setter Property="MinWidth" Value="48"/>
<Setter Property="AutomationProperties.Name" Value="Back"/>
<Setter Property="Content">
<Setter.Value>
<Grid x:Name="RootGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<FontIcon x:Name="Glyph" Grid.Column="0" FontSize="16" Glyph="&#xE0D5;" MirroredWhenRightToLeft="True" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock x:Name="Text" Grid.Column="1" Style="{ThemeResource BodyTextBlockStyle}" Text="Back" VerticalAlignment="Center" />
</Grid>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="NavMenuItemContainerStyle" TargetType="ListViewItem">
<Setter Property="MinWidth" Value="{StaticResource SplitViewCompactPaneThemeLength}"/>
<Setter Property="Height" Value="48"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ResourceDictionary>

Просмотреть файл

@ -0,0 +1,110 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using ServiceHelpers;
using Microsoft.ProjectOxford.Face;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Graphics.Display;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Popups;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using System.Runtime.InteropServices.WindowsRuntime;
using Microsoft.Rest;
namespace IntelligentKioskSample
{
internal static class Util
{
internal static async Task GenericApiCallExceptionHandler(Exception ex, string errorTitle)
{
string errorDetails = GetMessageFromException(ex);
await new MessageDialog(errorDetails, errorTitle).ShowAsync();
}
internal static string GetMessageFromException(Exception ex)
{
string errorDetails = ex.Message;
FaceAPIException faceApiException = ex as FaceAPIException;
if (faceApiException?.ErrorMessage != null)
{
errorDetails = faceApiException.ErrorMessage;
}
Microsoft.ProjectOxford.Common.ClientException commonException = ex as Microsoft.ProjectOxford.Common.ClientException;
if (commonException?.Error?.Message != null)
{
errorDetails = commonException.Error.Message;
}
HttpOperationException httpException = ex as HttpOperationException;
if (httpException?.Response?.ReasonPhrase != null)
{
errorDetails = string.Format("{0}. The error message was \"{1}\".", ex.Message, httpException?.Response?.ReasonPhrase);
}
return errorDetails;
}
public static async Task<IEnumerable<string>> GetAvailableCameraNamesAsync()
{
DeviceInformationCollection deviceInfo = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
return deviceInfo.OrderBy(d => d.Name).Select(d => d.Name);
}
internal static async Task<byte[]> GetPixelBytesFromSoftwareBitmapAsync(SoftwareBitmap softwareBitmap)
{
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
encoder.SetSoftwareBitmap(softwareBitmap);
await encoder.FlushAsync();
// Read the pixel bytes from the memory stream
using (var reader = new DataReader(stream.GetInputStreamAt(0)))
{
var bytes = new byte[stream.Size];
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(bytes);
return bytes;
}
}
}
}
}

Просмотреть файл

@ -0,0 +1,58 @@
<Page
x:Class="IntelligentKioskSample.Views.EmotionRecognitionPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IntelligentKioskSample.Views"
xmlns:ctl="using:IntelligentKioskSample.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<CommandBar x:Name="commandBar" VerticalAlignment="Top" HorizontalContentAlignment="Stretch">
<CommandBar.Content>
<ctl:PageHeader>
<ctl:PageHeader.HeaderContent>
<TextBlock Text="EMOTION API EXPLORER" Style="{ThemeResource PageTitleTextBlockStyle}" TextWrapping="NoWrap"/>
</ctl:PageHeader.HeaderContent>
</ctl:PageHeader>
</CommandBar.Content>
</CommandBar>
<Grid Grid.Row="1" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="0.3*"/>
<RowDefinition/>
<RowDefinition Height="0.3*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.1*"/>
<ColumnDefinition/>
<ColumnDefinition Width="0.1*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1" Grid.Row="1" x:Name="TxtStatusDescription" Text="{StaticResource TextStatus_Hi}" FontSize="18" HorizontalAlignment="Center" Foreground="{StaticResource StatusTextBrush}" MinHeight="16" MinWidth="96" Width="256" ></TextBlock>
<Grid Grid.Row="2" Grid.Column="1" x:Name="webCamHostGrid" Visibility="Collapsed" >
<!--HERE-->
<ctl:ImageWithFaceBorderUserControl BalloonBackground="#ECCF11" BalloonForeground="#D86C2A" FlowDirection="RightToLeft" x:Name="imageFromCameraWithFaces" ShowEmotionRecognition="True" DetectFacesOnLoad="True" ShowMultipleFaces="True" ShowRecognitionResults="True"/>
<ctl:CameraControl x:Name="cameraControl"
EnableAutoCaptureMode="True"/>
</Grid>
<ctl:ImageWithFaceBorderUserControl BalloonBackground="#ECCF11" BalloonForeground="#D86C2A" Grid.Row="1" Grid.Column="1" x:Name="imageWithFacesControl" ShowEmotionRecognition="True" DetectFacesOnLoad="True" ShowMultipleFaces="True" ShowRecognitionResults="True"/>
<ProgressRing Grid.Column="1" Grid.Row="3" x:Name="PrgRing1" Width="64" Height="64" />
</Grid>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,147 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using ServiceHelpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace IntelligentKioskSample.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class EmotionRecognitionPage : Page
{
public EmotionRecognitionPage()
{
this.InitializeComponent();
this.cameraControl.ImageCaptured += CameraControl_ImageCaptured;
this.cameraControl.CameraRestarted += CameraControl_CameraRestarted;
this.Loaded += EmotionRecognitionPage_Loaded;
this.imageFromCameraWithFaces.EmotionDetected += ImageFromCameraWithFaces_EmotionDetected;
}
private void ImageFromCameraWithFaces_EmotionDetected(object sender, EventArgs e)
{
// AFTER 10s RESET
var delay = Task.Delay(10000).ContinueWith(async _ =>
{
await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
//this.cameraControl.CameraControlButtonClick(this, new RoutedEventArgs());
this.cameraControl.RestartAutoCaptureCycle();
this.PrgRing1.IsActive = false;
});
});
}
private void EmotionRecognitionPage_Loaded(object sender, RoutedEventArgs e)
{
//this.cameraControl.RestartAutoCaptureCycle();
this.cameraControl.AutoCaptureStateChanged += CameraControl_AutoCaptureStateChanged;
}
private void CameraControl_AutoCaptureStateChanged(object sender, Controls.AutoCaptureState e)
{
var txt = "UNK";
if (e == Controls.AutoCaptureState.ShowingCapturedPhoto)
{
txt = "ShowingCapturedPhoto";
}
else if (e == Controls.AutoCaptureState.ShowingCountdownForCapture)
{
txt = "Thanks!";
PrgRing1.IsActive = true;
}
else if (e == Controls.AutoCaptureState.WaitingForFaces)
{
txt = "Hi, how are you doing?";
PrgRing1.IsActive = false;
}
else// if (e == Controls.AutoCaptureState.WaitingForStillFaces)
{
txt = "Please stand still...";
}
TxtStatusDescription.Text = txt;
}
private async void CameraControl_CameraRestarted(object sender, EventArgs e)
{
// We induce a delay here to give the camera some time to start rendering before we hide the last captured photo.
// This avoids a black flash.
await Task.Delay(500);
this.imageFromCameraWithFaces.Visibility = Visibility.Collapsed;
}
private async void CameraControl_ImageCaptured(object sender, ImageAnalyzer e)
{
this.imageFromCameraWithFaces.DataContext = e;
this.imageFromCameraWithFaces.Visibility = Visibility.Visible;
await this.cameraControl.StopStreamAsync();
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
await this.StartWebCameraAsync();
base.OnNavigatedTo(e);
}
private async Task StartWebCameraAsync()
{
webCamHostGrid.Visibility = Visibility.Visible;
imageWithFacesControl.Visibility = Visibility.Collapsed;
await this.cameraControl.StartStreamAsync();
await Task.Delay(250);
this.imageFromCameraWithFaces.Visibility = Visibility.Collapsed;
UpdateWebCamHostGridSize();
}
private void UpdateWebCamHostGridSize()
{
this.webCamHostGrid.Width = this.webCamHostGrid.ActualHeight * (this.cameraControl.CameraAspectRatio != 0 ? this.cameraControl.CameraAspectRatio : 1.777777777777);
}
}
}

Просмотреть файл

@ -0,0 +1,53 @@
<Page
x:Class="IntelligentKioskSample.Views.SettingsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IntelligentKioskSample.Views"
xmlns:ctl="using:IntelligentKioskSample.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<CommandBar x:Name="commandBar" VerticalAlignment="Top" HorizontalContentAlignment="Stretch">
<CommandBar.Content>
<ctl:PageHeader>
<ctl:PageHeader.HeaderContent>
<TextBlock Style="{ThemeResource PageTitleTextBlockStyle}" Text="SETTINGS"/>
</ctl:PageHeader.HeaderContent>
</ctl:PageHeader>
</CommandBar.Content>
</CommandBar>
<ScrollViewer Grid.Row="1">
<StackPanel Orientation="Vertical" Margin="12,12" >
<StackPanel >
<StackPanel Orientation="Horizontal">
<TextBlock Text="Keys" Style="{StaticResource SubheaderTextBlockStyle}"/>
<HyperlinkButton Margin="6,0,0,0" VerticalAlignment="Bottom" NavigateUri="https://azure.microsoft.com/en-us/try/cognitive-services/">Click here if you need keys</HyperlinkButton>
</StackPanel>
<PasswordBox Margin="0,10,0,0" Header="Emotion API Key" Password="{Binding EmotionApiKey, Mode=TwoWay}" />
</StackPanel>
<StackPanel Margin="0,50,0,0">
<TextBlock Text="Miscellaneous" Style="{StaticResource SubheaderTextBlockStyle}"/>
<ComboBox x:Name="cameraSourceComboBox" Header="Camera Source" SelectionChanged="OnCameraSourceSelectionChanged"/>
<ToggleSwitch IsOn="{Binding ShowDebugInfo, Mode=TwoWay}" Header="Show debug info:" Margin="0,6,0,0"/>
<StackPanel Orientation="Horizontal">
<Slider x:Name="MinDetectableFaceSizeSlider" Minimum="0" Maximum="100" Value="{Binding MinDetectableFaceCoveragePercentage, Mode=TwoWay}" SmallChange="1" LargeChange="5" Header="Minimum detectable face size (as % of image height):" HorizontalAlignment="Left" Margin="0,0,0,0" StepFrequency="1"/>
<TextBlock Text="{Binding ElementName=MinDetectableFaceSizeSlider, Path=Value}" Style="{StaticResource TitleTextBlockStyle}" VerticalAlignment="Center" Margin="12,0,0,0"/>
</StackPanel>
</StackPanel>
</StackPanel>
</ScrollViewer>
</Grid>
</Page>

Просмотреть файл

@ -0,0 +1,72 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license.
//
// Microsoft Cognitive Services: http://www.microsoft.com/cognitive
//
// Microsoft Cognitive Services Github:
// https://github.com/Microsoft/Cognitive
//
// Copyright (c) Microsoft Corporation
// All rights reserved.
//
// MIT License:
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace IntelligentKioskSample.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class SettingsPage : Page
{
public SettingsPage()
{
this.InitializeComponent();
this.DataContext = SettingsHelper.Instance;
}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
this.cameraSourceComboBox.ItemsSource = await Util.GetAvailableCameraNamesAsync();
this.cameraSourceComboBox.SelectedItem = SettingsHelper.Instance.CameraName;
base.OnNavigatedFrom(e);
}
private void OnCameraSourceSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (this.cameraSourceComboBox.SelectedItem != null)
{
SettingsHelper.Instance.CameraName = this.cameraSourceComboBox.SelectedItem.ToString();
}
}
}
}

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="portable45-net45+win8" />
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="portable45-net45+win8" />
<package id="Microsoft.Net.Http" version="2.2.29" targetFramework="portable45-net45+win8" />
</packages>

Просмотреть файл

@ -0,0 +1,23 @@
{
"dependencies": {
"Microsoft.Bcl.Build": "1.0.21",
"Microsoft.NETCore.UniversalWindowsPlatform": "5.2.3",
"Microsoft.ProjectOxford.Emotion": "1.0.336",
"Microsoft.ProjectOxford.Face": "1.2.5",
"Microsoft.Rest.ClientRuntime": "2.3.10",
"Newtonsoft.Json": "9.0.1",
"System.Net.NameResolution": "4.3.0",
"WriteableBitmapEx": "1.5.0"
},
"frameworks": {
"uap10.0.10240": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {},
"win10-x86": {},
"win10-x86-aot": {},
"win10-x64": {},
"win10-x64-aot": {}
}
}

Просмотреть файл

@ -0,0 +1,39 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2006
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContosoHelpdeskChatBot", "ContosoHelpdeskChatBot\ContosoHelpdeskChatBot.csproj", "{7CEA9614-BE08-47A8-9175-E858235B6231}"
EndProject
Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "ContosoHelpdeskData", "ContosoHelpdeskData\ContosoHelpdeskData.sqlproj", "{ACE2D83E-26AB-490E-B6C3-737AC7F49975}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContosoHelpdeskSms", "ContosoHelpdeskSms\ContosoHelpdeskSms.csproj", "{DC4B0541-A167-4AF2-A5BF-D21D9379AE54}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7CEA9614-BE08-47A8-9175-E858235B6231}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7CEA9614-BE08-47A8-9175-E858235B6231}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CEA9614-BE08-47A8-9175-E858235B6231}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CEA9614-BE08-47A8-9175-E858235B6231}.Release|Any CPU.Build.0 = Release|Any CPU
{ACE2D83E-26AB-490E-B6C3-737AC7F49975}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ACE2D83E-26AB-490E-B6C3-737AC7F49975}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ACE2D83E-26AB-490E-B6C3-737AC7F49975}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{ACE2D83E-26AB-490E-B6C3-737AC7F49975}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ACE2D83E-26AB-490E-B6C3-737AC7F49975}.Release|Any CPU.Build.0 = Release|Any CPU
{ACE2D83E-26AB-490E-B6C3-737AC7F49975}.Release|Any CPU.Deploy.0 = Release|Any CPU
{DC4B0541-A167-4AF2-A5BF-D21D9379AE54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC4B0541-A167-4AF2-A5BF-D21D9379AE54}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC4B0541-A167-4AF2-A5BF-D21D9379AE54}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC4B0541-A167-4AF2-A5BF-D21D9379AE54}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2D8005E5-57DD-4910-950A-5950E0BF8DAA}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,37 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace ContosoHelpdeskChatBot
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Json settings
config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.Formatters.JsonFormatter.SerializerSettings.Formatting = Formatting.Indented;
JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Formatting = Newtonsoft.Json.Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore,
};
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}

Просмотреть файл

@ -0,0 +1,203 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{7CEA9614-BE08-47A8-9175-E858235B6231}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ContosoHelpdeskChatBot</RootNamespace>
<AssemblyName>Bot Application</AssemblyName>
<TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion>
<UseIISExpress>true</UseIISExpress>
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
<Use64BitIISExpress />
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Autofac, Version=4.6.2.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
<HintPath>..\packages\Autofac.4.6.2\lib\net45\Autofac.dll</HintPath>
</Reference>
<Reference Include="Chronic, Version=0.3.2.0, Culture=neutral, PublicKeyToken=3bd1f1ef638b0d3c, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Chronic.Signed.0.3.2\lib\net40\Chronic.dll</HintPath>
</Reference>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath>
</Reference>
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bot.Builder, Version=3.11.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bot.Builder.3.11.0\lib\net46\Microsoft.Bot.Builder.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bot.Builder.Autofac, Version=3.10.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bot.Builder.3.11.0\lib\net46\Microsoft.Bot.Builder.Autofac.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bot.Connector, Version=3.11.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bot.Connector.3.11.1\lib\net45\Microsoft.Bot.Connector.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.IdentityModel.Protocol.Extensions, Version=1.0.40306.1554, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Microsoft.IdentityModel.Protocol.Extensions.1.0.4.403061554\lib\net45\Microsoft.IdentityModel.Protocol.Extensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Rest.ClientRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Rest.ClientRuntime.2.3.10\lib\net452\Microsoft.Rest.ClientRuntime.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAzure.Configuration, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.WindowsAzure.ConfigurationManager.3.2.3\lib\net40\Microsoft.WindowsAzure.Configuration.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.IdentityModel.Tokens.Jwt, Version=4.0.40306.1554, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\System.IdentityModel.Tokens.Jwt.4.0.4.403061554\lib\net45\System.IdentityModel.Tokens.Jwt.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Numerics" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Security" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Web.Http, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http.WebHost, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="System.Web.Services" />
<Reference Include="System.EnterpriseServices" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Content Include="default.htm" />
<Content Include="Global.asax" />
<Content Include="Web.config">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<ItemGroup>
<Compile Include="App_Start\WebApiConfig.cs" />
<Compile Include="Controllers\MessagesController.cs" />
<Compile Include="Dialogs\LocalAdminDialog.cs" />
<Compile Include="Dialogs\ResetPasswordDialog.cs" />
<Compile Include="Models\AppMsi.cs" />
<Compile Include="Models\ContosoHelpdeskContext.cs" />
<Compile Include="Models\InstallApp.cs" />
<Compile Include="Models\LocalAdmin.cs" />
<Compile Include="Models\LocalAdminPrompt.cs" />
<Compile Include="Models\Log.cs" />
<Compile Include="Models\ResetPassword.cs" />
<Compile Include="Dialogs\CancelScorable.cs" />
<Compile Include="Dialogs\InstallAppDialog.cs" />
<Compile Include="Dialogs\RootDialog.cs" />
<Compile Include="Global.asax.cs">
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="GlobalMessageHandlersBotModule.cs" />
<Compile Include="Models\ResetPasswordPrompt.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="packages.config">
<SubType>Designer</SubType>
</Content>
<None Include="Web.Debug.config">
<DependentUpon>Web.config</DependentUpon>
</None>
<None Include="Web.Release.config">
<DependentUpon>Web.config</DependentUpon>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ContosoHelpdeskSms\ContosoHelpdeskSms.csproj">
<Project>{dc4b0541-a167-4af2-a5bf-d21d9379ae54}</Project>
<Name>ContosoHelpdeskSms</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<PropertyGroup>
<EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>3979</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:3979/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

Просмотреть файл

@ -0,0 +1,63 @@
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using System;
namespace ContosoHelpdeskChatBot
{
[BotAuthentication]
public class MessagesController : ApiController
{
/// <summary>
/// POST: api/Messages
/// Receive a message from a user and reply to it
/// </summary>
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
}
else
{
HandleSystemMessage(activity);
}
var response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
private Activity HandleSystemMessage(Activity message)
{
if (message.Type == ActivityTypes.DeleteUserData)
{
// Implement user deletion here
// If we handle user deletion, return a real message
}
else if (message.Type == ActivityTypes.ConversationUpdate)
{
// Handle conversation state changes, like members being added and removed
// Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
// Not available in all channels
}
else if (message.Type == ActivityTypes.ContactRelationUpdate)
{
// Handle add/remove from contact lists
// Activity.From + Activity.Action represent what happened
}
else if (message.Type == ActivityTypes.Typing)
{
// Handle knowing tha the user is typing
}
else if (message.Type == ActivityTypes.Ping)
{
}
return null;
}
}
}

Просмотреть файл

@ -0,0 +1,65 @@
namespace ContosoHelpdeskChatBot.Dialogs
{
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs.Internals;
using Microsoft.Bot.Builder.Internals.Fibers;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Builder.Scorables.Internals;
using Autofac;
#pragma warning disable 1998
public class CancelScorable : ScorableBase<IActivity, string, double>
{
private readonly IDialogTask task;
public CancelScorable(IDialogTask task)
{
SetField.NotNull(out this.task, nameof(task), task);
}
protected override async Task<string> PrepareAsync(IActivity activity, CancellationToken token)
{
var message = activity as IMessageActivity;
if (message != null && !string.IsNullOrWhiteSpace(message.Text))
{
if (message.Text.Equals("cancel", StringComparison.InvariantCultureIgnoreCase))
{
return message.Text;
}
}
return null;
}
protected override bool HasScore(IActivity item, string state)
{
return state != null;
}
protected override double GetScore(IActivity item, string state)
{
return 1.0;
}
protected override async Task PostAsync(IActivity item, string state, CancellationToken token)
{
var activity = (Activity)item;
var reply = activity.CreateReply($"Ok restarting conversation.");
//Refer to Connector service
//https://docs.microsoft.com/en-us/bot-framework/dotnet/bot-builder-dotnet-connector
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
await connector.Conversations.ReplyToActivityAsync(reply);
this.task.Reset();
}
protected override Task DoneAsync(IActivity item, string state, CancellationToken token)
{
return Task.CompletedTask;
}
}
}

Просмотреть файл

@ -0,0 +1,122 @@
namespace ContosoHelpdeskChatBot.Dialogs
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.FormFlow;
using Microsoft.Bot.Connector;
using ContosoHelpdeskChatBot.Models;
[Serializable]
public class InstallAppDialog : IDialog<object>
{
private Models.InstallApp install = new InstallApp();
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("Ok let's get started. What is the name of the application? ");
context.Wait(appNameAsync);
}
private async Task appNameAsync(IDialogContext context, IAwaitable<IMessageActivity> userReply)
{
//this will trigger a wait for user's reply
//in this case we are waiting for an app name which will be used as keyword to search the AppMsi table
var message = await userReply;
var appname = message.Text;
var names = await this.getAppsAsync(appname);
if (names.Count == 1)
{
install.AppName = names.First();
await context.PostAsync($"Found {install.AppName}. What is the name of the machine to install application?");
context.Wait(machineNameAsync);
}
else if (names.Count > 1)
{
string appnames = "";
for (int i = 0; i < names.Count; i++)
{
appnames += $"<br/>&nbsp;&nbsp;&nbsp;{i + 1}.&nbsp;" + names[i];
}
await context.PostAsync($"I found {names.Count()} applications.<br/> {appnames}<br/> Please reply 1 - {names.Count()} to indicate your choice.");
//at a conversation scope, store state data in ConversationData
context.ConversationData.SetValue("AppList", names);
context.Wait(multipleAppsAsync);
}
else
{
await context.PostAsync($"Sorry, I did not find any application with the name \"{appname}\".");
context.Done<object>(null);
}
}
private async Task multipleAppsAsync(IDialogContext context, IAwaitable<IMessageActivity> userReply)
{
//this will trigger a wait for user's reply
//here we ask the user which specific app to install when we found more than one
var message = await userReply;
int choice;
var isNum = int.TryParse(message.Text, out choice);
List<string> applist;
context.ConversationData.TryGetValue("AppList", out applist);
if (isNum && choice <= applist.Count && choice > 0)
{
//minus becoz index zero base
this.install.AppName = applist[choice - 1];
await context.PostAsync($"What is the name of the machine to install?");
context.Wait(machineNameAsync);
}
else
{
await context.PostAsync($"Invalid response. Please reply 1 - {applist.Count()} to indicate your choice.");
context.Wait(multipleAppsAsync);
}
}
private async Task machineNameAsync(IDialogContext context, IAwaitable<IMessageActivity> userReply)
{
//this will trigger a wait for user's reply
//finally we ask for the machine name on which to install the app
var message = await userReply;
var machinename = message.Text;
this.install.MachineName = machinename;
//TODO: Save to database
using (var db = new ContosoHelpdeskContext())
{
db.InstallApps.Add(install);
db.SaveChanges();
}
await context.PostAsync($"Great, your request to install {this.install.AppName} on {this.install.MachineName} has been scheduled.");
context.Done<object>(null);
}
private async Task<List<string>> getAppsAsync(string Name)
{
//TODO: Add EF to lookup database
var names = new List<string>();
using (var db = new ContosoHelpdeskContext())
{
names = (from app in db.AppMsis
where app.AppName.ToLower().Contains(Name.ToLower())
select app.AppName).ToList();
}
return names;
}
}
}

Просмотреть файл

@ -0,0 +1,60 @@
using System;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using ContosoHelpdeskChatBot.Models;
using Microsoft.Bot.Builder.FormFlow;
namespace ContosoHelpdeskChatBot.Dialogs
{
[Serializable]
public class LocalAdminDialog : IDialog<object>
{
private LocalAdmin admin = new LocalAdmin();
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("Great I will help you request local machine admin.");
var localAdminDialog = FormDialog.FromForm(this.BuildLocalAdminForm, FormOptions.PromptInStart);
context.Call(localAdminDialog, this.ResumeAfterLocalAdminFormDialog);
}
private async Task ResumeAfterLocalAdminFormDialog(IDialogContext context, IAwaitable<LocalAdminPrompt> userReply)
{
using (var db = new ContosoHelpdeskContext())
{
db.LocalAdmins.Add(admin);
db.SaveChanges();
}
context.Done<object>(null);
}
private IForm<LocalAdminPrompt> BuildLocalAdminForm()
{
//here's an example of how validation can be used in form builder
return new FormBuilder<LocalAdminPrompt>()
.Field(nameof(LocalAdminPrompt.MachineName),
validate: async (state, value) =>
{
var result = new ValidateResult { IsValid = true, Value = value };
//add validation here
this.admin.MachineName = (string)value;
return result;
})
.Field(nameof(LocalAdminPrompt.AdminDuration),
validate: async (state, value) =>
{
var result = new ValidateResult { IsValid = true, Value = value };
//add validation here
this.admin.AdminDuration = Convert.ToInt32((long)value) as int?;
return result;
})
.Build();
}
}
}

Просмотреть файл

@ -0,0 +1,94 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using Microsoft.Bot.Builder.FormFlow;
using ContosoHelpdeskChatBot.Models;
using ContosoHelpdeskSms;
namespace ContosoHelpdeskChatBot.Dialogs
{
[Serializable]
public class ResetPasswordDialog : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
await context.PostAsync("Alright I will help you create a temp password");
if (sendPassCode(context))
{
var resetPasswordDialog = FormDialog.FromForm(this.BuildResetPasswordForm, FormOptions.PromptInStart);
context.Call(resetPasswordDialog, this.ResumeAfterResetPasswordFormDialog);
}
else
{
//here we can simply fail the current dialog because we have root dialog handling all exceptions
context.Fail(new Exception("Failed to send SMS. Make sure email & phone number has been added to database."));
}
}
private bool sendPassCode(IDialogContext context)
{
bool result = false;
//Recipient Id varies depending on channel
//refer ChannelAccount class https://docs.botframework.com/en-us/csharp/builder/sdkreference/dd/def/class_microsoft_1_1_bot_1_1_connector_1_1_channel_account.html#a0b89cf01fdd73cbc00a524dce9e2ad1a
//as well as Activity class https://docs.botframework.com/en-us/csharp/builder/sdkreference/dc/d2f/class_microsoft_1_1_bot_1_1_connector_1_1_activity.html
var email = context.Activity.From.Id;
int passcode = new Random().Next(1000, 9999);
Int64? smsNumber = 0;
string smsMessage = "Your Contoso Pass Code is ";
string countryDialPrefix = "+1";
//save PassCode to database
using (var db = new ContosoHelpdeskContext())
{
var reset = db.ResetPasswords.Where(r => r.EmailAddress == email).ToList();
if (reset.Count >= 1)
{
reset.First().PassCode = passcode;
smsNumber = reset.First().MobileNumber;
result = true;
}
db.SaveChanges();
}
if (result)
{
result = Helper.SendSms($"{countryDialPrefix}{smsNumber.ToString()}", $"{smsMessage} {passcode}");
}
return result;
}
private IForm<ResetPasswordPrompt> BuildResetPasswordForm()
{
return new FormBuilder<ResetPasswordPrompt>()
.Field(nameof(ResetPasswordPrompt.PassCode))
.Build();
}
private async Task ResumeAfterResetPasswordFormDialog(IDialogContext context, IAwaitable<ResetPasswordPrompt> userReply)
{
var prompt = await userReply;
var email = context.Activity.From.Id;
int? passcode;
using (var db = new ContosoHelpdeskContext())
{
passcode = db.ResetPasswords.Where(r => r.EmailAddress == email).First().PassCode;
}
if (prompt.PassCode == passcode)
{
string temppwd = "TempPwd" + new Random().Next(0, 5000);
await context.PostAsync($"Your temp password is {temppwd}");
}
context.Done<object>(null);
}
}
}

Просмотреть файл

@ -0,0 +1,90 @@
namespace ContosoHelpdeskChatBot.Dialogs
{
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
[Serializable]
public class RootDialog : IDialog<object>
{
private static log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private const string InstallAppOption = "Install Application (install)";
private const string ResetPasswordOption = "Reset Password (password)";
private const string LocalAdminOption = "Request Local Admin (admin)";
private const string GreetMessage = "Welcome to **Contoso Helpdesk Chat Bot**.\n\nI am designed to use with mobile email app, make sure your replies do not contain signatures. \n\nFollowing is what I can help you with, just reply with word in parenthesis:";
private const string ErrorMessage = "Not a valid option";
private static List<string> HelpdeskOptions = new List<string>()
{
InstallAppOption,
ResetPasswordOption,
LocalAdminOption
};
public async Task StartAsync(IDialogContext context)
{
context.Wait(this.MessageReceivedAsync);
}
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> userReply)
{
var message = await userReply;
this.ShowOptions(context);
}
private void ShowOptions(IDialogContext context)
{
PromptDialog.Choice(context, this.OnOptionSelected, HelpdeskOptions, GreetMessage, ErrorMessage, 3, PromptStyle.PerLine);
}
private async Task OnOptionSelected(IDialogContext context, IAwaitable<string> userReply)
{
try
{
string optionSelected = await userReply;
switch (optionSelected)
{
case InstallAppOption:
context.Call(new InstallAppDialog(), this.ResumeAfterOptionDialog);
break;
case ResetPasswordOption:
context.Call(new ResetPasswordDialog(), this.ResumeAfterOptionDialog);
break;
case LocalAdminOption:
context.Call(new LocalAdminDialog(), this.ResumeAfterOptionDialog);
break;
}
}
catch (TooManyAttemptsException ex)
{
await context.PostAsync($"Ooops! Too many attemps :(. But don't worry, I'm handling that exception and you can try again!");
context.Wait(this.MessageReceivedAsync);
}
}
private async Task ResumeAfterOptionDialog(IDialogContext context, IAwaitable<object> userReply)
{
try
{
var message = await userReply;
var ticketNumber = new Random().Next(0, 20000);
await context.PostAsync($"Thank you for using the Helpdesk Bot. Your ticket number is {ticketNumber}.");
context.Done(ticketNumber);
}
catch (Exception ex)
{
await context.PostAsync($"Failed with message: {ex.Message}");
// In general resume from task after calling a child dialog is a good place to handle exceptions
// try catch will capture exceptions from the bot framework awaitable object which is essentially "userReply"
logger.Error(ex);
}
}
}
}

Просмотреть файл

@ -0,0 +1 @@
<%@ Application Codebehind="Global.asax.cs" Inherits="ContosoHelpdeskChatBot.WebApiApplication" Language="C#" %>

Просмотреть файл

@ -0,0 +1,55 @@
using Autofac;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Dialogs.Internals;
using Microsoft.Bot.Builder.Internals.Fibers;
using Microsoft.Bot.Connector;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Routing;
namespace ContosoHelpdeskChatBot
{
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
BotConfig.UpdateConversationContainer();
this.RegisterBotModules();
log4net.Config.XmlConfigurator.Configure();
}
//setting Bot data store policy to use last write win
//example if bot service got restarted, existing conversation would just overwrite data to store
public static class BotConfig
{
public static void UpdateConversationContainer()
{
var builder = new ContainerBuilder();
builder.Register(c => new CachingBotDataStore(c.ResolveKeyed<IBotDataStore<BotData>>(typeof(ConnectorStore)),
CachingBotDataStoreConsistencyPolicy.LastWriteWins))
.As<IBotDataStore<BotData>>()
.AsSelf()
.InstancePerLifetimeScope();
builder.Update(Conversation.Container);
}
}
private void RegisterBotModules()
{
Conversation.UpdateContainer(builder =>
{
builder.RegisterModule(new ReflectionSurrogateModule());
builder.RegisterModule<GlobalMessageHandlersBotModule>();
});
}
}
}

Просмотреть файл

@ -0,0 +1,21 @@
namespace ContosoHelpdeskChatBot
{
using Autofac;
using Dialogs;
using Microsoft.Bot.Builder.Dialogs.Internals;
using Microsoft.Bot.Builder.Scorables;
using Microsoft.Bot.Connector;
public class GlobalMessageHandlersBotModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder
.Register(c => new CancelScorable(c.Resolve<IDialogTask>()))
.As<IScorable<IActivity, double>>()
.InstancePerLifetimeScope();
}
}
}

Просмотреть файл

@ -0,0 +1,19 @@
namespace ContosoHelpdeskChatBot.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
[Table("AppMsi")]
public partial class AppMsi
{
[Key]
public int Id { get; set; }
public string AppName { get; set; }
public string MsiPackage { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,44 @@
namespace ContosoHelpdeskChatBot.Models
{
using System;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
public partial class ContosoHelpdeskContext : DbContext
{
public ContosoHelpdeskContext()
: base("name=ContosoHelpdeskContext")
{
}
public virtual DbSet<AppMsi> AppMsis { get; set; }
public virtual DbSet<InstallApp> InstallApps { get; set; }
public virtual DbSet<LocalAdmin> LocalAdmins { get; set; }
public virtual DbSet<Log> Logs { get; set; }
public virtual DbSet<ResetPassword> ResetPasswords { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<AppMsi>()
.Property(e => e.AppName)
.IsUnicode(false);
modelBuilder.Entity<AppMsi>()
.Property(e => e.MsiPackage)
.IsUnicode(false);
modelBuilder.Entity<InstallApp>()
.Property(e => e.AppName)
.IsUnicode(false);
modelBuilder.Entity<InstallApp>()
.Property(e => e.MachineName)
.IsUnicode(false);
modelBuilder.Entity<ResetPassword>()
.Property(e => e.EmailAddress)
.IsUnicode(false);
}
}
}

Просмотреть файл

@ -0,0 +1,19 @@
namespace ContosoHelpdeskChatBot.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
[Table("InstallApp")]
public partial class InstallApp
{
[Key]
public int Id { get; set; }
public string AppName { get; set; }
public string MachineName { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,19 @@
namespace ContosoHelpdeskChatBot.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
[Table("LocalAdmin")]
public partial class LocalAdmin
{
[Key]
public int Id { get; set; }
public string MachineName { get; set; }
public int? AdminDuration { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.Bot.Builder.FormFlow;
namespace ContosoHelpdeskChatBot.Models
{
public class LocalAdminPrompt
{
[Prompt("What is the machine name to add you to local admin group?")]
public string MachineName { get; set; }
[Prompt("How many days do you need the admin access?")]
public int? AdminDuration { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,23 @@
namespace ContosoHelpdeskChatBot.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
[Table("Log")]
public partial class Log
{
[Key]
public int Id { get; set; }
public DateTime Date { get; set; }
public string Level { get; set; }
public string Message { get; set; }
public string Exception { get; set; }
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше