Merge pull request #2 from Affectiva/affdexme
Merging AffdexMe SDK demo to master
This commit is contained in:
commit
00af1ee714
17 changed files with 1570 additions and 2 deletions
116
AffdexMe/AffdexMe.csproj
Normal file
116
AffdexMe/AffdexMe.csproj
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
<?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>
|
||||||
|
<ProjectGuid>{5B893EA1-EB11-425A-BF8A-05822F5E2C9A}</ProjectGuid>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>AffdexMe</RootNamespace>
|
||||||
|
<AssemblyName>AffdexMe</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>x86</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>
|
||||||
|
<ApplicationIcon>$(ProjectDir)Resources\AffdexMe_Logo.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
|
||||||
|
<Reference Include="Affdex" Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<HintPath>..\..\Program Files (x86)\Affectiva\Affdex SDK\bin\debug\Affdex.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Affdex" Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<HintPath>..\..\Program Files (x86)\Affectiva\Affdex SDK\bin\release\Affdex.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
|
||||||
|
<Reference Include="Microsoft.VisualBasic" />
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="System.Xaml">
|
||||||
|
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="WindowsBase" />
|
||||||
|
<Reference Include="PresentationCore" />
|
||||||
|
<Reference Include="PresentationFramework" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Include="$(ProjectDir)MainWindow.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
|
<Compile Include="App.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="$(ProjectDir)MainWindow.xaml.cs">
|
||||||
|
<DependentUpon>$(ProjectDir)MainWindow.xaml</DependentUpon>
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="$(ProjectDir)Properties\AssemblyInfo.cs">
|
||||||
|
<SubType>Code</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="$(ProjectDir)Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="$(ProjectDir)Properties\Settings.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>$(ProjectDir)Settings.settings</DependentUpon>
|
||||||
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
|
</Compile>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>$(ProjectDir)Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<Resource Include="$(ProjectDir)Fonts\Square.ttf" />
|
||||||
|
<None Include="$(ProjectDir)Properties\Settings.settings">
|
||||||
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
<LastGenOutput>$(ProjectDir)Settings.Designer.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
<AppDesigner Include="$(ProjectDir)Properties\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="$(ProjectDir)App.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="$(ProjectDir)Resources\AffectivaLogo1.png" />
|
||||||
|
<Resource Include="$(ProjectDir)Resources\AffdexMe_Logo.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.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>
|
6
AffdexMe/App.config
Normal file
6
AffdexMe/App.config
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||||
|
</startup>
|
||||||
|
</configuration>
|
82
AffdexMe/App.cs
Normal file
82
AffdexMe/App.cs
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
using Microsoft.VisualBasic.ApplicationServices;
|
||||||
|
|
||||||
|
namespace AffdexMe
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for App.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// From reference source: https://msdn.microsoft.com/en-us/library/vstudio/ms771662(v=vs.90).aspx
|
||||||
|
/// </summary>
|
||||||
|
public class EntryPoint
|
||||||
|
{
|
||||||
|
[STAThread]
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
SingleInstanceManager manager = new SingleInstanceManager();
|
||||||
|
manager.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using VB bits to detect single instances and process accordingly:
|
||||||
|
// * OnStartup is fired when the first instance loads
|
||||||
|
// * OnStartupNextInstance is fired when the application is re-run again
|
||||||
|
// NOTE: it is redirected to this instance thanks to IsSingleInstance
|
||||||
|
public class SingleInstanceManager : WindowsFormsApplicationBase
|
||||||
|
{
|
||||||
|
SingleInstanceApplication app;
|
||||||
|
|
||||||
|
public SingleInstanceManager()
|
||||||
|
{
|
||||||
|
this.IsSingleInstance = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
|
||||||
|
{
|
||||||
|
// First time app is launched
|
||||||
|
app = new SingleInstanceApplication();
|
||||||
|
app.Run();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
// Subsequent launches
|
||||||
|
base.OnStartupNextInstance(eventArgs);
|
||||||
|
app.Activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SingleInstanceApplication : Application
|
||||||
|
{
|
||||||
|
|
||||||
|
protected override void OnStartup(System.Windows.StartupEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnStartup(e);
|
||||||
|
|
||||||
|
// Create and show the application's main window
|
||||||
|
MainWindow window = new MainWindow();
|
||||||
|
window.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Activate()
|
||||||
|
{
|
||||||
|
// Reactivate application's main window
|
||||||
|
this.MainWindow.Activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
AffdexMe/App.xaml
Normal file
8
AffdexMe/App.xaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<Application x:Class="AffdexMe.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
StartupUri="MainWindow.xaml">
|
||||||
|
<Application.Resources>
|
||||||
|
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
17
AffdexMe/App.xaml.cs
Normal file
17
AffdexMe/App.xaml.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Configuration;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace AffdexMe
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for App.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
BIN
AffdexMe/Fonts/Square.ttf
Normal file
BIN
AffdexMe/Fonts/Square.ttf
Normal file
Binary file not shown.
248
AffdexMe/MainWindow.xaml
Normal file
248
AffdexMe/MainWindow.xaml
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
<Window x:Class="AffdexMe.MainWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
Title="AffdexMe"
|
||||||
|
Height="640" Width="480"
|
||||||
|
MinHeight="640" MinWidth="480"
|
||||||
|
MaxHeight="640" MaxWidth="480"
|
||||||
|
ResizeMode="NoResize"
|
||||||
|
Loaded="Window_Loaded"
|
||||||
|
Closing="Window_Closing">
|
||||||
|
|
||||||
|
|
||||||
|
<Window.Resources>
|
||||||
|
<Style TargetType="{x:Type ButtonBase}" x:Key="CustomButtonStyle">
|
||||||
|
<Setter Property="Foreground" Value="White"/>
|
||||||
|
<Setter Property="Background">
|
||||||
|
<Setter.Value>
|
||||||
|
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
|
||||||
|
<GradientStop Color="#FF2778BB" Offset="0.51"/>
|
||||||
|
<GradientStop Color="#FF2683C5" Offset="0.484"/>
|
||||||
|
<GradientStop Color="#FF8CD4FF" Offset="1"/>
|
||||||
|
<GradientStop Color="#FF1973AE" Offset="0.497"/>
|
||||||
|
</LinearGradientBrush>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Setter Property="Cursor" Value="Hand"/>
|
||||||
|
<Setter Property="BorderBrush" Value="#FF2B5F91"/>
|
||||||
|
<Setter Property="Margin" Value="1"/>
|
||||||
|
<Setter Property="Height" Value="30"/>
|
||||||
|
<Setter Property="MinWidth" Value="20"/>
|
||||||
|
<Setter Property="FontSize" Value="13"/>
|
||||||
|
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="{x:Type Button}">
|
||||||
|
<Grid>
|
||||||
|
<Rectangle Stroke="{TemplateBinding BorderBrush}" RadiusX="15" RadiusY="15" Fill="{TemplateBinding Background}"/>
|
||||||
|
<Rectangle VerticalAlignment="Top" Height="10" Margin="7,2,7,1" RadiusX="10" RadiusY="10">
|
||||||
|
<Rectangle.Fill>
|
||||||
|
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
|
||||||
|
<GradientStop Color="#11FFFFFF" Offset="1"/>
|
||||||
|
<GradientStop Color="#B2FFFFFF" Offset="0"/>
|
||||||
|
</LinearGradientBrush>
|
||||||
|
</Rectangle.Fill>
|
||||||
|
</Rectangle>
|
||||||
|
<Rectangle x:Name="rectangle" RadiusX="15" RadiusY="15" Fill="White" Margin="1" Opacity="0"/>
|
||||||
|
<ContentPresenter x:Name="contentPresenter" HorizontalAlignment="Center" VerticalAlignment="Center" IsHitTestVisible="False" Margin="{TemplateBinding Padding}"/>
|
||||||
|
</Grid>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Opacity" TargetName="rectangle" Value="0.2"/>
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsPressed" Value="True">
|
||||||
|
<Setter Property="Opacity" TargetName="rectangle" Value="0.3"/>
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsEnabled" Value="False">
|
||||||
|
<Setter Property="Fill" TargetName="rectangle" Value="#666"/>
|
||||||
|
<Setter Property="Opacity" TargetName="rectangle" Value="0.6"/>
|
||||||
|
<Setter Property="Opacity" TargetName="contentPresenter" Value="0.3"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="{x:Type ButtonBase}" x:Key="PointsOnButtonStyle">
|
||||||
|
<Setter Property="Foreground" Value="White"/>
|
||||||
|
<Setter Property="Background">
|
||||||
|
<Setter.Value>
|
||||||
|
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
|
||||||
|
<GradientStop Color="#FF3CB371" Offset="0.51"/>
|
||||||
|
<GradientStop Color="#FF3CB371" Offset="0.484"/>
|
||||||
|
<GradientStop Color="#FF3CB371" Offset="1"/>
|
||||||
|
<GradientStop Color="#FF1973AE" Offset="0.497"/>
|
||||||
|
</LinearGradientBrush>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Setter Property="Cursor" Value="Hand"/>
|
||||||
|
<Setter Property="BorderBrush" Value="#FF2B5F91"/>
|
||||||
|
<Setter Property="Margin" Value="1"/>
|
||||||
|
<Setter Property="Height" Value="30"/>
|
||||||
|
<Setter Property="MinWidth" Value="20"/>
|
||||||
|
<Setter Property="FontSize" Value="13"/>
|
||||||
|
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="{x:Type Button}">
|
||||||
|
<Grid>
|
||||||
|
<Rectangle Stroke="{TemplateBinding BorderBrush}" RadiusX="15" RadiusY="15" Fill="{TemplateBinding Background}"/>
|
||||||
|
<Rectangle VerticalAlignment="Top" Height="10" Margin="7,2,7,1" RadiusX="10" RadiusY="10">
|
||||||
|
<Rectangle.Fill>
|
||||||
|
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
|
||||||
|
<GradientStop Color="#11FFFFFF" Offset="1"/>
|
||||||
|
<GradientStop Color="#B2FFFFFF" Offset="0"/>
|
||||||
|
</LinearGradientBrush>
|
||||||
|
</Rectangle.Fill>
|
||||||
|
</Rectangle>
|
||||||
|
<Rectangle x:Name="rectangle" RadiusX="15" RadiusY="15" Fill="White" Margin="1" Opacity="0"/>
|
||||||
|
<ContentPresenter x:Name="contentPresenter" HorizontalAlignment="Center" VerticalAlignment="Center" IsHitTestVisible="False" Margin="{TemplateBinding Padding}"/>
|
||||||
|
</Grid>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter Property="Opacity" TargetName="rectangle" Value="0.2"/>
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsPressed" Value="True">
|
||||||
|
<Setter Property="Opacity" TargetName="rectangle" Value="0.3"/>
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsEnabled" Value="False">
|
||||||
|
<Setter Property="Fill" TargetName="rectangle" Value="#666"/>
|
||||||
|
<Setter Property="Opacity" TargetName="rectangle" Value="0.6"/>
|
||||||
|
<Setter Property="Opacity" TargetName="contentPresenter" Value="0.3"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
</Window.Resources>
|
||||||
|
|
||||||
|
<Grid Name="gridMainDisplay" Margin="0,0,0,0" >
|
||||||
|
|
||||||
|
<Grid Name="gridContentDisplay" DockPanel.Dock="Top">
|
||||||
|
|
||||||
|
|
||||||
|
<StackPanel Name="stackPanelImage" Orientation="Vertical" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
|
||||||
|
|
||||||
|
<Grid Name="gridAffdexFaceDisplay" VerticalAlignment="Stretch" Width="auto" Height="560" >
|
||||||
|
|
||||||
|
<Image Name="imgAffdexFaceDisplay" Visibility="Hidden" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="UniformToFill"/>
|
||||||
|
|
||||||
|
<Image Name="imgAffdexLogoDisplay" Margin="40" Width="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||||
|
Height="auto" Source="Resources/AffectivaLogo1.png" Visibility="Visible"/>
|
||||||
|
|
||||||
|
<Canvas Name="canvasFacePoints" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Name="stackPanelClassifiersBackground" Orientation="Vertical" Background="Gainsboro" Height="130" HorizontalAlignment="Stretch" VerticalAlignment="Top" Opacity=".3" />
|
||||||
|
|
||||||
|
|
||||||
|
<StackPanel Name="stackPanelClassifiers" Orientation="Vertical" Background="Transparent" Height="130" HorizontalAlignment="Stretch" VerticalAlignment="Top" >
|
||||||
|
|
||||||
|
<Grid Name="gridClassifierDisplay" VerticalAlignment="Stretch" Background="Transparent" Margin="0,5,0,0"
|
||||||
|
Width="{Binding ElementName=stackPanelClassifiers, Path=ActualWidth}"
|
||||||
|
Height="{Binding ElementName=stackPanelClassifiers, Path=ActualHeight}" >
|
||||||
|
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="0.36*" />
|
||||||
|
<ColumnDefinition Width="0.28*" />
|
||||||
|
<ColumnDefinition Width="0.36*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="40" />
|
||||||
|
<RowDefinition Height="40" />
|
||||||
|
<RowDefinition Height="40" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Vertical" Grid.Row="0" Grid.Column="0" Margin="0,0,0,0">
|
||||||
|
<TextBlock Name="txtSmileClassifierName" Text="SMILE" Foreground="OrangeRed" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/>
|
||||||
|
<Grid>
|
||||||
|
<TextBlock Name="txtSmileClassifierValueBackground" Width="50" Background="LimeGreen" HorizontalAlignment="Center"/>
|
||||||
|
<TextBlock Name="txtSmileClassifierValue" Width="50" TextAlignment="Center" Text="10%" FontWeight="SemiBold" Foreground="Black" HorizontalAlignment="Center"/>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Vertical" Grid.Row="0" Grid.Column="2" Margin="0,0,0,0" >
|
||||||
|
<TextBlock Name="txtFrownClassifierName" Text="FROWN" Foreground="OrangeRed" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/>
|
||||||
|
<Grid>
|
||||||
|
<TextBlock Name="txtFrownClassifierValueBackground" Width="50" Background="LimeGreen" HorizontalAlignment="Center" />
|
||||||
|
<TextBlock Name="txtFrownClassifierValue" Width="50" TextAlignment="Center" Text="10%" FontWeight="SemiBold" Foreground="Black" HorizontalAlignment="Center" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Vertical" Grid.Row="1" Grid.Column="0" Margin="0,0,0,0" >
|
||||||
|
<TextBlock Name="txtBrowRaiseClassifierName" Text="BROW RAISE" Foreground="OrangeRed" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/>
|
||||||
|
<Grid>
|
||||||
|
<TextBlock Name="txtBrowRaiseClassifierValueBackground" Width="50" Background="LimeGreen" HorizontalAlignment="Center" />
|
||||||
|
<TextBlock Name="txtBrowRaiseClassifierValue" Width="50" TextAlignment="Center" Text="10%" FontWeight="SemiBold" Foreground="Black" HorizontalAlignment="Center" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Vertical" Grid.Row="1" Grid.Column="2" Margin="0,0,0,0" >
|
||||||
|
<TextBlock Name="txtValenceClassifierName" Text="VALENCE" Foreground="OrangeRed" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/>
|
||||||
|
<Grid>
|
||||||
|
<TextBlock Name="txtValenceClassifierValueBackground" Width="50" Background="LimeGreen" HorizontalAlignment="Center" />
|
||||||
|
<TextBlock Name="txtValenceClassifierValue" Width="50" TextAlignment="Center" Text="10%" FontWeight="SemiBold" Foreground="Black" HorizontalAlignment="Center"/>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Vertical" Grid.Row="2" Grid.Column="0" Margin="0,0,0,0" >
|
||||||
|
<TextBlock Name="txtBrowLowerClassifierName" Text="BROW FURROW" Foreground="OrangeRed" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center"/>
|
||||||
|
<Grid>
|
||||||
|
<TextBlock Name="txtBrowLowerClassifierValueBackground" Width="50" Background="LimeGreen" HorizontalAlignment="Center" />
|
||||||
|
<TextBlock Name="txtBrowLowerClassifierValue" Width="50" TextAlignment="Center" Text="10%" FontWeight="SemiBold" Foreground="Black" HorizontalAlignment="Center" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Vertical" Grid.Row="2" Grid.Column="2" Margin="0,0,0,0" >
|
||||||
|
<TextBlock Name="txtEngagementClassifierName" Text="ENGAGEMENT" Foreground="OrangeRed" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center" />
|
||||||
|
<Grid>
|
||||||
|
<TextBlock Name="txtEngagementClassifierValueBackground" Width="50" Background="LimeGreen" HorizontalAlignment="Center" />
|
||||||
|
<TextBlock Name="txtEngagementClassifierValue" Width="50" TextAlignment="Center" Text="10%" FontWeight="SemiBold" Foreground="Black" HorizontalAlignment="Center" />
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<StackPanel Name="stackPanelLogoBackground" Orientation="Vertical" Background="Transparent" Height="75" HorizontalAlignment="Stretch" VerticalAlignment="Top" >
|
||||||
|
<Grid Name="gridLogoBackground">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="0.36*" />
|
||||||
|
<ColumnDefinition Width="0.28*" />
|
||||||
|
<ColumnDefinition Width="0.36*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="20" />
|
||||||
|
<RowDefinition Height="35" />
|
||||||
|
<RowDefinition Height="20" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<Image Name="imgAffdexLogoBackground" Width="auto" Grid.Column="1" Grid.Row="1"
|
||||||
|
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||||
|
Height="auto" Source="Resources/AffectivaLogo1.png" Margin="0,0,0,-34" Grid.RowSpan="2"/>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<DockPanel VerticalAlignment="Bottom" Background="Coral" >
|
||||||
|
|
||||||
|
<Grid HorizontalAlignment="Center">
|
||||||
|
<GroupBox Margin="0,5,0,0" Height="40" VerticalAlignment="Stretch" BorderBrush="Transparent" BorderThickness="0">
|
||||||
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||||
|
<Button Name="btnStartCamera" Style="{StaticResource CustomButtonStyle}" HorizontalAlignment="Center" Margin="0,0,5,0" VerticalAlignment="Top" Width="55" Content="Start" />
|
||||||
|
<Button Name="btnResetCamera" Style="{StaticResource CustomButtonStyle}" HorizontalAlignment="Center" Margin="0,0,5,0" VerticalAlignment="Top" Width="56" Content="Reset" />
|
||||||
|
<Button Name="btnShowPoints" Style="{StaticResource CustomButtonStyle}" HorizontalAlignment="Center" Margin="0,0,5,0" VerticalAlignment="Top" Width="80" Content="Show Points" />
|
||||||
|
<Button Name="btnStopCamera" Style="{StaticResource CustomButtonStyle}" HorizontalAlignment="Center" Margin="0,0,5,0" VerticalAlignment="Top" Width="55" Content="Stop" />
|
||||||
|
<Button Name="btnExit" Style="{StaticResource CustomButtonStyle}" HorizontalAlignment="Center" Margin="0,0,5,0" VerticalAlignment="Bottom" Width="55" Content="Exit" />
|
||||||
|
</StackPanel>
|
||||||
|
</GroupBox>
|
||||||
|
</Grid>
|
||||||
|
</DockPanel>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
755
AffdexMe/MainWindow.xaml.cs
Normal file
755
AffdexMe/MainWindow.xaml.cs
Normal file
|
@ -0,0 +1,755 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
namespace AffdexMe
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for MainWindow.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class MainWindow : Window
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Location of Affdex Data files
|
||||||
|
/// </summary>
|
||||||
|
private const String AFFDEX_DATA_PATH = "C:\\Program Files (x86)\\Affectiva\\Affdex SDK\\data";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Location of AffdexSDK Licence file
|
||||||
|
/// </summary>
|
||||||
|
private const String AFFDEX_LICENSE_FILE = "C:\\Affectiva\\Build\\AffdexfaceWindows\\bin\\affdex.license";
|
||||||
|
|
||||||
|
#region Member Variables and Enums
|
||||||
|
|
||||||
|
enum AffdexFaceClassifiers : int
|
||||||
|
{
|
||||||
|
Smile = 0,
|
||||||
|
BrowFurrow = 1,
|
||||||
|
BrowRaise = 2,
|
||||||
|
LipCornerDepressor = 3,
|
||||||
|
Engagement = 4,
|
||||||
|
Valence = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum length of the Classifier Value textbox
|
||||||
|
/// </summary>
|
||||||
|
const int ClassiferValueDisplayLength = 90;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// So the Classifiers can be cached
|
||||||
|
/// </summary>
|
||||||
|
int[] mAffdexClassifierValues = new int[6];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Once a face has been recognized, the number of captures that occur before the classifiers get zero displayed
|
||||||
|
/// This helps prevent classifier numbers from flashing on the screen.
|
||||||
|
/// </summary>
|
||||||
|
int mCachedSkipFaceResultsCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Once a face's feature points get displayed, the number of successive captures that occur without
|
||||||
|
/// the points getting redrawn in the OnResults callback.
|
||||||
|
/// </summary>
|
||||||
|
int mFeaturePointsSkipCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to delay the display of the Classifier panel until the 1st face is recognized
|
||||||
|
/// </summary>
|
||||||
|
bool mFirstFaceRecognized;
|
||||||
|
|
||||||
|
private Affdex.CameraDetector mCameraDetector;
|
||||||
|
|
||||||
|
private DateTime mStartTime;
|
||||||
|
|
||||||
|
private float mCurrentTimeStamp;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scale factor based on ratio between current and original size
|
||||||
|
/// </summary>
|
||||||
|
private double mImageXScaleFactor;
|
||||||
|
private double mImageYScaleFactor;
|
||||||
|
|
||||||
|
private bool mShowFacePoints;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Image and Results Arg Classes
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
class ImageCaptureDataUpdateArgs
|
||||||
|
{
|
||||||
|
public float ImageCaptureTimeStamp {get; set;}
|
||||||
|
public Affdex.Frame Image { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
class ImageResultsDataUpdateArgs
|
||||||
|
{
|
||||||
|
public float ImageResultsTimeStamp { get; set; }
|
||||||
|
public Affdex.Frame Image { get; set; }
|
||||||
|
public Affdex.Face Face { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Listener Implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
class Listener : Affdex.ImageListener, Affdex.ProcessStatusListener
|
||||||
|
{
|
||||||
|
public event EventHandler<ImageCaptureDataUpdateArgs> ImageCaptureUpdate;
|
||||||
|
public event EventHandler<ImageResultsDataUpdateArgs> ImageResultsUpdate;
|
||||||
|
public event EventHandler<Affdex.AffdexException> ExceptionHandler;
|
||||||
|
|
||||||
|
public void onImageResults(Dictionary<int, Affdex.Face> faces, Affdex.Frame image)
|
||||||
|
{
|
||||||
|
// For now only single face is supported
|
||||||
|
if ((faces.Count() >= 1))
|
||||||
|
{
|
||||||
|
Affdex.Face face = faces[0];
|
||||||
|
|
||||||
|
if (ImageResultsUpdate != null)
|
||||||
|
{
|
||||||
|
ImageResultsDataUpdateArgs imageResultsData = new ImageResultsDataUpdateArgs()
|
||||||
|
{
|
||||||
|
Image = image,
|
||||||
|
ImageResultsTimeStamp = image.getTimestamp(),
|
||||||
|
Face = face
|
||||||
|
};
|
||||||
|
ImageResultsUpdate(this, imageResultsData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="affdexImage"></param>
|
||||||
|
public void onImageCapture(Affdex.Frame image)
|
||||||
|
{
|
||||||
|
if (ImageCaptureUpdate != null)
|
||||||
|
{
|
||||||
|
ImageCaptureDataUpdateArgs imageCaptureData = new ImageCaptureDataUpdateArgs()
|
||||||
|
{
|
||||||
|
Image = image,
|
||||||
|
ImageCaptureTimeStamp = image.getTimestamp()
|
||||||
|
};
|
||||||
|
ImageCaptureUpdate(this, imageCaptureData);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onProcessingException(Affdex.AffdexException ex)
|
||||||
|
{
|
||||||
|
if (ExceptionHandler != null)
|
||||||
|
{
|
||||||
|
ExceptionHandler(this, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onProcessingFinished()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void ShowExceptionAndShutDown(String exceptionMessage)
|
||||||
|
{
|
||||||
|
MessageBoxResult result = MessageBox.Show(exceptionMessage,
|
||||||
|
"AffdexMe Error",
|
||||||
|
MessageBoxButton.OK,
|
||||||
|
MessageBoxImage.Error);
|
||||||
|
this.Dispatcher.BeginInvoke((Action)(() =>
|
||||||
|
{
|
||||||
|
StopCameraProcessing();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
CenterWindowOnScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
InitializeCameraApp();
|
||||||
|
|
||||||
|
// Enable/Disable buttons on start
|
||||||
|
btnStartCamera.IsEnabled =
|
||||||
|
btnResetCamera.IsEnabled =
|
||||||
|
btnShowPoints.IsEnabled =
|
||||||
|
btnStopCamera.IsEnabled =
|
||||||
|
btnExit.IsEnabled = true;
|
||||||
|
|
||||||
|
this.ContentRendered += MainWindow_ContentRendered;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Once the window las been loaded and the content rendered, the camera
|
||||||
|
/// can be initialized and started. This sequence allows for the underlying controls
|
||||||
|
/// and watermark logo to be displayed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
void MainWindow_ContentRendered(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
StartCameraProcessing();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
private void CenterWindowOnScreen()
|
||||||
|
{
|
||||||
|
double screenWidth = System.Windows.SystemParameters.PrimaryScreenWidth;
|
||||||
|
double screenHeight = System.Windows.SystemParameters.PrimaryScreenHeight;
|
||||||
|
double windowWidth = this.Width;
|
||||||
|
double windowHeight = this.Height;
|
||||||
|
this.Left = (screenWidth / 2) - (windowWidth / 2);
|
||||||
|
this.Top = (screenHeight / 2) - (windowHeight / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BitmapSource ConstructImage(byte[] imageData, int width, int height)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (imageData != null && imageData.Length > 0)
|
||||||
|
{
|
||||||
|
var stride = (width * PixelFormats.Bgr24.BitsPerPixel + 7) / 8;
|
||||||
|
var imageSrc = BitmapSource.Create(width, height, 96d, 96d, PixelFormats.Bgr24, null, imageData, stride);
|
||||||
|
return imageSrc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisplayFeaturePoints(Affdex.Frame affdexImage, Affdex.Face affdexFace)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Plot Face Points
|
||||||
|
if ((mShowFacePoints) && (affdexFace != null))
|
||||||
|
{
|
||||||
|
canvasFacePoints.Dispatcher.BeginInvoke((Action)(() =>
|
||||||
|
{
|
||||||
|
if ((mCameraDetector != null) && (mCameraDetector.isRunning()))
|
||||||
|
{
|
||||||
|
// Clear the previous points
|
||||||
|
canvasFacePoints.Children.Clear();
|
||||||
|
canvasFacePoints.Width = imgAffdexFaceDisplay.ActualWidth;
|
||||||
|
canvasFacePoints.Height = imgAffdexFaceDisplay.ActualHeight;
|
||||||
|
|
||||||
|
mImageXScaleFactor = imgAffdexFaceDisplay.ActualWidth / affdexImage.getWidth();
|
||||||
|
mImageYScaleFactor = imgAffdexFaceDisplay.ActualHeight / affdexImage.getHeight();
|
||||||
|
|
||||||
|
SolidColorBrush pointBrush = new SolidColorBrush(Colors.Cornsilk);
|
||||||
|
var featurePoints = affdexFace.getFeaturePoints();
|
||||||
|
foreach (var point in featurePoints)
|
||||||
|
{
|
||||||
|
Ellipse ellipse = new Ellipse()
|
||||||
|
{
|
||||||
|
Width = 4,
|
||||||
|
Height = 4,
|
||||||
|
Fill = pointBrush
|
||||||
|
};
|
||||||
|
|
||||||
|
canvasFacePoints.Children.Add(ellipse);
|
||||||
|
Canvas.SetLeft(ellipse, point.x * mImageXScaleFactor);
|
||||||
|
Canvas.SetTop(ellipse, point.y * mImageYScaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw Face Bounding Rectangle
|
||||||
|
var xMax = featurePoints.Max(r => r.x);
|
||||||
|
var xMin = featurePoints.Min(r => r.x);
|
||||||
|
var yMax = featurePoints.Max(r => r.y);
|
||||||
|
var yMin = featurePoints.Min(r => r.y);
|
||||||
|
|
||||||
|
// Adjust the x/y min to accomodate all points
|
||||||
|
xMin -= 2;
|
||||||
|
yMin -= 2;
|
||||||
|
|
||||||
|
// Increase the width/height to accomodate the entire max pixel position
|
||||||
|
// EllipseWidth + N to make sure max points in the box
|
||||||
|
double width = (xMax - xMin + 6) * mImageXScaleFactor;
|
||||||
|
double height = (yMax - yMin + 6) * mImageYScaleFactor;
|
||||||
|
|
||||||
|
SolidColorBrush boundingBrush = new SolidColorBrush(Colors.Bisque);
|
||||||
|
Rectangle boundingBox = new Rectangle()
|
||||||
|
{
|
||||||
|
Width = width,
|
||||||
|
Height = height,
|
||||||
|
Stroke = boundingBrush,
|
||||||
|
StrokeThickness = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
canvasFacePoints.Children.Add(boundingBox);
|
||||||
|
Canvas.SetLeft(boundingBox, xMin * mImageXScaleFactor);
|
||||||
|
Canvas.SetTop(boundingBox, yMin * mImageYScaleFactor);
|
||||||
|
|
||||||
|
mFeaturePointsSkipCount = 0;
|
||||||
|
|
||||||
|
affdexFace.Dispose();
|
||||||
|
affdexImage.Dispose();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Since the panel is getting updated from a separate callback thread, access to controls must be
|
||||||
|
/// made through BeginInvoke()
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="face"></param>
|
||||||
|
private void UpdateClassifierPanel(Affdex.Face face = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
bool displayClassifiers = (imgAffdexFaceDisplay.Visibility == Visibility.Hidden)? false : true;
|
||||||
|
|
||||||
|
if (mCameraDetector.isRunning() == true)
|
||||||
|
{
|
||||||
|
// A Face was found - this comes from ImageResults CallBack
|
||||||
|
if (face != null)
|
||||||
|
{
|
||||||
|
// Convert classifier value to Integer (percentage) for display purposes
|
||||||
|
mAffdexClassifierValues[(int)AffdexFaceClassifiers.Smile] = Convert.ToInt32(Math.Round(face.getSmileScore(), MidpointRounding.AwayFromZero));
|
||||||
|
mAffdexClassifierValues[(int)AffdexFaceClassifiers.BrowFurrow] = Convert.ToInt32(Math.Round(face.getBrowFurrowScore(), MidpointRounding.AwayFromZero));
|
||||||
|
mAffdexClassifierValues[(int)AffdexFaceClassifiers.BrowRaise] = Convert.ToInt32(Math.Round(face.getBrowRaiseScore(), MidpointRounding.AwayFromZero));
|
||||||
|
mAffdexClassifierValues[(int)AffdexFaceClassifiers.LipCornerDepressor] = Convert.ToInt32(Math.Round(face.getLipCornerDepressorScore(), MidpointRounding.AwayFromZero));
|
||||||
|
mAffdexClassifierValues[(int)AffdexFaceClassifiers.Engagement] = Convert.ToInt32(Math.Round(face.getEngagementScore(), MidpointRounding.AwayFromZero));
|
||||||
|
mAffdexClassifierValues[(int)AffdexFaceClassifiers.Valence] = Convert.ToInt32(Math.Round(face.getValenceScore(), MidpointRounding.AwayFromZero));
|
||||||
|
|
||||||
|
// Reset the cache count
|
||||||
|
mCachedSkipFaceResultsCount = 0;
|
||||||
|
mFirstFaceRecognized =
|
||||||
|
displayClassifiers = true;
|
||||||
|
}
|
||||||
|
else if (mFirstFaceRecognized == false)
|
||||||
|
{
|
||||||
|
displayClassifiers = false;
|
||||||
|
}
|
||||||
|
else if (++mCachedSkipFaceResultsCount > 10)
|
||||||
|
{
|
||||||
|
mAffdexClassifierValues[(int)AffdexFaceClassifiers.Smile] =
|
||||||
|
mAffdexClassifierValues[(int)AffdexFaceClassifiers.BrowFurrow] =
|
||||||
|
mAffdexClassifierValues[(int)AffdexFaceClassifiers.BrowRaise] =
|
||||||
|
mAffdexClassifierValues[(int)AffdexFaceClassifiers.LipCornerDepressor] =
|
||||||
|
mAffdexClassifierValues[(int)AffdexFaceClassifiers.Engagement] =
|
||||||
|
mAffdexClassifierValues[(int)AffdexFaceClassifiers.Valence] = 0;
|
||||||
|
|
||||||
|
// If we haven't seen a face in the past 30 frames (roughly 30/15fps seconds), don't display the classifiers
|
||||||
|
if (mCachedSkipFaceResultsCount >= 30)
|
||||||
|
{
|
||||||
|
displayClassifiers = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only display the classifiers and FacePoints if we've had a re
|
||||||
|
if (displayClassifiers)
|
||||||
|
{
|
||||||
|
// Update the Classifier Display
|
||||||
|
UpdateClassifier(txtSmileClassifierName, txtSmileClassifierValue, txtSmileClassifierValueBackground, AffdexFaceClassifiers.Smile);
|
||||||
|
UpdateClassifier(txtFrownClassifierName, txtFrownClassifierValue, txtFrownClassifierValueBackground, AffdexFaceClassifiers.LipCornerDepressor);
|
||||||
|
UpdateClassifier(txtBrowRaiseClassifierName, txtBrowRaiseClassifierValue, txtBrowRaiseClassifierValueBackground, AffdexFaceClassifiers.BrowRaise);
|
||||||
|
UpdateClassifier(txtValenceClassifierName, txtValenceClassifierValue, txtValenceClassifierValueBackground, AffdexFaceClassifiers.Valence);
|
||||||
|
UpdateClassifier(txtBrowLowerClassifierName, txtBrowLowerClassifierValue, txtBrowLowerClassifierValueBackground, AffdexFaceClassifiers.BrowFurrow);
|
||||||
|
UpdateClassifier(txtEngagementClassifierName, txtEngagementClassifierValue, txtEngagementClassifierValueBackground, AffdexFaceClassifiers.Engagement);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the Image control from the UI thread
|
||||||
|
stackPanelClassifiers.Dispatcher.BeginInvoke((Action)(() =>
|
||||||
|
{
|
||||||
|
if ((mCameraDetector != null) && (mCameraDetector.isRunning()))
|
||||||
|
{
|
||||||
|
if (imgAffdexFaceDisplay.Visibility == Visibility.Hidden)
|
||||||
|
{
|
||||||
|
imgAffdexFaceDisplay.Visibility =
|
||||||
|
stackPanelClassifiersBackground.Visibility =
|
||||||
|
stackPanelLogoBackground.Visibility = Visibility.Visible;
|
||||||
|
}
|
||||||
|
stackPanelClassifiers.Visibility = (displayClassifiers)?Visibility.Visible : Visibility.Hidden;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateClassifier(TextBlock txtClassifier, TextBlock txtClassifierValue,
|
||||||
|
TextBlock txtClassifierValueBackground, AffdexFaceClassifiers classifierIndex)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int classifierValue = mAffdexClassifierValues[(int)classifierIndex];
|
||||||
|
|
||||||
|
// Calculate the width
|
||||||
|
double width = ClassiferValueDisplayLength * Math.Abs(classifierValue) / 100;
|
||||||
|
|
||||||
|
var backgroundColor = Colors.Transparent;
|
||||||
|
|
||||||
|
if (classifierValue > 0)
|
||||||
|
{
|
||||||
|
backgroundColor = Colors.LimeGreen;
|
||||||
|
}
|
||||||
|
else if (classifierValue < 0)
|
||||||
|
{
|
||||||
|
backgroundColor = Colors.Red;
|
||||||
|
}
|
||||||
|
|
||||||
|
txtClassifierValue.Dispatcher.BeginInvoke((Action)(() =>
|
||||||
|
{
|
||||||
|
txtClassifierValueBackground.Background = new SolidColorBrush(backgroundColor);
|
||||||
|
txtClassifierValueBackground.Width = width;
|
||||||
|
txtClassifierValue.Text = String.Format("{0}%", classifierValue);
|
||||||
|
}));
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisplayImageToOffscreenCanvas(Affdex.Frame image)
|
||||||
|
{
|
||||||
|
// Update the Image control from the UI thread
|
||||||
|
imgAffdexFaceDisplay.Dispatcher.BeginInvoke((Action)(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mCurrentTimeStamp = image.getTimestamp();
|
||||||
|
|
||||||
|
// Update the Image control from the UI thread
|
||||||
|
//imgAffdexFaceDisplay.Source = rtb;
|
||||||
|
imgAffdexFaceDisplay.Source = ConstructImage(image.getBGRByteArray(), image.getWidth(), image.getHeight());
|
||||||
|
|
||||||
|
// Allow N successive OnCapture callbacks before the FacePoint drawing canvas gets cleared.
|
||||||
|
if (++mFeaturePointsSkipCount > 4)
|
||||||
|
{
|
||||||
|
canvasFacePoints.Children.Clear();
|
||||||
|
mFeaturePointsSkipCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image != null)
|
||||||
|
{
|
||||||
|
image.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeCameraApp()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mCameraDetector = null;
|
||||||
|
|
||||||
|
// Initialize Button Click Handlers
|
||||||
|
btnStartCamera.Click += btnStartCamera_Click;
|
||||||
|
btnStopCamera.Click += btnStopCamera_Click;
|
||||||
|
btnShowPoints.Click += btnShowPoints_Click;
|
||||||
|
btnResetCamera.Click += btnResetCamera_Click;
|
||||||
|
btnExit.Click += btnExit_Click;
|
||||||
|
|
||||||
|
// Disable Stop/Reset buttons
|
||||||
|
btnResetCamera.IsEnabled =
|
||||||
|
btnStopCamera.IsEnabled = false;
|
||||||
|
|
||||||
|
mFeaturePointsSkipCount =
|
||||||
|
mCachedSkipFaceResultsCount = 0;
|
||||||
|
|
||||||
|
// Initially hide Classifier Panels
|
||||||
|
stackPanelLogoBackground.Visibility =
|
||||||
|
stackPanelClassifiersBackground.Visibility =
|
||||||
|
stackPanelClassifiers.Visibility = Visibility.Hidden;
|
||||||
|
|
||||||
|
// Face Points are off by default
|
||||||
|
mShowFacePoints = false;
|
||||||
|
|
||||||
|
// Show the logo
|
||||||
|
imgAffdexLogoDisplay.Visibility = Visibility.Visible;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
void btnShowPoints_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Style style;
|
||||||
|
String buttonText = String.Empty;
|
||||||
|
|
||||||
|
mShowFacePoints = !mShowFacePoints;
|
||||||
|
if (mShowFacePoints)
|
||||||
|
{
|
||||||
|
style = this.FindResource("PointsOnButtonStyle") as Style;
|
||||||
|
buttonText = "Hide Points";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
style = this.FindResource("CustomButtonStyle") as Style;
|
||||||
|
buttonText = "Show Points";
|
||||||
|
}
|
||||||
|
|
||||||
|
btnShowPoints.Style = style;
|
||||||
|
btnShowPoints.Content = buttonText;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnResetCamera_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
ResetCameraProcessing();
|
||||||
|
}
|
||||||
|
|
||||||
|
void btnStartCamera_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StartCameraProcessing();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void btnStopCamera_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
StopCameraProcessing();
|
||||||
|
ResetDisplayArea();
|
||||||
|
}
|
||||||
|
|
||||||
|
void btnExit_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Application.Current.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearClassifiersAndPointsDisplay()
|
||||||
|
{
|
||||||
|
// Hide AffdexFace Image
|
||||||
|
imgAffdexFaceDisplay.Visibility =
|
||||||
|
stackPanelLogoBackground.Visibility =
|
||||||
|
stackPanelClassifiersBackground.Visibility = Visibility.Hidden;
|
||||||
|
|
||||||
|
// Hide the Classifier Panel
|
||||||
|
stackPanelClassifiers.Visibility = Visibility.Hidden;
|
||||||
|
|
||||||
|
// Clear any Face Points
|
||||||
|
canvasFacePoints.Children.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetDisplayArea()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ClearClassifiersAndPointsDisplay();
|
||||||
|
|
||||||
|
// Show the logo
|
||||||
|
imgAffdexLogoDisplay.Visibility = Visibility.Visible;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartCameraProcessing()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Instantiate CameraDetector using default camera ID
|
||||||
|
mCameraDetector = new Affdex.CameraDetector();
|
||||||
|
mCameraDetector.setClassifierPath(AFFDEX_DATA_PATH);
|
||||||
|
|
||||||
|
// Set the Classifiers that we are interested in tracking
|
||||||
|
mCameraDetector.setDetectSmile(true);
|
||||||
|
mCameraDetector.setDetectBrowFurrow(true);
|
||||||
|
mCameraDetector.setDetectBrowRaise(true);
|
||||||
|
mCameraDetector.setDetectLipCornerDepressor(true);
|
||||||
|
mCameraDetector.setDetectEngagement(true);
|
||||||
|
mCameraDetector.setDetectValence(true);
|
||||||
|
|
||||||
|
// Initialize Classifier cache
|
||||||
|
for (int index = 0; index < mAffdexClassifierValues.Count(); index++)
|
||||||
|
{
|
||||||
|
mAffdexClassifierValues[index] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCachedSkipFaceResultsCount = 0;
|
||||||
|
|
||||||
|
Listener listener = new Listener();
|
||||||
|
listener.ImageCaptureUpdate += imageListener_ImageCaptureUpdate;
|
||||||
|
listener.ImageResultsUpdate += imageListener_ImageResultsUpdate;
|
||||||
|
listener.ExceptionHandler += imageListener_ExceptionHandler;
|
||||||
|
|
||||||
|
mCameraDetector.setImageListener(listener);
|
||||||
|
mCameraDetector.setProcessStatusListener(listener);
|
||||||
|
|
||||||
|
btnStartCamera.IsEnabled = false;
|
||||||
|
btnResetCamera.IsEnabled =
|
||||||
|
btnShowPoints.IsEnabled =
|
||||||
|
btnStopCamera.IsEnabled =
|
||||||
|
btnExit.IsEnabled = true;
|
||||||
|
|
||||||
|
// Set the License Path
|
||||||
|
mCameraDetector.setLicensePath(AFFDEX_LICENSE_FILE);
|
||||||
|
|
||||||
|
mStartTime = DateTime.Now;
|
||||||
|
mCameraDetector.start();
|
||||||
|
|
||||||
|
// Delay loading the Classifier panel until 1st face
|
||||||
|
mFirstFaceRecognized = false;
|
||||||
|
|
||||||
|
// Hide the logo
|
||||||
|
imgAffdexLogoDisplay.Visibility = Visibility.Hidden;
|
||||||
|
}
|
||||||
|
catch(Affdex.AffdexException ex)
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(ex.Message))
|
||||||
|
{
|
||||||
|
// If this is a camera failure, then reset the application to allow the user to turn on/enable camera
|
||||||
|
if (ex.Message.Equals("Unable to open webcam."))
|
||||||
|
{
|
||||||
|
MessageBoxResult result = MessageBox.Show(ex.Message,
|
||||||
|
"AffdexMe Error",
|
||||||
|
MessageBoxButton.OK,
|
||||||
|
MessageBoxImage.Error);
|
||||||
|
StopCameraProcessing();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void imageListener_ExceptionHandler(object sender, Affdex.AffdexException ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void imageListener_ImageResultsUpdate(object sender, MainWindow.ImageResultsDataUpdateArgs e)
|
||||||
|
{
|
||||||
|
UpdateClassifierPanel(e.Face);
|
||||||
|
DisplayFeaturePoints(e.Image, e.Face);
|
||||||
|
}
|
||||||
|
|
||||||
|
void imageListener_ImageCaptureUpdate(object sender, MainWindow.ImageCaptureDataUpdateArgs e)
|
||||||
|
{
|
||||||
|
UpdateClassifierPanel();
|
||||||
|
DisplayImageToOffscreenCanvas(e.Image);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetCameraProcessing()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mCameraDetector.reset();
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopCameraProcessing()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if ((mCameraDetector != null) && (mCameraDetector.isRunning()))
|
||||||
|
{
|
||||||
|
mCameraDetector.stop();
|
||||||
|
mCameraDetector.Dispose();
|
||||||
|
mCameraDetector = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable/Disable buttons on start
|
||||||
|
btnStartCamera.IsEnabled = true;
|
||||||
|
btnResetCamera.IsEnabled =
|
||||||
|
btnStopCamera.IsEnabled = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
String message = String.IsNullOrEmpty(ex.Message) ? "AffdexMe error encountered." : ex.Message;
|
||||||
|
ShowExceptionAndShutDown(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||||
|
{
|
||||||
|
StopCameraProcessing();
|
||||||
|
Application.Current.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
55
AffdexMe/Properties/AssemblyInfo.cs
Normal file
55
AffdexMe/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Resources;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
// 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("AffdexMe")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("AffdexMe")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||||
|
[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)]
|
||||||
|
|
||||||
|
//In order to begin building localizable applications, set
|
||||||
|
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||||
|
//inside a <PropertyGroup>. For example, if you are using US english
|
||||||
|
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||||
|
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||||
|
//the line below to match the UICulture setting in the project file.
|
||||||
|
|
||||||
|
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||||
|
|
||||||
|
|
||||||
|
[assembly: ThemeInfo(
|
||||||
|
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// or application resource dictionaries)
|
||||||
|
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// app, or any theme specific resource dictionaries)
|
||||||
|
)]
|
||||||
|
|
||||||
|
|
||||||
|
// 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")]
|
71
AffdexMe/Properties/Resources.Designer.cs
generated
Normal file
71
AffdexMe/Properties/Resources.Designer.cs
generated
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.34209
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace AffdexMe.Properties
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class Resources
|
||||||
|
{
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Resources()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if ((resourceMan == null))
|
||||||
|
{
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AffdexMe.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
117
AffdexMe/Properties/Resources.resx
Normal file
117
AffdexMe/Properties/Resources.resx
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
30
AffdexMe/Properties/Settings.Designer.cs
generated
Normal file
30
AffdexMe/Properties/Settings.Designer.cs
generated
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.34209
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace AffdexMe.Properties
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||||
|
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||||
|
{
|
||||||
|
|
||||||
|
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||||
|
|
||||||
|
public static Settings Default
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return defaultInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
AffdexMe/Properties/Settings.settings
Normal file
7
AffdexMe/Properties/Settings.settings
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||||
|
<Profiles>
|
||||||
|
<Profile Name="(Default)" />
|
||||||
|
</Profiles>
|
||||||
|
<Settings />
|
||||||
|
</SettingsFile>
|
53
AffdexMe/README.md
Normal file
53
AffdexMe/README.md
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# AffdexMe
|
||||||
|
|
||||||
|
**Affdex SDK** is the culmination of years of scientific research into emotion detection, validated across thousands of tests worldwide on PC platforms, and now made available as a software development kit for Windows. Affdex SDK turns your ordinary app into an extraordinary app by emotion-enabling it to respond in real-time to user emotions.
|
||||||
|
|
||||||
|
**AffdexMe** is a windows application that demonstrates the use of the Affdex SDK for Windows. It uses the camera on your Windows PC to view, process and analyze live video of your face. Start the app and you will see your own face on the screen, and metrics describing your expressions.
|
||||||
|
|
||||||
|
#### This app includes the following command buttons:
|
||||||
|
|
||||||
|
* Start - Starts the camera processing.
|
||||||
|
* Reset - Resets the context of the video frames.
|
||||||
|
* ShowPoints/HidePoints - toggles the display of facial feature points, which Affdex uses to detect expressions.
|
||||||
|
* Stop - Stops the camera processing.
|
||||||
|
* Exit - exits the application.
|
||||||
|
|
||||||
|
This application runs on Windows 7.0, 8.0 and 8.1
|
||||||
|
|
||||||
|
#### To use this project, you will need:
|
||||||
|
|
||||||
|
* Visual Studio 2013
|
||||||
|
|
||||||
|
* To download and install the Windows SDK from Affectiva By default, the Windows SDK is installed to the following location: C:\Program Files (x86)\Affectiva\Affdex SDK
|
||||||
|
|
||||||
|
If you have installed the SDK to a location other than the default, you will have to modify the following String constants located in the MainWindow.xaml.cs file:
|
||||||
|
|
||||||
|
* **AFFDEX_DATA_PATH** - the classifier data path
|
||||||
|
* **AFFDEX_LICENSE_FILE** - the full path to the Affdex license file (including the license file name)
|
||||||
|
* The AffdexMe app can be built and run in either debug or release mode.
|
||||||
|
|
||||||
|
**To build and run in Debug Mode**
|
||||||
|
|
||||||
|
* Through Visual Studio select the "Debug" configuration.
|
||||||
|
|
||||||
|
* Add the following to your system path: C:\Program Files (x86)\Affectiva\Affdex SDK\bin\debug
|
||||||
|
|
||||||
|
* Clean, rebuild and then run the project.
|
||||||
|
|
||||||
|
**To build and run in Release Mode:**
|
||||||
|
|
||||||
|
* Through Visual Studio select the "Debug" configuration.
|
||||||
|
|
||||||
|
* Add the following to your system path: C:\Program Files (x86)\Affectiva\Affdex SDK\bin\release
|
||||||
|
|
||||||
|
* Clean, rebuild and then run the project.
|
||||||
|
|
||||||
|
**It is important** not to mix Release and Debug versions of the DLLs. If you run into issues when switching between the two different build types, check to make sure that your system path points to the matching build type.
|
||||||
|
|
||||||
|
* In order to modify the system path, from the Control Panel, navigiate to the following: **Control Panel -> Advanced System Settings -> Environment Variables -> System Variables -> Path**
|
||||||
|
|
||||||
|
* Build the project
|
||||||
|
|
||||||
|
* Run the app through Visual Studio
|
||||||
|
|
||||||
|
Copyright (c) 2015 Affectiva. All rights reserved.
|
BIN
AffdexMe/Resources/AffdexMe_Logo.ico
Normal file
BIN
AffdexMe/Resources/AffdexMe_Logo.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 361 KiB |
BIN
AffdexMe/Resources/AffectivaLogo1.png
Normal file
BIN
AffdexMe/Resources/AffectivaLogo1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 169 KiB |
|
@ -1,10 +1,12 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Express 2013 for Windows Desktop
|
# Visual Studio 2013
|
||||||
VisualStudioVersion = 12.0.30723.0
|
VisualStudioVersion = 12.0.21005.1
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opencv-webcam-demo", "opencv-webcam-demo\opencv-webcam-demo.vcxproj", "{8DCDC209-C25D-4C61-B2AC-2FBA1775DD6B}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opencv-webcam-demo", "opencv-webcam-demo\opencv-webcam-demo.vcxproj", "{8DCDC209-C25D-4C61-B2AC-2FBA1775DD6B}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AffdexMe", "AffdexMe\AffdexMe.csproj", "{5B893EA1-EB11-425A-BF8A-05822F5E2C9A}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Release|Win32 = Release|Win32
|
Release|Win32 = Release|Win32
|
||||||
|
@ -12,6 +14,7 @@ Global
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{8DCDC209-C25D-4C61-B2AC-2FBA1775DD6B}.Release|Win32.ActiveCfg = Release|Win32
|
{8DCDC209-C25D-4C61-B2AC-2FBA1775DD6B}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{8DCDC209-C25D-4C61-B2AC-2FBA1775DD6B}.Release|Win32.Build.0 = Release|Win32
|
{8DCDC209-C25D-4C61-B2AC-2FBA1775DD6B}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{5B893EA1-EB11-425A-BF8A-05822F5E2C9A}.Release|Win32.ActiveCfg = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
Loading…
Reference in a new issue