Skip to content

Commit

Permalink
Add Form Recognizer demo and Overlay Control (microsoft#105)
Browse files Browse the repository at this point in the history
* Add Form Recognizer demo + Overlay Control

* Update keys on the Insurance Claim Automation demo + minor fixes

* minor fixes

* small fix

* Simplify animation logic

* small updates
  • Loading branch information
Albert Davletov authored Aug 10, 2020
1 parent 6d15dbf commit 1dd0eb6
Show file tree
Hide file tree
Showing 72 changed files with 7,182 additions and 98 deletions.
3 changes: 2 additions & 1 deletion Kiosk/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
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">

Expand Down Expand Up @@ -30,6 +29,8 @@
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

<ResourceDictionary Source="Controls/Overlays/OverlayResources.xaml" /> <!--include overlay resource globally-->

</ResourceDictionary.MergedDictionaries>

</ResourceDictionary>
Expand Down
8 changes: 7 additions & 1 deletion Kiosk/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ protected override void OnLaunched(LaunchActivatedEventArgs e)
FaceListManager.FaceListsUserDataFilter = SettingsHelper.Instance.WorkspaceKey;
CoreUtil.MinDetectableFaceCoveragePercentage = SettingsHelper.Instance.MinDetectableFaceCoveragePercentage;
AnomalyDetectorHelper.ApiKey = SettingsHelper.Instance.AnomalyDetectorApiKey;
ReceiptOCRHelper.ApiKey = SettingsHelper.Instance.FormRecognizerApiKey;
ReceiptOCRHelper.ApiEndpoint = SettingsHelper.Instance.FormRecognizerApiKeyEndpoint;
};

// callbacks for core library
Expand Down Expand Up @@ -186,7 +188,11 @@ private static async void TestApiKeysAsync()

!string.IsNullOrEmpty(SettingsHelper.Instance.AnomalyDetectorApiKey)
? CognitiveServiceApiKeyTester.TestAnomalyDetectorApiKeyAsync(SettingsHelper.Instance.AnomalyDetectorApiKey)
: Task.CompletedTask
: Task.CompletedTask,

!string.IsNullOrEmpty(SettingsHelper.Instance.FormRecognizerApiKey)
? CognitiveServiceApiKeyTester.TestFormRecognizerApiKeyAsync(SettingsHelper.Instance.FormRecognizerApiKey, SettingsHelper.Instance.FormRecognizerApiKeyEndpoint)
: Task.CompletedTask,
};

try
Expand Down
Binary file added Kiosk/Assets/FormsRecognizer.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
81 changes: 81 additions & 0 deletions Kiosk/AzureBlobHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//
// 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.Azure.Storage;
using Microsoft.Azure.Storage.Auth;
using Microsoft.Azure.Storage.Blob;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Windows.Storage;

namespace IntelligentKioskSample
{
class AzureBlobHelper
{
public static CloudBlobContainer GetCloudBlobContainer(string storageAccount, string storageKey, string containerName)
{
CloudStorageAccount cloudStorageAccount = new CloudStorageAccount(new StorageCredentials(storageAccount, storageKey), true);
CloudBlobClient blobClient = cloudStorageAccount.CreateCloudBlobClient();
return blobClient?.GetContainerReference(containerName);
}

public static async Task UploadStorageFilesToContainerAsync(IEnumerable<StorageFile> storageFiles, CloudBlobContainer container)
{
await container.CreateIfNotExistsAsync(BlobContainerPublicAccessType.Blob, new BlobRequestOptions(), new OperationContext());

// Upload our images
foreach (StorageFile storageFile in storageFiles)
{
CloudBlockBlob imageBlob = container.GetBlockBlobReference(storageFile.Name);
using (var stream = await storageFile.OpenStreamForReadAsync())
{
await imageBlob.UploadFromStreamAsync(stream);
}
}
}

public static string GetContainerSasToken(CloudBlobContainer container, int sharedAccessStartTimeInMinutes, int sharedAccessExpiryTimeInMinutes)
{
SharedAccessBlobPolicy sasPolicy = new SharedAccessBlobPolicy
{
Permissions = SharedAccessBlobPermissions.List | SharedAccessBlobPermissions.Read,
SharedAccessStartTime = DateTimeOffset.UtcNow.AddMinutes(-sharedAccessStartTimeInMinutes),
SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddMinutes(sharedAccessExpiryTimeInMinutes)
};

return $"{container.Uri}{container.GetSharedAccessSignature(sasPolicy)}";
}
}
}
14 changes: 14 additions & 0 deletions Kiosk/CognitiveServiceApiKeyTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,20 @@ public static async Task TestAnomalyDetectorApiKeyAsync(string key)
}
}

