├── .gitignore ├── LICENSE ├── MobileApp ├── ExpenseIt │ ├── ExpenseIt.Droid │ │ ├── Assets │ │ │ └── AboutAssets.txt │ │ ├── InvoiceIt.Droid.csproj │ │ ├── MainActivity.cs │ │ ├── MainApplication.cs │ │ ├── Properties │ │ │ ├── AndroidManifest.xml │ │ │ └── AssemblyInfo.cs │ │ ├── Resources │ │ │ ├── AboutResources.txt │ │ │ ├── Resource.Designer.cs │ │ │ ├── drawable-hdpi │ │ │ │ └── icon.png │ │ │ ├── drawable-xhdpi │ │ │ │ └── icon.png │ │ │ ├── drawable-xxhdpi │ │ │ │ └── icon.png │ │ │ ├── drawable │ │ │ │ └── icon.png │ │ │ ├── layout │ │ │ │ ├── Tabbar.axml │ │ │ │ └── Toolbar.axml │ │ │ └── values │ │ │ │ └── styles.xml │ │ ├── app.config │ │ └── packages.config │ ├── ExpenseIt.UWP │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── Assets │ │ │ ├── LockScreenLogo.scale-200.png │ │ │ ├── SplashScreen.scale-200.png │ │ │ ├── Square150x150Logo.scale-200.png │ │ │ ├── Square44x44Logo.scale-200.png │ │ │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ │ │ ├── StoreLogo.png │ │ │ └── Wide310x150Logo.scale-200.png │ │ ├── InvoiceIt.UWP.csproj │ │ ├── InvoiceIt.UWP.nuget.targets │ │ ├── MainPage.xaml │ │ ├── MainPage.xaml.cs │ │ ├── Package.appxmanifest │ │ ├── Properties │ │ │ ├── AssemblyInfo.cs │ │ │ └── Default.rd.xml │ │ ├── project.json │ │ └── project.lock.json │ ├── ExpenseIt.iOS │ │ ├── AppDelegate.cs │ │ ├── Entitlements.plist │ │ ├── Info.plist │ │ ├── InvoiceIt.iOS.csproj │ │ ├── Main.cs │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── Resources │ │ │ ├── Default-568h@2x.png │ │ │ ├── Default-Portrait.png │ │ │ ├── Default-Portrait@2x.png │ │ │ ├── Default.png │ │ │ ├── Default@2x.png │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-60@3x.png │ │ │ ├── Icon-76.png │ │ │ ├── Icon-76@2x.png │ │ │ ├── Icon-Small-40.png │ │ │ ├── Icon-Small-40@2x.png │ │ │ ├── Icon-Small-40@3x.png │ │ │ ├── Icon-Small.png │ │ │ ├── Icon-Small@2x.png │ │ │ ├── Icon-Small@3x.png │ │ │ └── LaunchScreen.storyboard │ │ ├── app.config │ │ ├── iTunesArtwork │ │ ├── iTunesArtwork@2x │ │ └── packages.config │ └── ExpenseIt │ │ ├── APIResponse.cs │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── CardViewCell.cs │ │ ├── Expense.cs │ │ ├── InvoiceIt.csproj │ │ ├── InvoicesPage.xaml │ │ ├── InvoicesPage.xaml.cs │ │ ├── InvoicesViewModel.cs │ │ ├── MLResponseOutput.cs │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ ├── app.config │ │ └── packages.config └── InvoiceIt.sln ├── README.md ├── ocr-from-url.py ├── ocr.py ├── prep-data.py ├── prep-image-url.py └── redistribute-data.py /.gitignore: -------------------------------------------------------------------------------- 1 | #credential 2 | config.ini 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | env/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *,cover 49 | .hypothesis/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | local_settings.py 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # IPython Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # dotenv 82 | .env 83 | 84 | # virtualenv 85 | venv/ 86 | ENV/ 87 | 88 | # Spyder project settings 89 | .spyderproject 90 | .spyderworkspace 91 | 92 | # Rope project settings 93 | .ropeproject 94 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Microsoft Partner Catalyst Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/Assets/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories) and given a Build Action of "AndroidAsset". 3 | 4 | These files will be deployed with you package and will be accessible using Android's 5 | AssetManager, like this: 6 | 7 | public class ReadAsset : Activity 8 | { 9 | protected override void OnCreate (Bundle bundle) 10 | { 11 | base.OnCreate (bundle); 12 | 13 | InputStream input = Assets.Open ("my_asset.txt"); 14 | } 15 | } 16 | 17 | Additionally, some Android functions will automatically load asset files: 18 | 19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); 20 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/InvoiceIt.Droid.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9} 9 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10 | Library 11 | Properties 12 | InvoiceIt.Droid 13 | InvoiceIt.Droid 14 | 512 15 | true 16 | Resources\Resource.Designer.cs 17 | Off 18 | Properties\AndroidManifest.xml 19 | true 20 | v6.0 21 | armeabi,armeabi-v7a,x86 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | true 31 | full 32 | false 33 | bin\Debug\ 34 | DEBUG;TRACE 35 | prompt 36 | 4 37 | True 38 | None 39 | 40 | 41 | pdbonly 42 | true 43 | bin\Release\ 44 | TRACE 45 | prompt 46 | 4 47 | False 48 | SdkOnly 49 | 50 | 51 | 52 | ..\..\packages\Xamarin.Forms.2.3.0.107\lib\MonoAndroid10\FormsViewGroup.dll 53 | True 54 | 55 | 56 | 57 | 58 | ..\..\packages\Plugin.CurrentActivity.1.0.1\lib\MonoAndroid10\Plugin.CurrentActivity.dll 59 | True 60 | 61 | 62 | ..\..\packages\Xam.Plugin.Media.2.3.0\lib\MonoAndroid10\Plugin.Media.dll 63 | True 64 | 65 | 66 | ..\..\packages\Xam.Plugin.Media.2.3.0\lib\MonoAndroid10\Plugin.Media.Abstractions.dll 67 | True 68 | 69 | 70 | ..\..\packages\Plugin.Permissions.1.1.7\lib\MonoAndroid10\Plugin.Permissions.dll 71 | True 72 | 73 | 74 | ..\..\packages\Plugin.Permissions.1.1.7\lib\MonoAndroid10\Plugin.Permissions.Abstractions.dll 75 | True 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | ..\..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Animated.Vector.Drawable.dll 84 | True 85 | 86 | 87 | ..\..\packages\Xamarin.Android.Support.Design.23.3.0\lib\MonoAndroid43\Xamarin.Android.Support.Design.dll 88 | True 89 | 90 | 91 | ..\..\packages\Xamarin.Android.Support.v4.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll 92 | True 93 | 94 | 95 | ..\..\packages\Xamarin.Android.Support.v7.AppCompat.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll 96 | True 97 | 98 | 99 | ..\..\packages\Xamarin.Android.Support.v7.CardView.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.CardView.dll 100 | True 101 | 102 | 103 | ..\..\packages\Xamarin.Android.Support.v7.MediaRouter.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.MediaRouter.dll 104 | True 105 | 106 | 107 | ..\..\packages\Xamarin.Android.Support.v7.RecyclerView.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.RecyclerView.dll 108 | True 109 | 110 | 111 | ..\..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Vector.Drawable.dll 112 | True 113 | 114 | 115 | ..\..\packages\Xamarin.Forms.2.3.0.107\lib\MonoAndroid10\Xamarin.Forms.Core.dll 116 | True 117 | 118 | 119 | ..\..\packages\Xamarin.Forms.2.3.0.107\lib\MonoAndroid10\Xamarin.Forms.Platform.dll 120 | True 121 | 122 | 123 | ..\..\packages\Xamarin.Forms.2.3.0.107\lib\MonoAndroid10\Xamarin.Forms.Platform.Android.dll 124 | True 125 | 126 | 127 | ..\..\packages\Xamarin.Forms.2.3.0.107\lib\MonoAndroid10\Xamarin.Forms.Xaml.dll 128 | True 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | {1825C5AF-CCF4-4348-9049-273B7C29F855} 160 | InvoiceIt 161 | 162 | 163 | 164 | 165 | 166 | 167 | 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}. 168 | 169 | 170 | 171 | 172 | 173 | 180 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/MainActivity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Android.App; 4 | using Android.Content.PM; 5 | using Android.Runtime; 6 | using Android.Views; 7 | using Android.Widget; 8 | using Android.OS; 9 | 10 | namespace InvoiceIt.Droid 11 | { 12 | [Activity(Label = "InvoiceIt", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] 13 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity 14 | { 15 | protected override void OnCreate(Bundle bundle) 16 | { 17 | TabLayoutResource = Resource.Layout.Tabbar; 18 | ToolbarResource = Resource.Layout.Toolbar; 19 | 20 | base.OnCreate(bundle); 21 | 22 | global::Xamarin.Forms.Forms.Init(this, bundle); 23 | LoadApplication(new App()); 24 | } 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/MainApplication.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Android.App; 4 | using Android.OS; 5 | using Android.Runtime; 6 | using Plugin.CurrentActivity; 7 | 8 | namespace InvoiceIt.Droid 9 | { 10 | //You can specify additional application information in this attribute 11 | [Application] 12 | public class MainApplication : Application, Application.IActivityLifecycleCallbacks 13 | { 14 | public MainApplication(IntPtr handle, JniHandleOwnership transer) 15 | :base(handle, transer) 16 | { 17 | } 18 | 19 | public override void OnCreate() 20 | { 21 | base.OnCreate(); 22 | RegisterActivityLifecycleCallbacks(this); 23 | //A great place to initialize Xamarin.Insights and Dependency Services! 24 | } 25 | 26 | public override void OnTerminate() 27 | { 28 | base.OnTerminate(); 29 | UnregisterActivityLifecycleCallbacks(this); 30 | } 31 | 32 | public void OnActivityCreated(Activity activity, Bundle savedInstanceState) 33 | { 34 | CrossCurrentActivity.Current.Activity = activity; 35 | } 36 | 37 | public void OnActivityDestroyed(Activity activity) 38 | { 39 | } 40 | 41 | public void OnActivityPaused(Activity activity) 42 | { 43 | } 44 | 45 | public void OnActivityResumed(Activity activity) 46 | { 47 | CrossCurrentActivity.Current.Activity = activity; 48 | } 49 | 50 | public void OnActivitySaveInstanceState(Activity activity, Bundle outState) 51 | { 52 | } 53 | 54 | public void OnActivityStarted(Activity activity) 55 | { 56 | CrossCurrentActivity.Current.Activity = activity; 57 | } 58 | 59 | public void OnActivityStopped(Activity activity) 60 | { 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using Android.App; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("InvoiceIt.Droid")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("InvoiceIt.Droid")] 14 | [assembly: AssemblyCopyright("Copyright © 2014")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: ComVisible(false)] 18 | 19 | // Version information for an assembly consists of the following four values: 20 | // 21 | // Major Version 22 | // Minor Version 23 | // Build Number 24 | // Revision 25 | // 26 | // You can specify all the values or you can default the Build and Revision Numbers 27 | // by using the '*' as shown below: 28 | // [assembly: AssemblyVersion("1.0.*")] 29 | [assembly: AssemblyVersion("1.0.0.0")] 30 | [assembly: AssemblyFileVersion("1.0.0.0")] 31 | 32 | // Add some common permissions, these can be removed if not needed 33 | [assembly: UsesPermission(Android.Manifest.Permission.Internet)] 34 | [assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)] 35 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/Resources/AboutResources.txt: -------------------------------------------------------------------------------- 1 | Images, layout descriptions, binary blobs and string dictionaries can be included 2 | in your application as resource files. Various Android APIs are designed to 3 | operate on the resource IDs instead of dealing with images, strings or binary blobs 4 | directly. 5 | 6 | For example, a sample Android app that contains a user interface layout (main.xml), 7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 8 | would keep its resources in the "Resources" directory of the application: 9 | 10 | Resources/ 11 | drawable-hdpi/ 12 | icon.png 13 | 14 | drawable-ldpi/ 15 | icon.png 16 | 17 | drawable-mdpi/ 18 | icon.png 19 | 20 | layout/ 21 | main.xml 22 | 23 | values/ 24 | strings.xml 25 | 26 | In order to get the build system to recognize Android resources, set the build action to 27 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 28 | instead operate on resource IDs. When you compile an Android application that uses resources, 29 | the build system will package the resources for distribution and generate a class called 30 | "Resource" that contains the tokens for each one of the resources included. For example, 31 | for the above Resources layout, this is what the Resource class would expose: 32 | 33 | public class Resource { 34 | public class drawable { 35 | public const int icon = 0x123; 36 | } 37 | 38 | public class layout { 39 | public const int main = 0x456; 40 | } 41 | 42 | public class strings { 43 | public const int first_string = 0xabc; 44 | public const int second_string = 0xbcd; 45 | } 46 | } 47 | 48 | You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main 49 | to reference the layout/main.xml file, or Resource.strings.first_string to reference the first 50 | string in the dictionary file values/strings.xml. 51 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/Resources/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.Droid/Resources/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/Resources/drawable-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.Droid/Resources/drawable-xhdpi/icon.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/Resources/drawable-xxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.Droid/Resources/drawable-xxhdpi/icon.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/Resources/drawable/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.Droid/Resources/drawable/icon.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/Resources/layout/Tabbar.axml: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/Resources/layout/Toolbar.axml: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/Resources/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 26 | 27 | 30 | 31 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.Droid/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.ApplicationModel; 7 | using Windows.ApplicationModel.Activation; 8 | using Windows.Foundation; 9 | using Windows.Foundation.Collections; 10 | using Windows.UI.Xaml; 11 | using Windows.UI.Xaml.Controls; 12 | using Windows.UI.Xaml.Controls.Primitives; 13 | using Windows.UI.Xaml.Data; 14 | using Windows.UI.Xaml.Input; 15 | using Windows.UI.Xaml.Media; 16 | using Windows.UI.Xaml.Navigation; 17 | 18 | namespace InvoiceIt.UWP 19 | { 20 | /// 21 | /// Provides application-specific behavior to supplement the default Application class. 22 | /// 23 | sealed partial class App : Application 24 | { 25 | /// 26 | /// Initializes the singleton application object. This is the first line of authored code 27 | /// executed, and as such is the logical equivalent of main() or WinMain(). 28 | /// 29 | public App() 30 | { 31 | this.InitializeComponent(); 32 | this.Suspending += OnSuspending; 33 | } 34 | 35 | /// 36 | /// Invoked when the application is launched normally by the end user. Other entry points 37 | /// will be used such as when the application is launched to open a specific file. 38 | /// 39 | /// Details about the launch request and process. 40 | protected override void OnLaunched(LaunchActivatedEventArgs e) 41 | { 42 | 43 | #if DEBUG 44 | if (System.Diagnostics.Debugger.IsAttached) 45 | { 46 | this.DebugSettings.EnableFrameRateCounter = true; 47 | } 48 | #endif 49 | 50 | Frame rootFrame = Window.Current.Content as Frame; 51 | 52 | // Do not repeat app initialization when the Window already has content, 53 | // just ensure that the window is active 54 | if (rootFrame == null) 55 | { 56 | // Create a Frame to act as the navigation context and navigate to the first page 57 | rootFrame = new Frame(); 58 | 59 | rootFrame.NavigationFailed += OnNavigationFailed; 60 | 61 | Xamarin.Forms.Forms.Init(e); 62 | 63 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) 64 | { 65 | //TODO: Load state from previously suspended application 66 | } 67 | 68 | // Place the frame in the current Window 69 | Window.Current.Content = rootFrame; 70 | } 71 | 72 | if (rootFrame.Content == null) 73 | { 74 | // When the navigation stack isn't restored navigate to the first page, 75 | // configuring the new page by passing required information as a navigation 76 | // parameter 77 | rootFrame.Navigate(typeof(MainPage), e.Arguments); 78 | } 79 | // Ensure the current window is active 80 | Window.Current.Activate(); 81 | } 82 | 83 | /// 84 | /// Invoked when Navigation to a certain page fails 85 | /// 86 | /// The Frame which failed navigation 87 | /// Details about the navigation failure 88 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e) 89 | { 90 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName); 91 | } 92 | 93 | /// 94 | /// Invoked when application execution is being suspended. Application state is saved 95 | /// without knowing whether the application will be terminated or resumed with the contents 96 | /// of memory still intact. 97 | /// 98 | /// The source of the suspend request. 99 | /// Details about the suspend request. 100 | private void OnSuspending(object sender, SuspendingEventArgs e) 101 | { 102 | var deferral = e.SuspendingOperation.GetDeferral(); 103 | //TODO: Save application state and stop any background activity 104 | deferral.Complete(); 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/StoreLogo.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.UWP/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/InvoiceIt.UWP.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x86 7 | {07F9A8B3-5E21-4801-8FA5-F0928B847292} 8 | AppContainerExe 9 | Properties 10 | ExpenseIt.UWP 11 | ExpenseIt.UWP 12 | en-US 13 | UAP 14 | 10.0.10586.0 15 | 10.0.10586.0 16 | 14 17 | true 18 | 512 19 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 20 | Windows_TemporaryKey.pfx 21 | 22 | 23 | true 24 | bin\ARM\Debug\ 25 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 26 | ;2008 27 | full 28 | ARM 29 | false 30 | prompt 31 | true 32 | 33 | 34 | bin\ARM\Release\ 35 | TRACE;NETFX_CORE;WINDOWS_UWP 36 | true 37 | ;2008 38 | pdbonly 39 | ARM 40 | false 41 | prompt 42 | true 43 | true 44 | 45 | 46 | true 47 | bin\x64\Debug\ 48 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 49 | ;2008 50 | full 51 | x64 52 | false 53 | prompt 54 | true 55 | 56 | 57 | bin\x64\Release\ 58 | TRACE;NETFX_CORE;WINDOWS_UWP 59 | true 60 | ;2008 61 | pdbonly 62 | x64 63 | false 64 | prompt 65 | true 66 | true 67 | 68 | 69 | true 70 | bin\x86\Debug\ 71 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 72 | ;2008 73 | full 74 | x86 75 | false 76 | prompt 77 | true 78 | 79 | 80 | bin\x86\Release\ 81 | TRACE;NETFX_CORE;WINDOWS_UWP 82 | true 83 | ;2008 84 | pdbonly 85 | x86 86 | false 87 | prompt 88 | true 89 | true 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | App.xaml 98 | 99 | 100 | MainPage.xaml 101 | 102 | 103 | 104 | 105 | 106 | Designer 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | MSBuild:Compile 123 | Designer 124 | 125 | 126 | MSBuild:Compile 127 | Designer 128 | 129 | 130 | 131 | 132 | {1825C5AF-CCF4-4348-9049-273B7C29F855} 133 | InvoiceIt 134 | 135 | 136 | 137 | 14.0 138 | 139 | 140 | 147 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/InvoiceIt.UWP.nuget.targets: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(UserProfile)\.nuget\packages\ 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/MainPage.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/MainPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.Foundation; 7 | using Windows.Foundation.Collections; 8 | using Windows.UI.Xaml; 9 | using Windows.UI.Xaml.Controls; 10 | using Windows.UI.Xaml.Controls.Primitives; 11 | using Windows.UI.Xaml.Data; 12 | using Windows.UI.Xaml.Input; 13 | using Windows.UI.Xaml.Media; 14 | using Windows.UI.Xaml.Navigation; 15 | 16 | namespace InvoiceIt.UWP 17 | { 18 | public sealed partial class MainPage 19 | { 20 | public MainPage() 21 | { 22 | this.InitializeComponent(); 23 | 24 | LoadApplication(new InvoiceIt.App()); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | InvoiceIt.UWP 18 | xamarin 19 | Assets\StoreLogo.png 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("InvoiceIt.UWP")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("InvoiceIt.UWP")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/Properties/Default.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.UWP/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0", 4 | "Xam.Plugin.Media": "2.3.0", 5 | "Xamarin.Forms": "2.3.0.107" 6 | }, 7 | "frameworks": { 8 | "uap10.0": {} 9 | }, 10 | "runtimes": { 11 | "win10-arm": {}, 12 | "win10-arm-aot": {}, 13 | "win10-x86": {}, 14 | "win10-x86-aot": {}, 15 | "win10-x64": {}, 16 | "win10-x64-aot": {} 17 | } 18 | } -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using Foundation; 6 | using UIKit; 7 | 8 | namespace InvoiceIt.iOS 9 | { 10 | // The UIApplicationDelegate for the application. This class is responsible for launching the 11 | // User Interface of the application, as well as listening (and optionally responding) to 12 | // application events from iOS. 13 | [Register("AppDelegate")] 14 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate 15 | { 16 | // 17 | // This method is invoked when the application has loaded and is ready to run. In this 18 | // method you should instantiate the window, load the UI into it and then make the window 19 | // visible. 20 | // 21 | // You have 17 seconds to return from this method, or iOS will terminate your application. 22 | // 23 | public override bool FinishedLaunching(UIApplication app, NSDictionary options) 24 | { 25 | global::Xamarin.Forms.Forms.Init(); 26 | LoadApplication(new App()); 27 | 28 | return base.FinishedLaunching(app, options); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Entitlements.plist: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Info.plist: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | UIDeviceFamily 6 | 7 | 1 8 | 2 9 | 10 | UISupportedInterfaceOrientations 11 | 12 | UIInterfaceOrientationPortrait 13 | UIInterfaceOrientationLandscapeLeft 14 | UIInterfaceOrientationLandscapeRight 15 | 16 | UISupportedInterfaceOrientations~ipad 17 | 18 | UIInterfaceOrientationPortrait 19 | UIInterfaceOrientationPortraitUpsideDown 20 | UIInterfaceOrientationLandscapeLeft 21 | UIInterfaceOrientationLandscapeRight 22 | 23 | MinimumOSVersion 24 | 6.0 25 | CFBundleDisplayName 26 | InvoiceIt 27 | CFBundleIdentifier 28 | com.yourcompany.InvoiceIt 29 | CFBundleVersion 30 | 1.0 31 | CFBundleIconFiles 32 | 33 | Icon-60@2x 34 | Icon-60@3x 35 | Icon-76 36 | Icon-76@2x 37 | Default 38 | Default@2x 39 | Default-568h@2x 40 | Default-Portrait 41 | Default-Portrait@2x 42 | Icon-Small-40 43 | Icon-Small-40@2x 44 | Icon-Small-40@3x 45 | Icon-Small 46 | Icon-Small@2x 47 | Icon-Small@3x 48 | 49 | UILaunchStoryboardName 50 | LaunchScreen 51 | 52 | 53 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/InvoiceIt.iOS.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | iPhoneSimulator 6 | 8.0.30703 7 | 2.0 8 | {B2F3F763-FECF-4681-A558-417662CE6A9B} 9 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10 | Exe 11 | ExpenseIt.iOS 12 | Resources 13 | ExpenseItiOS 14 | 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\iPhoneSimulator\Debug 22 | DEBUG 23 | prompt 24 | 4 25 | false 26 | i386, x86_64 27 | None 28 | true 29 | 30 | 31 | none 32 | true 33 | bin\iPhoneSimulator\Release 34 | prompt 35 | 4 36 | None 37 | i386, x86_64 38 | false 39 | 40 | 41 | true 42 | full 43 | false 44 | bin\iPhone\Debug 45 | DEBUG 46 | prompt 47 | 4 48 | false 49 | ARMv7, ARM64 50 | iPhone Developer 51 | true 52 | Entitlements.plist 53 | 54 | 55 | none 56 | true 57 | bin\iPhone\Release 58 | prompt 59 | 4 60 | ARMv7, ARM64 61 | false 62 | iPhone Developer 63 | Entitlements.plist 64 | 65 | 66 | none 67 | True 68 | bin\iPhone\Ad-Hoc 69 | prompt 70 | 4 71 | False 72 | ARMv7, ARM64 73 | True 74 | Automatic:AdHoc 75 | iPhone Distribution 76 | Entitlements.plist 77 | 78 | 79 | none 80 | True 81 | bin\iPhone\AppStore 82 | prompt 83 | 4 84 | False 85 | ARMv7, ARM64 86 | Automatic:AppStore 87 | iPhone Distribution 88 | Entitlements.plist 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | ..\..\packages\Xam.Plugin.Media.2.3.0\lib\Xamarin.iOS10\Plugin.Media.dll 122 | True 123 | 124 | 125 | ..\..\packages\Xam.Plugin.Media.2.3.0\lib\Xamarin.iOS10\Plugin.Media.Abstractions.dll 126 | True 127 | 128 | 129 | 130 | 131 | 132 | ..\..\packages\Xamarin.Forms.2.3.0.107\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll 133 | True 134 | 135 | 136 | ..\..\packages\Xamarin.Forms.2.3.0.107\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll 137 | True 138 | 139 | 140 | ..\..\packages\Xamarin.Forms.2.3.0.107\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll 141 | True 142 | 143 | 144 | ..\..\packages\Xamarin.Forms.2.3.0.107\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll 145 | True 146 | 147 | 148 | 149 | 150 | 151 | {1825C5AF-CCF4-4348-9049-273B7C29F855} 152 | InvoiceIt 153 | 154 | 155 | 156 | 157 | 158 | 159 | 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}. 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Main.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using Foundation; 6 | using UIKit; 7 | 8 | namespace InvoiceIt.iOS 9 | { 10 | public class Application 11 | { 12 | // This is the main entry point of the application. 13 | static void Main(string[] args) 14 | { 15 | // if you want to use a different Application Delegate class from "AppDelegate" 16 | // you can specify it here. 17 | UIApplication.Main(args, null, "AppDelegate"); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("InvoiceIt.iOS")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("InvoiceIt.iOS")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Default-568h@2x.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Default-Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Default-Portrait.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Default-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Default-Portrait@2x.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Default.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Default@2x.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-60@2x.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-60@3x.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-76.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-76@2x.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-Small-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-Small-40.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-Small-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-Small-40@2x.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-Small-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-Small-40@3x.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-Small.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-Small@2x.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/Icon-Small@3x.png -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/Resources/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/iTunesArtwork: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/iTunesArtwork -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/iTunesArtwork@2x: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CatalystCode/receipt-recognition/47edbd191105ea4392773f5c5ea06df45e13bc6b/MobileApp/ExpenseIt/ExpenseIt.iOS/iTunesArtwork@2x -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt.iOS/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/APIResponse.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace ExpenseIt 9 | { 10 | class APIResponse 11 | { 12 | [JsonProperty(PropertyName = "receipt_url")] 13 | public string Receipt_Url { get; set; } 14 | 15 | [JsonProperty(PropertyName = "success")] 16 | public bool Success { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/App.xaml: -------------------------------------------------------------------------------- 1 |  2 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using Xamarin.Forms; 7 | using Xamarin.Forms.Xaml; 8 | 9 | [assembly: XamlCompilation(XamlCompilationOptions.Compile)] 10 | namespace InvoiceIt 11 | { 12 | public partial class App : Application 13 | { 14 | public App() 15 | { 16 | InitializeComponent(); 17 | 18 | MainPage = new NavigationPage(new InvoiceIt.InvoicesPage()) 19 | { 20 | BarBackgroundColor = Color.FromHex("#03A9F4"), 21 | BarTextColor = Color.White 22 | }; 23 | } 24 | 25 | protected override void OnStart() 26 | { 27 | // Handle when your app starts 28 | } 29 | 30 | protected override void OnSleep() 31 | { 32 | // Handle when your app sleeps 33 | } 34 | 35 | protected override void OnResume() 36 | { 37 | // Handle when your app resumes 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/CardViewCell.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using Xamarin.Forms; 8 | 9 | namespace InvoiceIt 10 | { 11 | public class CardViewCell : ViewCell 12 | { 13 | public static readonly BindableProperty TextProperty = 14 | BindableProperty.Create(nameof(Text), typeof(string), typeof(CardViewCell), null, BindingMode.OneWay, propertyChanged: (BindableObject bindable, object oldValue, object newValue) => 15 | { 16 | var ctrl = (CardViewCell)bindable; 17 | ctrl.Text = (string)newValue; 18 | }); 19 | 20 | public string Text 21 | { 22 | get { return (string)GetValue(TextProperty); } 23 | set { SetValue(TextProperty, value); textLabel.Text = value; } 24 | } 25 | 26 | public static readonly BindableProperty DetailProperty = 27 | BindableProperty.Create(nameof(Detail), typeof(string), typeof(CardViewCell), null, BindingMode.OneWay, propertyChanged: (BindableObject bindable, object oldValue, object newValue) => 28 | { 29 | var ctrl = (CardViewCell)bindable; 30 | ctrl.Detail = (string)newValue; 31 | }); 32 | 33 | public string Detail 34 | { 35 | get { return (string)GetValue(DetailProperty); } 36 | set { SetValue(DetailProperty, value); detailTextLabel.Text = value; } 37 | } 38 | 39 | 40 | public static readonly BindableProperty Detail1Property = 41 | BindableProperty.Create(nameof(Detail1), typeof(string), typeof(CardViewCell), null, BindingMode.OneWay, propertyChanged: (BindableObject bindable, object oldValue, object newValue) => 42 | { 43 | var ctrl = (CardViewCell)bindable; 44 | ctrl.Detail1 = (string)newValue; 45 | }); 46 | 47 | public string Detail1 48 | { 49 | get { return (string)GetValue(Detail1Property); } 50 | set { SetValue(Detail1Property, value); detail1TextLabel.Text = value; } 51 | } 52 | 53 | public static readonly BindableProperty Detail2Property = 54 | BindableProperty.Create(nameof(Detail2), typeof(string), typeof(CardViewCell), null, BindingMode.OneWay, propertyChanged: (BindableObject bindable, object oldValue, object newValue) => 55 | { 56 | var ctrl = (CardViewCell)bindable; 57 | ctrl.Detail2 = (string)newValue; 58 | }); 59 | 60 | public string Detail2 61 | { 62 | get { return (string)GetValue(Detail2Property); } 63 | set { SetValue(Detail2Property, value); detail2TextLabel.Text = value; } 64 | } 65 | 66 | public static readonly BindableProperty Detail3Property = 67 | BindableProperty.Create(nameof(Detail3), typeof(string), typeof(CardViewCell), null, BindingMode.OneWay, propertyChanged: (BindableObject bindable, object oldValue, object newValue) => 68 | { 69 | var ctrl = (CardViewCell)bindable; 70 | ctrl.Detail3 = (string)newValue; 71 | }); 72 | 73 | public string Detail3 74 | { 75 | get { return (string)GetValue(Detail3Property); } 76 | set { SetValue(Detail3Property, value); detail3TextLabel.Text = value; } 77 | } 78 | 79 | public static readonly BindableProperty ImageSourceProperty = 80 | BindableProperty.Create(nameof(ImageSource), typeof(ImageSource), typeof(CardViewCell), null, BindingMode.OneWay, propertyChanged: (BindableObject bindable, object oldValue, object newValue) => 81 | { 82 | var ctrl = (CardViewCell)bindable; 83 | ctrl.ImageSource = (ImageSource)newValue; 84 | }); 85 | 86 | public ImageSource ImageSource 87 | { 88 | get { return (ImageSource)GetValue(ImageSourceProperty); } 89 | set { SetValue(ImageSourceProperty, value); image.Source = value; } 90 | } 91 | 92 | 93 | StackLayout layout; 94 | Image image; 95 | Label textLabel; 96 | Label detailTextLabel; 97 | private Label detail1TextLabel; 98 | private Label valueLabel3; 99 | private Label valueLabel2; 100 | private Label detail2TextLabel; 101 | private Label detail3TextLabel; 102 | 103 | public CardViewCell() 104 | { 105 | image = new Image 106 | { 107 | Aspect = Device.OnPlatform(Aspect.AspectFill, Aspect.AspectFill, Aspect.AspectFit), 108 | HorizontalOptions = LayoutOptions.FillAndExpand, 109 | VerticalOptions = LayoutOptions.StartAndExpand, 110 | WidthRequest = 220, 111 | HeightRequest = 200, 112 | Source = ImageSource.FromUri(new Uri("https://avatars3.githubusercontent.com/u/1091304?v=3&s=460")) 113 | }; 114 | 115 | textLabel = new Label 116 | { 117 | FontSize = Device.OnPlatform(15, 15, 15), 118 | TextColor = Device.OnPlatform(Color.FromHex("030303"), Color.FromHex("030303"), Color.FromHex("030303")), 119 | HorizontalOptions = LayoutOptions.Start, 120 | HorizontalTextAlignment = TextAlignment.Start, 121 | Margin = Device.OnPlatform(new Thickness(12, 10, 12, 4), new Thickness(20, 10, 20, 5), new Thickness(20, 10, 20, 5)), 122 | LineBreakMode = LineBreakMode.WordWrap, 123 | VerticalOptions = LayoutOptions.End, 124 | Text = "Pierce Boggan" 125 | }; 126 | 127 | 128 | detail1TextLabel = new Label 129 | { 130 | FontSize = Device.OnPlatform(15, 15, 15), 131 | TextColor = Device.OnPlatform(Color.FromHex("030303"), Color.FromHex("030303"), Color.FromHex("030303")), 132 | HorizontalOptions = LayoutOptions.Start, 133 | HorizontalTextAlignment = TextAlignment.Start, 134 | Margin = Device.OnPlatform(new Thickness(12, 10, 12, 4), new Thickness(20, 10, 20, 5), new Thickness(20, 10, 20, 5)), 135 | LineBreakMode = LineBreakMode.WordWrap, 136 | VerticalOptions = LayoutOptions.End, 137 | Text = "Pierce Boggan" 138 | }; 139 | 140 | 141 | detail2TextLabel = new Label 142 | { 143 | FontSize = Device.OnPlatform(15, 15, 15), 144 | TextColor = Device.OnPlatform(Color.FromHex("030303"), Color.FromHex("030303"), Color.FromHex("030303")), 145 | HorizontalOptions = LayoutOptions.Start, 146 | HorizontalTextAlignment = TextAlignment.Start, 147 | Margin = Device.OnPlatform(new Thickness(12, 10, 12, 4), new Thickness(20, 10, 20, 5), new Thickness(20, 10, 20, 5)), 148 | LineBreakMode = LineBreakMode.WordWrap, 149 | VerticalOptions = LayoutOptions.End, 150 | Text = "Pierce Boggan" 151 | }; 152 | 153 | detailTextLabel = new Label 154 | { 155 | FontSize = Device.OnPlatform(13, 13, 13), 156 | TextColor = Device.OnPlatform(Color.FromHex("8F8E94"), Color.FromHex("8F8E94"), Color.FromHex("8F8E94")), 157 | HorizontalOptions = LayoutOptions.Start, 158 | HorizontalTextAlignment = TextAlignment.Start, 159 | Margin = Device.OnPlatform(new Thickness(12, 0, 10, 12), new Thickness(20, 0, 20, 20), new Thickness(20, 0, 20, 20)), 160 | LineBreakMode = LineBreakMode.WordWrap, 161 | VerticalOptions = LayoutOptions.End, 162 | Text = "pierce@xamarin.com" 163 | }; 164 | 165 | 166 | detail3TextLabel = new Label 167 | { 168 | FontSize = Device.OnPlatform(15, 15, 15), 169 | TextColor = Device.OnPlatform(Color.FromHex("030303"), Color.FromHex("030303"), Color.FromHex("030303")), 170 | HorizontalOptions = LayoutOptions.Start, 171 | HorizontalTextAlignment = TextAlignment.Start, 172 | Margin = Device.OnPlatform(new Thickness(12, 10, 12, 4), new Thickness(20, 10, 20, 5), new Thickness(20, 10, 20, 5)), 173 | LineBreakMode = LineBreakMode.WordWrap, 174 | VerticalOptions = LayoutOptions.End, 175 | Text = "Pierce Boggan" 176 | }; 177 | 178 | layout = new StackLayout 179 | { 180 | BackgroundColor = Color.White, 181 | Spacing = 0, 182 | Children = { image, detail1TextLabel, detail2TextLabel, detail3TextLabel, textLabel } 183 | }; 184 | 185 | View = layout; 186 | } 187 | 188 | protected override void OnBindingContextChanged() 189 | { 190 | base.OnBindingContextChanged(); 191 | 192 | View.BindingContext = BindingContext; 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/Expense.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Plugin.Media.Abstractions; 7 | 8 | using static System.DateTime; 9 | using static System.String; 10 | 11 | namespace InvoiceIt 12 | { 13 | public class Invoice 14 | { 15 | public DateTime TimeStamp { get; set; } = UtcNow; 16 | public string Photo { get; set; } = Empty; 17 | public string ScoredLabel1 { get; set; } 18 | public string ScoredLabel2 { get; set; } 19 | public string ScoredLabel3 { get; set; } 20 | } 21 | 22 | public class MLOutputItem 23 | { 24 | public float Probability { get; set; } 25 | public string Category { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/InvoiceIt.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 10.0 6 | Debug 7 | AnyCPU 8 | {1825C5AF-CCF4-4348-9049-273B7C29F855} 9 | Library 10 | Properties 11 | ExpenseIt 12 | ExpenseIt 13 | v4.5 14 | Profile111 15 | 512 16 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 17 | 18 | 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | App.xaml 41 | 42 | 43 | 44 | 45 | 46 | InvoicesPage.xaml 47 | 48 | 49 | 50 | 51 | 52 | 53 | Designer 54 | MSBuild:UpdateDesignTimeXaml 55 | 56 | 57 | Designer 58 | MSBuild:UpdateDesignTimeXaml 59 | 60 | 61 | 62 | 63 | ..\..\packages\Microsoft.ProjectOxford.Vision.1.0.354\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\Microsoft.ProjectOxford.Vision.dll 64 | True 65 | 66 | 67 | ..\..\packages\Newtonsoft.Json.8.0.2\lib\portable-net40+sl5+wp80+win8+wpa81\Newtonsoft.Json.dll 68 | True 69 | 70 | 71 | ..\..\packages\Xam.Plugin.Media.2.3.0\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Plugin.Media.dll 72 | True 73 | 74 | 75 | ..\..\packages\Xam.Plugin.Media.2.3.0\lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Plugin.Media.Abstractions.dll 76 | True 77 | 78 | 79 | ..\..\packages\System.Net.Http.Formatting.Extension.5.2.3.0\lib\System.Net.Http.Extensions.dll 80 | True 81 | 82 | 83 | ..\..\packages\System.Net.Http.Formatting.Extension.5.2.3.0\lib\System.Net.Http.Formatting.dll 84 | True 85 | 86 | 87 | ..\..\packages\System.Net.Http.Formatting.Extension.5.2.3.0\lib\System.Net.Http.Primitives.dll 88 | True 89 | 90 | 91 | ..\..\packages\Xamarin.Forms.2.3.0.107\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Core.dll 92 | True 93 | 94 | 95 | ..\..\packages\Xamarin.Forms.2.3.0.107\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Platform.dll 96 | True 97 | 98 | 99 | ..\..\packages\Xamarin.Forms.2.3.0.107\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Xaml.dll 100 | True 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 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}. 112 | 113 | 114 | 115 | 116 | 117 | 124 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/InvoicesPage.xaml: -------------------------------------------------------------------------------- 1 |  2 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/InvoicesPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Xamarin.Forms; 7 | 8 | namespace InvoiceIt 9 | { 10 | public partial class InvoicesPage : ContentPage 11 | { 12 | public InvoicesPage() 13 | { 14 | InitializeComponent(); 15 | 16 | BindingContext = new InvoicesViewModel(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/InvoicesViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | using Xamarin.Forms; 9 | 10 | using Plugin.Media; 11 | using Plugin.Media.Abstractions; 12 | 13 | using Microsoft.ProjectOxford.Vision; 14 | using Microsoft.ProjectOxford.Vision.Contract; 15 | using System.ComponentModel; 16 | using System.Diagnostics; 17 | 18 | using static System.Diagnostics.Debug; 19 | using System.Runtime.CompilerServices; 20 | using System.Net.Http.Headers; 21 | using System.Net.Http; 22 | using System.IO; 23 | using Newtonsoft.Json.Linq; 24 | using Newtonsoft.Json; 25 | using Newtonsoft.Json.Converters; 26 | using ExpenseIt; 27 | 28 | namespace InvoiceIt 29 | { 30 | public class InvoicesViewModel : INotifyPropertyChanged 31 | { 32 | public ObservableCollection Invoices { get; } = new ObservableCollection(); 33 | 34 | public string Message { get; set; } = "Hello World!"; 35 | 36 | Command addInvoiceCommand = null; 37 | public Command AddInvoiceCommand => 38 | addInvoiceCommand ?? (addInvoiceCommand = new Command(async () => await ExecuteAddInvoiceCommandAsync())); 39 | 40 | 41 | async Task ExecuteAddInvoiceCommandAsync() 42 | { 43 | try 44 | { 45 | IsBusy = true; 46 | // 1. Add camera logic. 47 | await CrossMedia.Current.Initialize(); 48 | 49 | MediaFile photo; 50 | if (CrossMedia.Current.IsCameraAvailable) 51 | { 52 | photo = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions 53 | { 54 | Directory = "Receipts", 55 | Name = "Receipt" 56 | }); 57 | } 58 | else 59 | { 60 | photo = await CrossMedia.Current.PickPhotoAsync(); 61 | } 62 | 63 | if (photo == null) 64 | { 65 | PrintStatus("Photo was null :("); 66 | return; 67 | } 68 | 69 | 70 | byte[] data = ReadFully(photo.GetStream()); 71 | 72 | using (var client = new HttpClient()) 73 | { 74 | using (var content = new MultipartFormDataContent()) 75 | { 76 | 77 | var fileContent = new ByteArrayContent(data); 78 | fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") // attachment? 79 | { 80 | Name = "file", // required? 81 | FileName = "test.jpg" 82 | }; 83 | content.Add(fileContent); 84 | //IsBusy = false; 85 | 86 | var requestUri = "http://at-dev-vm-zxpapi-01.westus.cloudapp.azure.com/v1.0/groups/1/receipts"; 87 | //var requestUri = "http://requestb.in/11y6k4z1"; 88 | var response = await client.PostAsync(requestUri, content); 89 | if (response.IsSuccessStatusCode) 90 | { 91 | string result = await response.Content.ReadAsStringAsync(); 92 | APIResponse apiResponse = JsonConvert.DeserializeObject(result); 93 | 94 | using (var clientML = new HttpClient()) 95 | { 96 | string temp = apiResponse.Receipt_Url.Replace("https", "http"); 97 | 98 | var scoreRequest = new 99 | { 100 | 101 | Inputs = new Dictionary>>() { 102 | { 103 | "input1", 104 | new List>() { 105 | new Dictionary() { 106 | //{ "Category", "" }, 107 | { "Url", temp}, 108 | } 109 | } 110 | }, 111 | }, 112 | GlobalParameters = new Dictionary() 113 | { 114 | } 115 | }; 116 | 117 | var jsonToSend = JsonConvert.SerializeObject(scoreRequest); 118 | var body = new StringContent(jsonToSend, Encoding.UTF8, "application/json"); 119 | 120 | const string apiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; // Replace this with the API key for the web service 121 | clientML.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); 122 | clientML.BaseAddress = new Uri("https://xxx.services.azureml.net/subscriptions/xxxxxxxxx/services/xxxxxxx/execute?api-version=2.0&format=swagger"); 123 | 124 | var responseML = await clientML.PostAsync("", body); 125 | 126 | if (responseML.IsSuccessStatusCode) 127 | { 128 | string resultML = await responseML.Content.ReadAsStringAsync(); 129 | // Convert JSON to object 130 | MLResponse obj = JsonConvert.DeserializeObject(resultML); 131 | 132 | var outPuts = new List(6); 133 | 134 | outPuts.Add(new MLOutputItem { Category = "Clothes and Accessories", Probability = (float)obj.Results.Output[0].ClothesAndAccessoriesProbability }); 135 | outPuts.Add(new MLOutputItem { Category = "Daily Snacks", Probability = (float)obj.Results.Output[0].DailySnacksProbability }); 136 | outPuts.Add(new MLOutputItem { Category = "Dining Out", Probability = (float)obj.Results.Output[0].DiningOutProbability }); 137 | outPuts.Add(new MLOutputItem { Category = "Entertainment", Probability = (float)obj.Results.Output[0].EntertainmentProbability }); 138 | outPuts.Add(new MLOutputItem { Category = "Fuel", Probability = (float)obj.Results.Output[0].FuelProbability }); 139 | outPuts.Add(new MLOutputItem { Category = "Groceries", Probability = (float)obj.Results.Output[0].GroceriesProbability }); 140 | 141 | outPuts = outPuts.OrderByDescending(x => x.Probability).ToList(); 142 | 143 | Invoices.Add(new Invoice 144 | { 145 | ScoredLabel1 = outPuts[0].Category + " : " + outPuts[0].Probability , 146 | ScoredLabel2 = outPuts[1].Category + " : " + outPuts[1].Probability , 147 | ScoredLabel3 = outPuts[2].Category + " : " + outPuts[2].Probability , 148 | Photo = photo.Path, 149 | TimeStamp = DateTime.Now 150 | }); 151 | 152 | } 153 | } 154 | } 155 | } 156 | } 157 | } 158 | catch (Exception ex) 159 | { 160 | 161 | } 162 | finally 163 | { 164 | IsBusy = false; 165 | } 166 | 167 | } 168 | 169 | 170 | public void PrintStatus(string helloWorld) 171 | { 172 | if (helloWorld == null) 173 | throw new ArgumentNullException(nameof(helloWorld)); 174 | 175 | WriteLine(helloWorld); 176 | } 177 | 178 | public static byte[] ReadFully(Stream input) 179 | { 180 | byte[] buffer = new byte[16 * 1024]; 181 | using (MemoryStream ms = new MemoryStream()) 182 | { 183 | int read; 184 | while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 185 | { 186 | ms.Write(buffer, 0, read); 187 | } 188 | return ms.ToArray(); 189 | } 190 | } 191 | 192 | public event PropertyChangedEventHandler PropertyChanged; 193 | void OnPropertyChanged([CallerMemberName]string propertyName = "") => 194 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 195 | 196 | 197 | bool busy; 198 | public bool IsBusy 199 | { 200 | get { return busy; } 201 | set 202 | { 203 | if (busy == value) 204 | return; 205 | 206 | busy = value; 207 | OnPropertyChanged(); 208 | OnPropertyChanged(nameof(Message)); 209 | } 210 | } 211 | 212 | 213 | } 214 | } -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/MLResponseOutput.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace ExpenseIt 9 | { 10 | 11 | public class MLResponseOutput 12 | { 13 | [JsonProperty(PropertyName = "Scored Probabilities for Class \"clothes and accessories\"")] 14 | public double ClothesAndAccessoriesProbability { get; set; } 15 | [JsonProperty(PropertyName = "Scored Probabilities for Class \"daily snack\"")] 16 | public double DailySnacksProbability { get; set; } 17 | [JsonProperty(PropertyName = "Scored Probabilities for Class \"dining out\"")] 18 | public double DiningOutProbability { get; set; } 19 | [JsonProperty(PropertyName = "Scored Probabilities for Class \"entertinement\"")] 20 | public double EntertainmentProbability { get; set; } 21 | [JsonProperty(PropertyName = "Scored Probabilities for Class \"fuel\"")] 22 | public double FuelProbability { get; set; } 23 | [JsonProperty(PropertyName = "Scored Probabilities for Class \"groceries\"")] 24 | public double GroceriesProbability { get; set; } 25 | [JsonProperty(PropertyName = "Scored Labels")] 26 | public string ScoredLabels { get; set; } 27 | } 28 | 29 | public class MLResponseResults 30 | { 31 | [JsonProperty(PropertyName = "output1")] 32 | public List Output { get; set; } 33 | } 34 | 35 | public class MLResponse 36 | { 37 | public MLResponseResults Results { get; set; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Resources; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("InvoiceIt")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("InvoiceIt")] 14 | [assembly: AssemblyCopyright("Copyright © 2014")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: NeutralResourcesLanguage("en")] 18 | 19 | // Version information for an assembly consists of the following four values: 20 | // 21 | // Major Version 22 | // Minor Version 23 | // Build Number 24 | // Revision 25 | // 26 | // You can specify all the values or you can default the Build and Revision Numbers 27 | // by using the '*' as shown below: 28 | // [assembly: AssemblyVersion("1.0.*")] 29 | [assembly: AssemblyVersion("1.0.0.0")] 30 | [assembly: AssemblyFileVersion("1.0.0.0")] 31 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /MobileApp/ExpenseIt/ExpenseIt/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MobileApp/InvoiceIt.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InvoiceIt.Droid", "ExpenseIt\ExpenseIt.Droid\InvoiceIt.Droid.csproj", "{C4588DE8-DA54-43BC-8814-374CE67FF7B9}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InvoiceIt.iOS", "ExpenseIt\ExpenseIt.iOS\InvoiceIt.iOS.csproj", "{B2F3F763-FECF-4681-A558-417662CE6A9B}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InvoiceIt.UWP", "ExpenseIt\ExpenseIt.UWP\InvoiceIt.UWP.csproj", "{07F9A8B3-5E21-4801-8FA5-F0928B847292}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InvoiceIt", "ExpenseIt\ExpenseIt\InvoiceIt.csproj", "{1825C5AF-CCF4-4348-9049-273B7C29F855}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Ad-Hoc|Any CPU = Ad-Hoc|Any CPU 17 | Ad-Hoc|ARM = Ad-Hoc|ARM 18 | Ad-Hoc|iPhone = Ad-Hoc|iPhone 19 | Ad-Hoc|iPhoneSimulator = Ad-Hoc|iPhoneSimulator 20 | Ad-Hoc|x64 = Ad-Hoc|x64 21 | Ad-Hoc|x86 = Ad-Hoc|x86 22 | AppStore|Any CPU = AppStore|Any CPU 23 | AppStore|ARM = AppStore|ARM 24 | AppStore|iPhone = AppStore|iPhone 25 | AppStore|iPhoneSimulator = AppStore|iPhoneSimulator 26 | AppStore|x64 = AppStore|x64 27 | AppStore|x86 = AppStore|x86 28 | Debug|Any CPU = Debug|Any CPU 29 | Debug|ARM = Debug|ARM 30 | Debug|iPhone = Debug|iPhone 31 | Debug|iPhoneSimulator = Debug|iPhoneSimulator 32 | Debug|x64 = Debug|x64 33 | Debug|x86 = Debug|x86 34 | Release|Any CPU = Release|Any CPU 35 | Release|ARM = Release|ARM 36 | Release|iPhone = Release|iPhone 37 | Release|iPhoneSimulator = Release|iPhoneSimulator 38 | Release|x64 = Release|x64 39 | Release|x86 = Release|x86 40 | EndGlobalSection 41 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 42 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU 43 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU 44 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|Any CPU.Deploy.0 = Release|Any CPU 45 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU 46 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|ARM.Build.0 = Release|Any CPU 47 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|ARM.Deploy.0 = Release|Any CPU 48 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU 49 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU 50 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|iPhone.Deploy.0 = Release|Any CPU 51 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU 52 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU 53 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|Any CPU 54 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU 55 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|x64.Build.0 = Release|Any CPU 56 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|x64.Deploy.0 = Release|Any CPU 57 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU 58 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|x86.Build.0 = Release|Any CPU 59 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Ad-Hoc|x86.Deploy.0 = Release|Any CPU 60 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|Any CPU.ActiveCfg = Release|Any CPU 61 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|Any CPU.Build.0 = Release|Any CPU 62 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|Any CPU.Deploy.0 = Release|Any CPU 63 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|ARM.ActiveCfg = Release|Any CPU 64 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|ARM.Build.0 = Release|Any CPU 65 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|ARM.Deploy.0 = Release|Any CPU 66 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|iPhone.ActiveCfg = Release|Any CPU 67 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|iPhone.Build.0 = Release|Any CPU 68 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|iPhone.Deploy.0 = Release|Any CPU 69 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU 70 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU 71 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|iPhoneSimulator.Deploy.0 = Release|Any CPU 72 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|x64.ActiveCfg = Release|Any CPU 73 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|x64.Build.0 = Release|Any CPU 74 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|x64.Deploy.0 = Release|Any CPU 75 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|x86.ActiveCfg = Release|Any CPU 76 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|x86.Build.0 = Release|Any CPU 77 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.AppStore|x86.Deploy.0 = Release|Any CPU 78 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 79 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|Any CPU.Build.0 = Debug|Any CPU 80 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|Any CPU.Deploy.0 = Debug|Any CPU 81 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|ARM.ActiveCfg = Debug|Any CPU 82 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|ARM.Build.0 = Debug|Any CPU 83 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|ARM.Deploy.0 = Debug|Any CPU 84 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|iPhone.ActiveCfg = Debug|Any CPU 85 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|iPhone.Build.0 = Debug|Any CPU 86 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|iPhone.Deploy.0 = Debug|Any CPU 87 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU 88 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU 89 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|iPhoneSimulator.Deploy.0 = Debug|Any CPU 90 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|x64.ActiveCfg = Debug|Any CPU 91 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|x64.Build.0 = Debug|Any CPU 92 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|x64.Deploy.0 = Debug|Any CPU 93 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|x86.ActiveCfg = Debug|Any CPU 94 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|x86.Build.0 = Debug|Any CPU 95 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Debug|x86.Deploy.0 = Debug|Any CPU 96 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|Any CPU.ActiveCfg = Release|Any CPU 97 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|Any CPU.Build.0 = Release|Any CPU 98 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|Any CPU.Deploy.0 = Release|Any CPU 99 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|ARM.ActiveCfg = Release|Any CPU 100 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|ARM.Build.0 = Release|Any CPU 101 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|ARM.Deploy.0 = Release|Any CPU 102 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|iPhone.ActiveCfg = Release|Any CPU 103 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|iPhone.Build.0 = Release|Any CPU 104 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|iPhone.Deploy.0 = Release|Any CPU 105 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU 106 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|iPhoneSimulator.Build.0 = Release|Any CPU 107 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|iPhoneSimulator.Deploy.0 = Release|Any CPU 108 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|x64.ActiveCfg = Release|Any CPU 109 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|x64.Build.0 = Release|Any CPU 110 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|x64.Deploy.0 = Release|Any CPU 111 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|x86.ActiveCfg = Release|Any CPU 112 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|x86.Build.0 = Release|Any CPU 113 | {C4588DE8-DA54-43BC-8814-374CE67FF7B9}.Release|x86.Deploy.0 = Release|Any CPU 114 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone 115 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Ad-Hoc|ARM.ActiveCfg = Ad-Hoc|iPhone 116 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone 117 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone 118 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator 119 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator 120 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Ad-Hoc|x64.ActiveCfg = Ad-Hoc|iPhone 121 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Ad-Hoc|x86.ActiveCfg = Ad-Hoc|iPhone 122 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone 123 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.AppStore|ARM.ActiveCfg = AppStore|iPhone 124 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.AppStore|iPhone.ActiveCfg = AppStore|iPhone 125 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.AppStore|iPhone.Build.0 = AppStore|iPhone 126 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator 127 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator 128 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.AppStore|x64.ActiveCfg = AppStore|iPhone 129 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.AppStore|x86.ActiveCfg = AppStore|iPhone 130 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Debug|Any CPU.ActiveCfg = Debug|iPhone 131 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Debug|Any CPU.Build.0 = Debug|iPhone 132 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Debug|ARM.ActiveCfg = Debug|iPhone 133 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Debug|iPhone.ActiveCfg = Debug|iPhone 134 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Debug|iPhone.Build.0 = Debug|iPhone 135 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator 136 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator 137 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Debug|x64.ActiveCfg = Debug|iPhone 138 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Debug|x86.ActiveCfg = Debug|iPhone 139 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Release|Any CPU.ActiveCfg = Release|iPhone 140 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Release|ARM.ActiveCfg = Release|iPhone 141 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Release|iPhone.ActiveCfg = Release|iPhone 142 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Release|iPhone.Build.0 = Release|iPhone 143 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator 144 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator 145 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Release|x64.ActiveCfg = Release|iPhone 146 | {B2F3F763-FECF-4681-A558-417662CE6A9B}.Release|x86.ActiveCfg = Release|iPhone 147 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|Any CPU.ActiveCfg = Release|x86 148 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|Any CPU.Build.0 = Release|x86 149 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|Any CPU.Deploy.0 = Release|x86 150 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|ARM.ActiveCfg = Release|ARM 151 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|ARM.Build.0 = Release|ARM 152 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|ARM.Deploy.0 = Release|ARM 153 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|iPhone.ActiveCfg = Release|x86 154 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|iPhone.Build.0 = Release|x86 155 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|iPhone.Deploy.0 = Release|x86 156 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|x86 157 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|x86 158 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|iPhoneSimulator.Deploy.0 = Release|x86 159 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|x64.ActiveCfg = Release|x64 160 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|x64.Build.0 = Release|x64 161 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|x64.Deploy.0 = Release|x64 162 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|x86.ActiveCfg = Release|x86 163 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|x86.Build.0 = Release|x86 164 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Ad-Hoc|x86.Deploy.0 = Release|x86 165 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|Any CPU.ActiveCfg = Release|x86 166 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|Any CPU.Build.0 = Release|x86 167 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|Any CPU.Deploy.0 = Release|x86 168 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|ARM.ActiveCfg = Release|ARM 169 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|ARM.Build.0 = Release|ARM 170 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|ARM.Deploy.0 = Release|ARM 171 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|iPhone.ActiveCfg = Release|x86 172 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|iPhone.Build.0 = Release|x86 173 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|iPhone.Deploy.0 = Release|x86 174 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|iPhoneSimulator.ActiveCfg = Release|x86 175 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|iPhoneSimulator.Build.0 = Release|x86 176 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|iPhoneSimulator.Deploy.0 = Release|x86 177 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|x64.ActiveCfg = Release|x64 178 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|x64.Build.0 = Release|x64 179 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|x64.Deploy.0 = Release|x64 180 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|x86.ActiveCfg = Release|x86 181 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|x86.Build.0 = Release|x86 182 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.AppStore|x86.Deploy.0 = Release|x86 183 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|Any CPU.ActiveCfg = Debug|x86 184 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|Any CPU.Build.0 = Debug|x86 185 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|Any CPU.Deploy.0 = Debug|x86 186 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|ARM.ActiveCfg = Debug|ARM 187 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|ARM.Build.0 = Debug|ARM 188 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|ARM.Deploy.0 = Debug|ARM 189 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|iPhone.ActiveCfg = Debug|x86 190 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|iPhoneSimulator.ActiveCfg = Debug|x86 191 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|iPhoneSimulator.Build.0 = Debug|x86 192 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|iPhoneSimulator.Deploy.0 = Debug|x86 193 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|x64.ActiveCfg = Debug|x64 194 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|x64.Build.0 = Debug|x64 195 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|x64.Deploy.0 = Debug|x64 196 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|x86.ActiveCfg = Debug|x86 197 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|x86.Build.0 = Debug|x86 198 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Debug|x86.Deploy.0 = Debug|x86 199 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Release|Any CPU.ActiveCfg = Release|x86 200 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Release|ARM.ActiveCfg = Release|ARM 201 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Release|ARM.Build.0 = Release|ARM 202 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Release|ARM.Deploy.0 = Release|ARM 203 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Release|iPhone.ActiveCfg = Release|x86 204 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Release|iPhoneSimulator.ActiveCfg = Release|x86 205 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Release|x64.ActiveCfg = Release|x64 206 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Release|x64.Build.0 = Release|x64 207 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Release|x64.Deploy.0 = Release|x64 208 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Release|x86.ActiveCfg = Release|x86 209 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Release|x86.Build.0 = Release|x86 210 | {07F9A8B3-5E21-4801-8FA5-F0928B847292}.Release|x86.Deploy.0 = Release|x86 211 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU 212 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU 213 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Ad-Hoc|ARM.ActiveCfg = Release|Any CPU 214 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Ad-Hoc|ARM.Build.0 = Release|Any CPU 215 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU 216 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU 217 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU 218 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU 219 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Ad-Hoc|x64.ActiveCfg = Release|Any CPU 220 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Ad-Hoc|x64.Build.0 = Release|Any CPU 221 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU 222 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Ad-Hoc|x86.Build.0 = Release|Any CPU 223 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.AppStore|Any CPU.ActiveCfg = Release|Any CPU 224 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.AppStore|Any CPU.Build.0 = Release|Any CPU 225 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.AppStore|ARM.ActiveCfg = Release|Any CPU 226 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.AppStore|ARM.Build.0 = Release|Any CPU 227 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.AppStore|iPhone.ActiveCfg = Release|Any CPU 228 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.AppStore|iPhone.Build.0 = Release|Any CPU 229 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU 230 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU 231 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.AppStore|x64.ActiveCfg = Release|Any CPU 232 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.AppStore|x64.Build.0 = Release|Any CPU 233 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.AppStore|x86.ActiveCfg = Release|Any CPU 234 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.AppStore|x86.Build.0 = Release|Any CPU 235 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 236 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Debug|Any CPU.Build.0 = Debug|Any CPU 237 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Debug|ARM.ActiveCfg = Debug|Any CPU 238 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Debug|ARM.Build.0 = Debug|Any CPU 239 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Debug|iPhone.ActiveCfg = Debug|Any CPU 240 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Debug|iPhone.Build.0 = Debug|Any CPU 241 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU 242 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU 243 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Debug|x64.ActiveCfg = Debug|Any CPU 244 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Debug|x64.Build.0 = Debug|Any CPU 245 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Debug|x86.ActiveCfg = Debug|Any CPU 246 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Debug|x86.Build.0 = Debug|Any CPU 247 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Release|Any CPU.ActiveCfg = Release|Any CPU 248 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Release|Any CPU.Build.0 = Release|Any CPU 249 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Release|ARM.ActiveCfg = Release|Any CPU 250 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Release|ARM.Build.0 = Release|Any CPU 251 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Release|iPhone.ActiveCfg = Release|Any CPU 252 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Release|iPhone.Build.0 = Release|Any CPU 253 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU 254 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Release|iPhoneSimulator.Build.0 = Release|Any CPU 255 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Release|x64.ActiveCfg = Release|Any CPU 256 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Release|x64.Build.0 = Release|Any CPU 257 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Release|x86.ActiveCfg = Release|Any CPU 258 | {1825C5AF-CCF4-4348-9049-273B7C29F855}.Release|x86.Build.0 = Release|Any CPU 259 | EndGlobalSection 260 | GlobalSection(SolutionProperties) = preSolution 261 | HideSolutionNode = FALSE 262 | EndGlobalSection 263 | EndGlobal 264 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # receipt-recognition 2 | Purpose: Predict type of expenses from imaged receipt, using Microsoft's OCR and AzureML. 3 | 4 | Accompanying [post](https://www.microsoft.com/developerblog/real-life-code/2017/01/02/expense-recognition.html). 5 | 6 | ML/Data Prep (Python): 7 | ---------------------- 8 | 1. ORC.py contains code for converting unstructured image data into structured text data, which is then used to build a predictive model. The code is then adapted so that it can be hosted within Azure ML's Python Module and make the modelling process self-contained within Azure ML Studio. 9 | 10 | 2. This model is trained on ~1100 imaged American receipts for categories: Dining, snack, clothes, feul, groceries, entertainment 11 | 12 | Mobile App (Xamarin): 13 | --------------------- 14 | This is a single page Xamarin Forms based cross platform mobile application which takes an image and calls the partner(Agitare) api to store it in Azure blob storage. Once we get a stored URL to the image, we then pass this URL to Machine learning web service end point to obtain probability scores of different classification groups. The results are shown in a CardViewCell control in a Xamarin forms page. The app uses MVVM pattern to implement this functionality. 15 | 16 | -------------------------------------------------------------------------------- /ocr-from-url.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed Nov 2 10:28:18 2016 4 | @author: chyam 5 | purpose: load images from blob storage, post to Microsoft OCR, save results, populate 'text' to .tsv file. 6 | """ 7 | ### Error: UnicodeEncodeError: 'charmap' codec can't encode character 8 | ### Fixes: at windows console, type chcp 65001, press enter 9 | 10 | from __future__ import print_function 11 | from azure.storage.blob import BlockBlobService 12 | from azure.storage.blob import PublicAccess 13 | import configparser 14 | import time 15 | import requests 16 | import json 17 | import pandas as pd 18 | from io import StringIO 19 | 20 | _url = 'https://api.projectoxford.ai/vision/v1.0/ocr' 21 | _maxNumRetries = 10 22 | 23 | def main(): 24 | 25 | # Get credential 26 | parser = configparser.ConfigParser() 27 | parser.read('config.ini') 28 | STORAGE_ACCOUNT_NAME = parser.get('credential', 'STORAGE_ACCOUNT_NAME') 29 | STORAGE_ACCOUNT_KEY = parser.get('credential', 'STORAGE_ACCOUNT_KEY') 30 | CONTAINER_NAME = parser.get('credential', 'CONTAINER_NAME') 31 | CONTAINER_NAME_METADATA = parser.get('credential', 'CONTAINER_NAME_METADATA') 32 | VISION_API_KEY = parser.get('credential', 'VISION_API_KEY') # need to use Agitare account 33 | CONTAINER_NAME_OCR_2 = parser.get('credential', 'CONTAINER_NAME_OCR_2') 34 | CONTAINER_NAME_STRUCTUREDDATA = parser.get('credential', 'CONTAINER_NAME_STRUCTUREDDATA') 35 | 36 | # access to bloob 37 | block_blob_service = BlockBlobService(account_name=STORAGE_ACCOUNT_NAME, account_key=STORAGE_ACCOUNT_KEY) 38 | block_blob_service.set_container_acl(CONTAINER_NAME, public_access=PublicAccess.Container) 39 | 40 | # empty dataframe 41 | df = pd.DataFrame({'Text' : [], 'Category' : [], 'ReceiptID' : []}) 42 | 43 | # get url and label from file 44 | blob_text = block_blob_service.get_blob_to_text(CONTAINER_NAME_METADATA, 'image-url-6-classes.tsv'); #print(blob_text.content) 45 | df_url_label = pd.DataFrame.from_csv(StringIO(blob_text.content), index_col=None, sep='\t'); #print(df_url_label.shape); print(df_url_label) 46 | 47 | for index, row in df_url_label.iterrows(): 48 | #print(row['Category']) 49 | #print(row['Url']) 50 | 51 | imageurl = row['Url'] 52 | # OCR parameters 53 | params = { 'language': 'en', 'detectOrientation ': 'true'} 54 | headers = dict() 55 | headers['Ocp-Apim-Subscription-Key'] = VISION_API_KEY 56 | headers['Content-Type'] = 'application/json' 57 | 58 | image_url = { 'url': imageurl } ; 59 | image_file = None 60 | result = processRequest( image_url, image_file, headers, params ) 61 | 62 | if result is not None: 63 | #print(result) 64 | result_str = json.dumps(result); #print(result_str) 65 | 66 | # write result into blob 67 | ocrblobname = imageurl[-17:-3] + 'json' 68 | block_blob_service.create_blob_from_text(CONTAINER_NAME_OCR_2, ocrblobname, result_str) 69 | # extract text 70 | text = extractText(result); #print (text) 71 | 72 | # populate dataframe 73 | df.loc[index,'Text'] = text 74 | else: 75 | # populate dataframe 76 | df.loc[index,'Text'] = None 77 | 78 | df.loc[index,'Category'] = row['Category'] 79 | df.loc[index,'ReceiptID'] = imageurl[-17:-3] 80 | 81 | # write dataframe to blob 82 | print("-----------------------") 83 | df_str = df.to_csv(sep='\t', index=False); 84 | 85 | dfblobname = 'dataframe_6_classes_url.tsv' 86 | block_blob_service.create_blob_from_text(CONTAINER_NAME_STRUCTUREDDATA, dfblobname, df_str) 87 | 88 | return 89 | 90 | def extractText(result): 91 | text = "" 92 | for region in result['regions']: 93 | for line in region['lines']: 94 | for word in line['words']: 95 | #print (word.get('text')) 96 | text = text + " " + word.get('text') 97 | return text 98 | 99 | def processRequest( image_url, image_file, headers, params ): 100 | 101 | """ 102 | Ref: https://github.com/Microsoft/Cognitive-Vision-Python/blob/master/Jupyter%20Notebook/Computer%20Vision%20API%20Example.ipynb 103 | Helper function to process the request to Project Oxford 104 | Parameters: 105 | json: Used when processing images from its URL. See API Documentation 106 | data: Used when processing image read from disk. See API Documentation 107 | headers: Used to pass the key information and the data type request 108 | """ 109 | 110 | retries = 0 111 | result = None 112 | 113 | while True: 114 | 115 | response = requests.request( 'post', _url, json = image_url, data = image_file, headers = headers, params = params ) 116 | 117 | if response.status_code == 429: 118 | 119 | print( "Message: %s" % ( response.json()['message'] ) ) 120 | 121 | if retries <= _maxNumRetries: 122 | time.sleep(1) 123 | retries += 1 124 | continue 125 | else: 126 | print( 'Error: failed after retrying!' ) 127 | break 128 | 129 | elif response.status_code == 200 or response.status_code == 201: 130 | 131 | if 'content-length' in response.headers and int(response.headers['content-length']) == 0: 132 | result = None 133 | elif 'content-type' in response.headers and isinstance(response.headers['content-type'], str): 134 | if 'application/json' in response.headers['content-type'].lower(): 135 | result = response.json() if response.content else None 136 | elif 'image' in response.headers['content-type'].lower(): 137 | result = response.content 138 | else: 139 | print(response.json()) 140 | print( "Error code: %d" % ( response.status_code ) ); 141 | print( "Message: %s" % ( response.json()['message'] ) ); 142 | 143 | break 144 | 145 | return result 146 | 147 | if __name__ == '__main__': 148 | main() -------------------------------------------------------------------------------- /ocr.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed Nov 2 10:28:18 2016 4 | @author: chyam 5 | purpose: load images from blob storage, post to Microsoft OCR, save results, populate 'text' to .tsv file. 6 | """ 7 | ### Error: UnicodeEncodeError: 'charmap' codec can't encode character 8 | ### Fixes: at windows console, type chcp 65001, press enter 9 | 10 | from __future__ import print_function 11 | from azure.storage.blob import BlockBlobService 12 | from azure.storage.blob import PublicAccess 13 | import configparser 14 | import time 15 | import requests 16 | import json 17 | import pandas as pd 18 | from io import StringIO 19 | 20 | _url = 'https://api.projectoxford.ai/vision/v1.0/ocr' 21 | _maxNumRetries = 10 22 | 23 | def main(): 24 | 25 | # Get credential 26 | parser = configparser.ConfigParser() 27 | parser.read('config.ini') 28 | STORAGE_ACCOUNT_NAME = parser.get('credential', 'STORAGE_ACCOUNT_NAME_9') 29 | STORAGE_ACCOUNT_KEY = parser.get('credential', 'STORAGE_ACCOUNT_KEY_9') 30 | CONTAINER_NAME = parser.get('credential', 'CONTAINER_NAME_9') 31 | VISION_API_KEY = parser.get('credential', 'VISION_API_KEY_9') # need to use Agitare account 32 | CONTAINER_NAME_OCR = parser.get('credential', 'CONTAINER_NAME_OCR_9') 33 | CONTAINER_NAME_STRUCTUREDDATA = parser.get('credential', 'CONTAINER_NAME_STRUCTUREDDATA_9') 34 | 35 | # access to blob storage 36 | block_blob_service = BlockBlobService(account_name=STORAGE_ACCOUNT_NAME, account_key=STORAGE_ACCOUNT_KEY) 37 | block_blob_service.set_container_acl(CONTAINER_NAME, public_access=PublicAccess.Container) 38 | generator = block_blob_service.list_blobs(CONTAINER_NAME) 39 | 40 | # empty dataframe 41 | df = pd.DataFrame({'Text' : [], 'Category' : [], 'ReceiptID' : []}) 42 | 43 | # get label from file 44 | blob_text = block_blob_service.get_blob_to_text(CONTAINER_NAME, 'receipts_list-utf8.csv'); #print(blob_text.content) 45 | df_label = pd.DataFrame.from_csv(StringIO(blob_text.content), index_col=None, sep=','); #print(df_label.shape); print(df_label) 46 | 47 | # index 48 | index = 0 49 | for blob in generator: 50 | if index <= 2: 51 | print(blob.name) 52 | imageurl = "https://" + STORAGE_ACCOUNT_NAME + ".blob.core.windows.net/" + CONTAINER_NAME + "/" + blob.name; print(imageurl) 53 | 54 | # OCR parameters 55 | params = { 'language': 'en', 'detectOrientation ': 'true'} 56 | 57 | headers = dict() 58 | headers['Ocp-Apim-Subscription-Key'] = VISION_API_KEY 59 | headers['Content-Type'] = 'application/json' 60 | 61 | image_url = { 'url': imageurl } ; 62 | image_file = None 63 | result = processRequest( image_url, image_file, headers, params ) 64 | 65 | if result is not None: 66 | #print(result) 67 | result_str = json.dumps(result); #print(result_str) 68 | 69 | # write result into blob 70 | ocrblobname = blob.name[:-3] + 'json' 71 | block_blob_service.create_blob_from_text(CONTAINER_NAME_OCR, ocrblobname, result_str) 72 | # extract text 73 | text = extractText(result); #print (text) 74 | 75 | # populate dataframe 76 | df.loc[index,'Text'] = text 77 | else: 78 | # populate dataframe 79 | df.loc[index,'Text'] = None 80 | 81 | df.loc[index,'Category'] = df_label.loc[index,'category'] 82 | df.loc[index,'ReceiptID'] = blob.name 83 | 84 | else: 85 | break 86 | index = index + 1 87 | 88 | # write dataframe to blob 89 | print("-----------------------") 90 | df_str = df.to_csv(sep='\t', index=False); 91 | 92 | dfblobname = 'dataframe.tsv' 93 | block_blob_service.create_blob_from_text(CONTAINER_NAME_STRUCTUREDDATA, dfblobname, df_str) 94 | 95 | return 96 | 97 | def extractText(result): 98 | text = "" 99 | for region in result['regions']: 100 | for line in region['lines']: 101 | for word in line['words']: 102 | #print (word.get('text')) 103 | text = text + " " + word.get('text') 104 | return text 105 | 106 | def processRequest( image_url, image_file, headers, params ): 107 | 108 | """ 109 | Ref: https://github.com/Microsoft/Cognitive-Vision-Python/blob/master/Jupyter%20Notebook/Computer%20Vision%20API%20Example.ipynb 110 | Helper function to process the request to Project Oxford 111 | Parameters: 112 | json: Used when processing images from its URL. See API Documentation 113 | data: Used when processing image read from disk. See API Documentation 114 | headers: Used to pass the key information and the data type request 115 | """ 116 | 117 | retries = 0 118 | result = None 119 | 120 | while True: 121 | 122 | response = requests.request( 'post', _url, json = image_url, data = image_file, headers = headers, params = params ) 123 | 124 | if response.status_code == 429: 125 | 126 | print( "Message: %s" % ( response.json()['message'] ) ) 127 | 128 | if retries <= _maxNumRetries: 129 | time.sleep(1) 130 | retries += 1 131 | continue 132 | else: 133 | print( 'Error: failed after retrying!' ) 134 | break 135 | 136 | elif response.status_code == 200 or response.status_code == 201: 137 | 138 | if 'content-length' in response.headers and int(response.headers['content-length']) == 0: 139 | result = None 140 | elif 'content-type' in response.headers and isinstance(response.headers['content-type'], str): 141 | if 'application/json' in response.headers['content-type'].lower(): 142 | result = response.json() if response.content else None 143 | elif 'image' in response.headers['content-type'].lower(): 144 | result = response.content 145 | else: 146 | print(response.json()) 147 | print( "Error code: %d" % ( response.status_code ) ); 148 | print( "Message: %s" % ( response.json()['message'] ) ); 149 | 150 | break 151 | 152 | return result 153 | 154 | if __name__ == '__main__': 155 | main() -------------------------------------------------------------------------------- /prep-data.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Nov 5 10:35:35 2016 4 | 5 | @author: chyam 6 | Purpose: prepare sturctured-data for azure ml. load from blob, clean, i) write to blob ii) pass to a azure ml learner 7 | """ 8 | 9 | from __future__ import print_function 10 | from azure.storage.blob import BlockBlobService 11 | from azure.storage.blob import ContentSettings 12 | import configparser 13 | import pandas as pd 14 | from io import StringIO 15 | 16 | def main(): 17 | 18 | # Get credential 19 | parser = configparser.ConfigParser() 20 | parser.read('config.ini') 21 | STORAGE_ACCOUNT_NAME = parser.get('credential', 'STORAGE_ACCOUNT_NAME') 22 | STORAGE_ACCOUNT_KEY = parser.get('credential', 'STORAGE_ACCOUNT_KEY') 23 | CONTAINER_NAME_STRUCTUREDDATA = parser.get('credential', 'CONTAINER_NAME_STRUCTUREDDATA') 24 | 25 | # access to blob storage 26 | block_blob_service = BlockBlobService(account_name=STORAGE_ACCOUNT_NAME, account_key=STORAGE_ACCOUNT_KEY) 27 | 28 | # load structured data from blob 29 | blob_text = block_blob_service.get_blob_to_text(CONTAINER_NAME_STRUCTUREDDATA, 'dataframe.tsv'); #print(blob_text.content) 30 | # clean df 31 | df = pd.DataFrame.from_csv(StringIO(blob_text.content), index_col=None, sep='\t'); print(df.shape) 32 | df_clean = df.dropna(); print(df_clean.shape) 33 | 34 | # write cleaned dataframe to blob 35 | print("-----------write cleaned dataframe to blob------------") 36 | df_clean_str = df_clean.to_csv(sep='\t', index=False); 37 | 38 | dfblobname = 'dataframe_cleaned.tsv' 39 | settings = ContentSettings(content_type='text/tab-separated-values') 40 | block_blob_service.create_blob_from_text(CONTAINER_NAME_STRUCTUREDDATA, dfblobname, df_clean_str, content_settings=settings) 41 | 42 | return 43 | 44 | if __name__ == '__main__': 45 | main() -------------------------------------------------------------------------------- /prep-image-url.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Tue Nov 8 21:08:16 2016 4 | 5 | @author: chyam 6 | """ 7 | 8 | from __future__ import print_function 9 | from azure.storage.blob import BlockBlobService 10 | from azure.storage.blob import PublicAccess 11 | import configparser 12 | import pandas as pd 13 | from io import StringIO 14 | 15 | def main(): 16 | 17 | # Get credential 18 | parser = configparser.ConfigParser() 19 | parser.read('config.ini') 20 | STORAGE_ACCOUNT_NAME = parser.get('credential', 'STORAGE_ACCOUNT_NAME') 21 | STORAGE_ACCOUNT_KEY = parser.get('credential', 'STORAGE_ACCOUNT_KEY') 22 | CONTAINER_NAME = parser.get('credential', 'CONTAINER_NAME') 23 | CONTAINER_NAME_METADATA = parser.get('credential', 'CONTAINER_NAME_METADATA') 24 | 25 | # access to blob storage 26 | block_blob_service = BlockBlobService(account_name=STORAGE_ACCOUNT_NAME, account_key=STORAGE_ACCOUNT_KEY) 27 | block_blob_service.set_container_acl(CONTAINER_NAME, public_access=PublicAccess.Container) 28 | generator = block_blob_service.list_blobs(CONTAINER_NAME) 29 | 30 | # empty dataframe 31 | df = pd.DataFrame({'Url' : [], 'Category' : []}) 32 | 33 | # get label from file 34 | blob_text = block_blob_service.get_blob_to_text(CONTAINER_NAME_METADATA, 'receipt_list_labelled.csv'); #print(blob_text.content) 35 | df_label = pd.DataFrame.from_csv(StringIO(blob_text.content), index_col=None, sep=','); #print(df_label.shape); print(df_label) 36 | 37 | # index 38 | index = 0 39 | for blob in generator: 40 | print(blob.name) 41 | # populate dataframe 42 | df.loc[index,'Category'] = df_label.loc[index,'category'] 43 | df.loc[index,'Url'] = imageurl = "https://" + STORAGE_ACCOUNT_NAME + ".blob.core.windows.net/" + CONTAINER_NAME + "/" + blob.name; print(imageurl) 44 | index = index + 1 45 | 46 | # write dataframe to blob 47 | print("-----------------------") 48 | df_str = df.to_csv(sep='\t', index=False); 49 | 50 | dfblobname = 'image-url.tsv' 51 | block_blob_service.create_blob_from_text(CONTAINER_NAME_METADATA, dfblobname, df_str) 52 | 53 | return 54 | 55 | if __name__ == '__main__': 56 | main() -------------------------------------------------------------------------------- /redistribute-data.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Tue Nov 8 04:41:15 2016 4 | 5 | @author: chyam 6 | purpose: data re-labelling to reduce grouping. 7 | """ 8 | 9 | from __future__ import print_function 10 | from azure.storage.blob import BlockBlobService 11 | from azure.storage.blob import ContentSettings 12 | import configparser 13 | import pandas as pd 14 | from io import StringIO 15 | 16 | def main(): 17 | 18 | # Get credential 19 | parser = configparser.ConfigParser() 20 | parser.read('config.ini') 21 | STORAGE_ACCOUNT_NAME = parser.get('credential', 'STORAGE_ACCOUNT_NAME') 22 | STORAGE_ACCOUNT_KEY = parser.get('credential', 'STORAGE_ACCOUNT_KEY') 23 | CONTAINER_NAME_METADATA = parser.get('credential', 'CONTAINER_NAME_METADATA') 24 | 25 | # access to blob storage 26 | block_blob_service = BlockBlobService(account_name=STORAGE_ACCOUNT_NAME, account_key=STORAGE_ACCOUNT_KEY) 27 | 28 | # load structured data from blob 29 | blob_text = block_blob_service.get_blob_to_text(CONTAINER_NAME_METADATA, 'image-url.tsv'); #print(blob_text.content) 30 | df = pd.DataFrame.from_csv(StringIO(blob_text.content), index_col=None, sep='\t'); print(df.shape) 31 | 32 | # Frequency 33 | df_crosstab = pd.crosstab(index=df["Category"], columns="count") 34 | print(df_crosstab) 35 | 36 | print(df.shape) 37 | df_sub = pd.concat([df.loc[df['Category'] == 'daily snack'], 38 | df.loc[df['Category'] == 'groceries'], 39 | df.loc[df['Category'] == 'dining out'], 40 | df.loc[df['Category'] == 'clothes and accessories'], 41 | df.loc[df['Category'] == 'fuel'], 42 | df.loc[df['Category'] == 'entertinement']]) 43 | print(df_sub.shape) 44 | print(df_sub.Category.unique()) 45 | 46 | # write cleaned dataframe to blob 47 | print("-----------write cleaned dataframe to blob------------") 48 | df_sub_str = df_sub.to_csv(sep='\t', index=False); 49 | 50 | #dfblobname = 'dataframe_6_classes.tsv' 51 | dfblobname = 'image-url-6-classes.tsv' 52 | settings = ContentSettings(content_type='text/tab-separated-values') 53 | block_blob_service.create_blob_from_text(CONTAINER_NAME_METADATA, dfblobname, df_sub_str, content_settings=settings) 54 | 55 | return 56 | 57 | if __name__ == '__main__': 58 | main() --------------------------------------------------------------------------------