public static async Task TestFormRecognizerApiKeyAsync(string key, string apiEndpoint)
{
bool isUri = !string.IsNullOrEmpty(apiEndpoint) ? Uri.IsWellFormedUriString(apiEndpoint, UriKind.Absolute) : false;
if (!isUri)
{
throw new ArgumentException("Invalid URI");
}
else
{
var service = new FormRecognizerService(key, apiEndpoint);
await service.GetCustomModelsAsync();
}
}

private static async Task<HttpResponseMessage> RequestAndAutoRetryWhenThrottled(Func<Task<HttpResponseMessage>> action)
{
int retriesLeft = 10;
Expand Down
90 changes: 90 additions & 0 deletions Kiosk/Controls/Animation/AnimationHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//
// 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.Extensions;
using System.Collections.Generic;
using Windows.UI.Xaml;

namespace IntelligentKioskSample.Controls.Animation
{
public class AnimationHelper
{
public static readonly DependencyProperty BaseAnimationsProperty = DependencyProperty.RegisterAttached("BaseAnimations", typeof(List<BaseAnimation>), typeof(AnimationHelper), new PropertyMetadata(null));

public static List<BaseAnimation> GetAnimations(DependencyObject obj)
{
return (List<BaseAnimation>)obj.GetValue(BaseAnimationsProperty);
}

public static void SetAnimations(DependencyObject obj, List<BaseAnimation> value)
{
obj.SetValue(BaseAnimationsProperty, value);
}

internal static void AddAnimation(BaseAnimation animation)
{
var list = VerifyList(animation);
int index = list.IndexOfItem(x => x.Equivalent(animation));
if (index != -1)
{
var item = list[index];
item.Retain();
item.Stop();
list.RemoveAt(index);
}

list.Add(animation);
}

internal static void RemoveAnimation(BaseAnimation animation)
{
var list = GetAnimations(animation.Element);
if (list != null)
{
animation.Retain();
animation.Stop();
list.Remove(animation);
}
}

private static List<BaseAnimation> VerifyList(BaseAnimation animation)
{
var list = GetAnimations(animation.Element);
if (list == null)
{
SetAnimations(animation.Element, list = new List<BaseAnimation>());
}
return list;
}
}
}
102 changes: 102 additions & 0 deletions Kiosk/Controls/Animation/BaseAnimation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//
// 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.Extensions;
using System;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media.Animation;

namespace IntelligentKioskSample.Controls.Animation
{
public class BaseAnimationCompleteEventArgs
{
public bool NaturallyCompleted { get; set; }
}

public abstract class BaseAnimation
{
public static readonly EasingFunctionBase DefaultOut = new QuadraticEase() { EasingMode = EasingMode.EaseOut };
public static readonly EasingFunctionBase DefaultIn = new QuadraticEase() { EasingMode = EasingMode.EaseIn };
public static readonly EasingFunctionBase DefaultInOut = new QuadraticEase() { EasingMode = EasingMode.EaseInOut };

private Storyboard storyboard;
private BaseAnimationCompleteEventArgs completeResult = new BaseAnimationCompleteEventArgs() { NaturallyCompleted = true };

public bool ForceFinalValueRetained { get; set; }
public FrameworkElement Element { get; protected set; }

public Task<BaseAnimationCompleteEventArgs> Activate(FrameworkElement element)
{
return Activate(element, false);
}

public async Task<BaseAnimationCompleteEventArgs> Activate(FrameworkElement element, bool forceFinalValueRetained)
{
if (Element != null)
{
throw new InvalidOperationException();
}
ForceFinalValueRetained = forceFinalValueRetained;
Element = element;
storyboard = CreateStoryboard();
AnimationHelper.AddAnimation(this);
await storyboard.BeginAsync();

storyboard = null;
AnimationHelper.RemoveAnimation(this);
Element = null;

var result = completeResult;
return result;
}

public void Stop()
{
if (storyboard != null)
{
storyboard.Stop();
completeResult.NaturallyCompleted = false;
}
}

public virtual bool Equivalent(BaseAnimation animation)
{
return animation.GetType() == GetType();
}

protected abstract Storyboard CreateStoryboard();

public abstract void Retain();
}
}
Loading

0 comments on commit 1dd0eb6

Please sign in to comment.