├── .gitignore ├── Convert ├── convert.py ├── download.sh └── labels.txt ├── LICENSE ├── Podfile ├── Podfile.lock ├── README.md ├── Screenshot.png ├── SentimentVision.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── SentimentVision.xcworkspace └── contents.xcworkspacedata └── SentimentVision ├── AppDelegate.swift ├── ClassificationService.swift ├── Resources ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Group 4.png │ │ ├── Icon-40.png │ │ ├── Icon-40@2x.png │ │ ├── Icon-40@3x.png │ │ ├── Icon-60@2x.png │ │ ├── Icon-60@3x.png │ │ ├── Icon-72.png │ │ ├── Icon-72@2x.png │ │ ├── Icon-76.png │ │ ├── Icon-76@2x.png │ │ ├── Icon-83.5@2x.png │ │ ├── Icon-Small-50.png │ │ ├── Icon-Small-50@2x.png │ │ ├── Icon-Small.png │ │ ├── Icon-Small@2x.png │ │ ├── Icon-Small@3x.png │ │ ├── Icon.png │ │ ├── Icon@2x.png │ │ ├── NotificationIcon@2x.png │ │ ├── NotificationIcon@3x.png │ │ ├── NotificationIcon~ipad.png │ │ └── NotificationIcon~ipad@2x.png ├── Info.plist └── LaunchScreen.storyboard └── ViewController.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | Icon 6 | ._* 7 | .Spotlight-V100 8 | .Trashes 9 | 10 | # Xcode 11 | # 12 | build/ 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata 22 | *.xccheckout 23 | *.moved-aside 24 | DerivedData 25 | *.hmap 26 | *.ipa 27 | *.xcuserstate 28 | .idea/ 29 | *.xcworkspace/xcshareddata/*.xcscmblueprint 30 | 31 | # CocoaPods 32 | Pods 33 | 34 | # Carthage 35 | Carthage 36 | 37 | # SPM 38 | .build/ 39 | 40 | ## CoreML models 41 | *.mlmodel 42 | -------------------------------------------------------------------------------- /Convert/convert.py: -------------------------------------------------------------------------------- 1 | import coremltools 2 | 3 | coreml_model = coremltools.converters.caffe.convert(('twitter_finetuned_test4_iter_180.caffemodel', 'sentiment_deploy.prototxt'), image_input_names = 'data', class_labels='labels.txt') 4 | coreml_model.author = 'Image Processing Group - BarcelonaTECH - UPC' 5 | coreml_model.license = 'MIT' 6 | coreml_model.short_description = 'Fine-tuning CNNs for Visual Sentiment Prediction' 7 | coreml_model.input_description['data'] = 'An image.' 8 | coreml_model.output_description['prob'] = 'The probabilities for each sentiment, for the given input.' 9 | coreml_model.output_description['classLabel'] = 'The most likely sentiment, for the given input.' 10 | coreml_model.save('VisualSentimentCNN.mlmodel') 11 | -------------------------------------------------------------------------------- /Convert/download.sh: -------------------------------------------------------------------------------- 1 | wget https://imatge.upc.edu/web/sites/default/files/projects/affective/public_html/2017-imavis/twitter_finetuned_test4_iter_180.caffemodel 2 | wget https://github.com/imatge-upc/sentiment-2017-imavis/raw/master/sentiment_deploy.prototxt 3 | -------------------------------------------------------------------------------- /Convert/labels.txt: -------------------------------------------------------------------------------- 1 | Negative 2 | Positive -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Vadym Markov 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 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | platform :ios, '11.0' 3 | pod 'VisionLab', git: 'https://github.com/cocoa-ai/VisionLab' 4 | target 'SentimentVision' 5 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - VisionLab (0.2.0) 3 | 4 | DEPENDENCIES: 5 | - VisionLab (from `https://github.com/cocoa-ai/VisionLab`) 6 | 7 | EXTERNAL SOURCES: 8 | VisionLab: 9 | :git: https://github.com/cocoa-ai/VisionLab 10 | 11 | CHECKOUT OPTIONS: 12 | VisionLab: 13 | :commit: aea33bfae9755aa9f175f2783f97593775f664e5 14 | :git: https://github.com/cocoa-ai/VisionLab 15 | 16 | SPEC CHECKSUMS: 17 | VisionLab: 6fc2dcc1f731dd21891c7bd9878a93c0526bfc91 18 | 19 | PODFILE CHECKSUM: b3731e7bdb17f1171592448b19fcf17042c1166d 20 | 21 | COCOAPODS: 1.3.1 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sentiment Vision Demo 2 | 3 | A Demo application using `Vision` and `CoreML` frameworks to detect the most 4 | likely sentiment of the given image. 5 | 6 |
7 | SentimentVisionDemo 8 |
9 | 10 | ## Model 11 | 12 | This demo is based on the "Fine-tuning CNNs for Visual Sentiment Prediction" 13 | neural network classifier, which was converted from original [Caffe model](https://github.com/imatge-upc/sentiment-2017-imavis) 14 | to [CoreML model](https://drive.google.com/file/d/1nt_Sp85Orplcbyyc7AAyCUjEfss8Pw87/view?usp=sharing) 15 | using [coremltools](https://pypi.python.org/pypi/coremltools) python package. 16 | 17 | ## Requirements 18 | 19 | - Xcode 9 20 | - iOS 11 21 | 22 | ## Installation 23 | 24 | ```sh 25 | git clone https://github.com/cocoa-ml/SentimentVisionDemo.git 26 | cd SentimentVisionDemo 27 | pod install 28 | open SentimentVision.xcworkspace/ 29 | ``` 30 | 31 | Download the [CoreMl model](https://drive.google.com/open?id=0B1ghKa_MYL6mZ0dITW5uZlgyNTg) 32 | and drag the file into your project. 33 | 34 | Build the project and run it on a simulator or a device with iOS 11. 35 | 36 | ## Conversion 37 | 38 | ```sh 39 | cd Convert 40 | ./download.sh 41 | python convert.py 42 | ``` 43 | 44 | ## Author 45 | 46 | Vadym Markov, markov.vadym@gmail.com 47 | 48 | ## Credits 49 | 50 | [From Pixels to Sentiment: Fine-tuning CNNs for Visual Sentiment Prediction](https://github.com/imatge-upc/sentiment-2017-imavis) 51 | 52 | ## References 53 | - [Caffe](http://caffe.berkeleyvision.org) 54 | - [Apple Machine Learning](https://developer.apple.com/machine-learning/) 55 | - [Vision Framework](https://developer.apple.com/documentation/vision) 56 | - [CoreML Framework](https://developer.apple.com/documentation/coreml) 57 | - [coremltools](https://pypi.python.org/pypi/coremltools) 58 | -------------------------------------------------------------------------------- /Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/Screenshot.png -------------------------------------------------------------------------------- /SentimentVision.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 87CFA7AB514506A27EB98F69 /* Pods_SentimentVision.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B5BD68118D9E30EF9D3CAB6 /* Pods_SentimentVision.framework */; }; 11 | D55FC74E1F1A907000342C00 /* VisualSentimentCNN.mlmodel in Sources */ = {isa = PBXBuildFile; fileRef = D55FC74D1F1A906D00342C00 /* VisualSentimentCNN.mlmodel */; }; 12 | D55FC7501F1A922700342C00 /* ClassificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55FC74F1F1A922700342C00 /* ClassificationService.swift */; }; 13 | D5D850D71F1A87A100585DB3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D850D61F1A87A100585DB3 /* AppDelegate.swift */; }; 14 | D5D850D91F1A87A100585DB3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D850D81F1A87A100585DB3 /* ViewController.swift */; }; 15 | D5D850EA1F1A8BBF00585DB3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D5D850E91F1A8BB900585DB3 /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 0B5BD68118D9E30EF9D3CAB6 /* Pods_SentimentVision.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SentimentVision.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | 22404BC1A611952680540FCF /* Pods-SentimentVision.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SentimentVision.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SentimentVision/Pods-SentimentVision.debug.xcconfig"; sourceTree = ""; }; 21 | 5D62E58E4DC29C5F30C8B179 /* Pods-SentimentVision.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SentimentVision.release.xcconfig"; path = "Pods/Target Support Files/Pods-SentimentVision/Pods-SentimentVision.release.xcconfig"; sourceTree = ""; }; 22 | D55FC74D1F1A906D00342C00 /* VisualSentimentCNN.mlmodel */ = {isa = PBXFileReference; lastKnownFileType = file.mlmodel; path = VisualSentimentCNN.mlmodel; sourceTree = ""; }; 23 | D55FC74F1F1A922700342C00 /* ClassificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClassificationService.swift; sourceTree = ""; }; 24 | D5D850D31F1A87A100585DB3 /* SentimentVision.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SentimentVision.app; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | D5D850D61F1A87A100585DB3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 26 | D5D850D81F1A87A100585DB3 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 27 | D5D850E91F1A8BB900585DB3 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 28 | D5D850EB1F1A8BE900585DB3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 29 | D5D850EC1F1A8BE900585DB3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 30 | /* End PBXFileReference section */ 31 | 32 | /* Begin PBXFrameworksBuildPhase section */ 33 | D5D850D01F1A87A100585DB3 /* Frameworks */ = { 34 | isa = PBXFrameworksBuildPhase; 35 | buildActionMask = 2147483647; 36 | files = ( 37 | 87CFA7AB514506A27EB98F69 /* Pods_SentimentVision.framework in Frameworks */, 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXFrameworksBuildPhase section */ 42 | 43 | /* Begin PBXGroup section */ 44 | 18AA236A55E026E74FAD1273 /* Frameworks */ = { 45 | isa = PBXGroup; 46 | children = ( 47 | 0B5BD68118D9E30EF9D3CAB6 /* Pods_SentimentVision.framework */, 48 | ); 49 | name = Frameworks; 50 | sourceTree = ""; 51 | }; 52 | 483D678BB1393041E7C411CD /* Pods */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 22404BC1A611952680540FCF /* Pods-SentimentVision.debug.xcconfig */, 56 | 5D62E58E4DC29C5F30C8B179 /* Pods-SentimentVision.release.xcconfig */, 57 | ); 58 | name = Pods; 59 | sourceTree = ""; 60 | }; 61 | D5D850CA1F1A87A100585DB3 = { 62 | isa = PBXGroup; 63 | children = ( 64 | D5D850D51F1A87A100585DB3 /* SentimentVision */, 65 | D5D850D41F1A87A100585DB3 /* Products */, 66 | 483D678BB1393041E7C411CD /* Pods */, 67 | 18AA236A55E026E74FAD1273 /* Frameworks */, 68 | ); 69 | sourceTree = ""; 70 | }; 71 | D5D850D41F1A87A100585DB3 /* Products */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | D5D850D31F1A87A100585DB3 /* SentimentVision.app */, 75 | ); 76 | name = Products; 77 | sourceTree = ""; 78 | }; 79 | D5D850D51F1A87A100585DB3 /* SentimentVision */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | D5D850E81F1A8B7000585DB3 /* Resources */, 83 | D5D850D61F1A87A100585DB3 /* AppDelegate.swift */, 84 | D5D850D81F1A87A100585DB3 /* ViewController.swift */, 85 | D55FC74F1F1A922700342C00 /* ClassificationService.swift */, 86 | ); 87 | path = SentimentVision; 88 | sourceTree = ""; 89 | }; 90 | D5D850E81F1A8B7000585DB3 /* Resources */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | D55FC74D1F1A906D00342C00 /* VisualSentimentCNN.mlmodel */, 94 | D5D850EB1F1A8BE900585DB3 /* Assets.xcassets */, 95 | D5D850EC1F1A8BE900585DB3 /* Info.plist */, 96 | D5D850E91F1A8BB900585DB3 /* LaunchScreen.storyboard */, 97 | ); 98 | path = Resources; 99 | sourceTree = ""; 100 | }; 101 | /* End PBXGroup section */ 102 | 103 | /* Begin PBXNativeTarget section */ 104 | D5D850D21F1A87A100585DB3 /* SentimentVision */ = { 105 | isa = PBXNativeTarget; 106 | buildConfigurationList = D5D850E51F1A87A100585DB3 /* Build configuration list for PBXNativeTarget "SentimentVision" */; 107 | buildPhases = ( 108 | FAE82AD73C118396B28822BB /* [CP] Check Pods Manifest.lock */, 109 | D5D850CF1F1A87A100585DB3 /* Sources */, 110 | D5D850D01F1A87A100585DB3 /* Frameworks */, 111 | D5D850D11F1A87A100585DB3 /* Resources */, 112 | 7C1ECF9603182F14CBA53FFA /* [CP] Embed Pods Frameworks */, 113 | FB06C8530D566C58398EF7C1 /* [CP] Copy Pods Resources */, 114 | ); 115 | buildRules = ( 116 | ); 117 | dependencies = ( 118 | ); 119 | name = SentimentVision; 120 | productName = SentimentVision; 121 | productReference = D5D850D31F1A87A100585DB3 /* SentimentVision.app */; 122 | productType = "com.apple.product-type.application"; 123 | }; 124 | /* End PBXNativeTarget section */ 125 | 126 | /* Begin PBXProject section */ 127 | D5D850CB1F1A87A100585DB3 /* Project object */ = { 128 | isa = PBXProject; 129 | attributes = { 130 | LastSwiftUpdateCheck = 0900; 131 | LastUpgradeCheck = 0900; 132 | ORGANIZATIONNAME = "Vadym Markov"; 133 | TargetAttributes = { 134 | D5D850D21F1A87A100585DB3 = { 135 | CreatedOnToolsVersion = 9.0; 136 | ProvisioningStyle = Manual; 137 | }; 138 | }; 139 | }; 140 | buildConfigurationList = D5D850CE1F1A87A100585DB3 /* Build configuration list for PBXProject "SentimentVision" */; 141 | compatibilityVersion = "Xcode 8.0"; 142 | developmentRegion = en; 143 | hasScannedForEncodings = 0; 144 | knownRegions = ( 145 | en, 146 | Base, 147 | ); 148 | mainGroup = D5D850CA1F1A87A100585DB3; 149 | productRefGroup = D5D850D41F1A87A100585DB3 /* Products */; 150 | projectDirPath = ""; 151 | projectRoot = ""; 152 | targets = ( 153 | D5D850D21F1A87A100585DB3 /* SentimentVision */, 154 | ); 155 | }; 156 | /* End PBXProject section */ 157 | 158 | /* Begin PBXResourcesBuildPhase section */ 159 | D5D850D11F1A87A100585DB3 /* Resources */ = { 160 | isa = PBXResourcesBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | D5D850EA1F1A8BBF00585DB3 /* LaunchScreen.storyboard in Resources */, 164 | ); 165 | runOnlyForDeploymentPostprocessing = 0; 166 | }; 167 | /* End PBXResourcesBuildPhase section */ 168 | 169 | /* Begin PBXShellScriptBuildPhase section */ 170 | 7C1ECF9603182F14CBA53FFA /* [CP] Embed Pods Frameworks */ = { 171 | isa = PBXShellScriptBuildPhase; 172 | buildActionMask = 2147483647; 173 | files = ( 174 | ); 175 | inputPaths = ( 176 | "${SRCROOT}/Pods/Target Support Files/Pods-SentimentVision/Pods-SentimentVision-frameworks.sh", 177 | "${BUILT_PRODUCTS_DIR}/VisionLab/VisionLab.framework", 178 | ); 179 | name = "[CP] Embed Pods Frameworks"; 180 | outputPaths = ( 181 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/VisionLab.framework", 182 | ); 183 | runOnlyForDeploymentPostprocessing = 0; 184 | shellPath = /bin/sh; 185 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SentimentVision/Pods-SentimentVision-frameworks.sh\"\n"; 186 | showEnvVarsInLog = 0; 187 | }; 188 | FAE82AD73C118396B28822BB /* [CP] Check Pods Manifest.lock */ = { 189 | isa = PBXShellScriptBuildPhase; 190 | buildActionMask = 2147483647; 191 | files = ( 192 | ); 193 | inputPaths = ( 194 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 195 | "${PODS_ROOT}/Manifest.lock", 196 | ); 197 | name = "[CP] Check Pods Manifest.lock"; 198 | outputPaths = ( 199 | "$(DERIVED_FILE_DIR)/Pods-SentimentVision-checkManifestLockResult.txt", 200 | ); 201 | runOnlyForDeploymentPostprocessing = 0; 202 | shellPath = /bin/sh; 203 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 204 | showEnvVarsInLog = 0; 205 | }; 206 | FB06C8530D566C58398EF7C1 /* [CP] Copy Pods Resources */ = { 207 | isa = PBXShellScriptBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | ); 211 | inputPaths = ( 212 | ); 213 | name = "[CP] Copy Pods Resources"; 214 | outputPaths = ( 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | shellPath = /bin/sh; 218 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SentimentVision/Pods-SentimentVision-resources.sh\"\n"; 219 | showEnvVarsInLog = 0; 220 | }; 221 | /* End PBXShellScriptBuildPhase section */ 222 | 223 | /* Begin PBXSourcesBuildPhase section */ 224 | D5D850CF1F1A87A100585DB3 /* Sources */ = { 225 | isa = PBXSourcesBuildPhase; 226 | buildActionMask = 2147483647; 227 | files = ( 228 | D55FC74E1F1A907000342C00 /* VisualSentimentCNN.mlmodel in Sources */, 229 | D5D850D91F1A87A100585DB3 /* ViewController.swift in Sources */, 230 | D5D850D71F1A87A100585DB3 /* AppDelegate.swift in Sources */, 231 | D55FC7501F1A922700342C00 /* ClassificationService.swift in Sources */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | /* End PBXSourcesBuildPhase section */ 236 | 237 | /* Begin XCBuildConfiguration section */ 238 | D5D850E31F1A87A100585DB3 /* Debug */ = { 239 | isa = XCBuildConfiguration; 240 | buildSettings = { 241 | ALWAYS_SEARCH_USER_PATHS = NO; 242 | CLANG_ANALYZER_NONNULL = YES; 243 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 244 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 245 | CLANG_CXX_LIBRARY = "libc++"; 246 | CLANG_ENABLE_MODULES = YES; 247 | CLANG_ENABLE_OBJC_ARC = YES; 248 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 249 | CLANG_WARN_BOOL_CONVERSION = YES; 250 | CLANG_WARN_COMMA = YES; 251 | CLANG_WARN_CONSTANT_CONVERSION = YES; 252 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 253 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 254 | CLANG_WARN_EMPTY_BODY = YES; 255 | CLANG_WARN_ENUM_CONVERSION = YES; 256 | CLANG_WARN_INFINITE_RECURSION = YES; 257 | CLANG_WARN_INT_CONVERSION = YES; 258 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 259 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 260 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 261 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 262 | CLANG_WARN_STRICT_PROTOTYPES = YES; 263 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 264 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 265 | CLANG_WARN_UNREACHABLE_CODE = YES; 266 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 267 | CODE_SIGN_IDENTITY = "iPhone Developer"; 268 | COPY_PHASE_STRIP = NO; 269 | DEBUG_INFORMATION_FORMAT = dwarf; 270 | ENABLE_STRICT_OBJC_MSGSEND = YES; 271 | ENABLE_TESTABILITY = YES; 272 | GCC_C_LANGUAGE_STANDARD = gnu11; 273 | GCC_DYNAMIC_NO_PIC = NO; 274 | GCC_NO_COMMON_BLOCKS = YES; 275 | GCC_OPTIMIZATION_LEVEL = 0; 276 | GCC_PREPROCESSOR_DEFINITIONS = ( 277 | "DEBUG=1", 278 | "$(inherited)", 279 | ); 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 282 | GCC_WARN_UNDECLARED_SELECTOR = YES; 283 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 284 | GCC_WARN_UNUSED_FUNCTION = YES; 285 | GCC_WARN_UNUSED_VARIABLE = YES; 286 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 287 | MTL_ENABLE_DEBUG_INFO = YES; 288 | ONLY_ACTIVE_ARCH = YES; 289 | SDKROOT = iphoneos; 290 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 291 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 292 | }; 293 | name = Debug; 294 | }; 295 | D5D850E41F1A87A100585DB3 /* Release */ = { 296 | isa = XCBuildConfiguration; 297 | buildSettings = { 298 | ALWAYS_SEARCH_USER_PATHS = NO; 299 | CLANG_ANALYZER_NONNULL = YES; 300 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 301 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 302 | CLANG_CXX_LIBRARY = "libc++"; 303 | CLANG_ENABLE_MODULES = YES; 304 | CLANG_ENABLE_OBJC_ARC = YES; 305 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 306 | CLANG_WARN_BOOL_CONVERSION = YES; 307 | CLANG_WARN_COMMA = YES; 308 | CLANG_WARN_CONSTANT_CONVERSION = YES; 309 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 310 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 311 | CLANG_WARN_EMPTY_BODY = YES; 312 | CLANG_WARN_ENUM_CONVERSION = YES; 313 | CLANG_WARN_INFINITE_RECURSION = YES; 314 | CLANG_WARN_INT_CONVERSION = YES; 315 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 316 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 317 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 318 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 319 | CLANG_WARN_STRICT_PROTOTYPES = YES; 320 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 321 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 322 | CLANG_WARN_UNREACHABLE_CODE = YES; 323 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 324 | CODE_SIGN_IDENTITY = "iPhone Developer"; 325 | COPY_PHASE_STRIP = NO; 326 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 327 | ENABLE_NS_ASSERTIONS = NO; 328 | ENABLE_STRICT_OBJC_MSGSEND = YES; 329 | GCC_C_LANGUAGE_STANDARD = gnu11; 330 | GCC_NO_COMMON_BLOCKS = YES; 331 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 332 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 333 | GCC_WARN_UNDECLARED_SELECTOR = YES; 334 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 335 | GCC_WARN_UNUSED_FUNCTION = YES; 336 | GCC_WARN_UNUSED_VARIABLE = YES; 337 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 338 | MTL_ENABLE_DEBUG_INFO = NO; 339 | SDKROOT = iphoneos; 340 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 341 | VALIDATE_PRODUCT = YES; 342 | }; 343 | name = Release; 344 | }; 345 | D5D850E61F1A87A100585DB3 /* Debug */ = { 346 | isa = XCBuildConfiguration; 347 | baseConfigurationReference = 22404BC1A611952680540FCF /* Pods-SentimentVision.debug.xcconfig */; 348 | buildSettings = { 349 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 350 | CODE_SIGN_STYLE = Manual; 351 | COREML_CODEGEN_LANGUAGE = Swift; 352 | DEVELOPMENT_TEAM = ""; 353 | INFOPLIST_FILE = SentimentVision/Resources/Info.plist; 354 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 355 | PRODUCT_BUNDLE_IDENTIFIER = "codes.cocoa-ai.SentimentVision"; 356 | PRODUCT_NAME = "$(TARGET_NAME)"; 357 | PROVISIONING_PROFILE_SPECIFIER = ""; 358 | SWIFT_VERSION = 4.0; 359 | TARGETED_DEVICE_FAMILY = 1; 360 | }; 361 | name = Debug; 362 | }; 363 | D5D850E71F1A87A100585DB3 /* Release */ = { 364 | isa = XCBuildConfiguration; 365 | baseConfigurationReference = 5D62E58E4DC29C5F30C8B179 /* Pods-SentimentVision.release.xcconfig */; 366 | buildSettings = { 367 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 368 | CODE_SIGN_STYLE = Manual; 369 | COREML_CODEGEN_LANGUAGE = Swift; 370 | DEVELOPMENT_TEAM = ""; 371 | INFOPLIST_FILE = SentimentVision/Resources/Info.plist; 372 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 373 | PRODUCT_BUNDLE_IDENTIFIER = "codes.cocoa-ai.SentimentVision"; 374 | PRODUCT_NAME = "$(TARGET_NAME)"; 375 | PROVISIONING_PROFILE_SPECIFIER = ""; 376 | SWIFT_VERSION = 4.0; 377 | TARGETED_DEVICE_FAMILY = 1; 378 | }; 379 | name = Release; 380 | }; 381 | /* End XCBuildConfiguration section */ 382 | 383 | /* Begin XCConfigurationList section */ 384 | D5D850CE1F1A87A100585DB3 /* Build configuration list for PBXProject "SentimentVision" */ = { 385 | isa = XCConfigurationList; 386 | buildConfigurations = ( 387 | D5D850E31F1A87A100585DB3 /* Debug */, 388 | D5D850E41F1A87A100585DB3 /* Release */, 389 | ); 390 | defaultConfigurationIsVisible = 0; 391 | defaultConfigurationName = Release; 392 | }; 393 | D5D850E51F1A87A100585DB3 /* Build configuration list for PBXNativeTarget "SentimentVision" */ = { 394 | isa = XCConfigurationList; 395 | buildConfigurations = ( 396 | D5D850E61F1A87A100585DB3 /* Debug */, 397 | D5D850E71F1A87A100585DB3 /* Release */, 398 | ); 399 | defaultConfigurationIsVisible = 0; 400 | defaultConfigurationName = Release; 401 | }; 402 | /* End XCConfigurationList section */ 403 | }; 404 | rootObject = D5D850CB1F1A87A100585DB3 /* Project object */; 405 | } 406 | -------------------------------------------------------------------------------- /SentimentVision.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SentimentVision.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SentimentVision/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | @UIApplicationMain 4 | final class AppDelegate: UIResponder, UIApplicationDelegate { 5 | var window: UIWindow? 6 | private lazy var controller: UIViewController = ViewController() 7 | 8 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 9 | window = UIWindow() 10 | window?.rootViewController = controller 11 | window?.makeKeyAndVisible() 12 | 13 | return true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SentimentVision/ClassificationService.swift: -------------------------------------------------------------------------------- 1 | import CoreML 2 | import Vision 3 | import VisionLab 4 | 5 | protocol ClassificationServiceDelegate: class { 6 | func classificationService(_ service: ClassificationService, didDetectSentiment sentiment: String) 7 | } 8 | 9 | /// Service used to perform gender, age and emotion classification 10 | final class ClassificationService: ClassificationServiceProtocol { 11 | /// The service's delegate 12 | weak var delegate: ClassificationServiceDelegate? 13 | /// Array of vision requests 14 | private var requests = [VNRequest]() 15 | 16 | /// Create CoreML model and classification requests 17 | func setup() { 18 | do { 19 | // Sentiment request 20 | requests.append(VNCoreMLRequest( 21 | model: try VNCoreMLModel(for: VisualSentimentCNN().model), 22 | completionHandler: handleClassification 23 | )) 24 | } catch { 25 | assertionFailure("Can't load Vision ML model: \(error)") 26 | } 27 | } 28 | 29 | /// Run individual requests one by one. 30 | func classify(image: CIImage) { 31 | do { 32 | for request in self.requests { 33 | let handler = VNImageRequestHandler(ciImage: image) 34 | try handler.perform([request]) 35 | } 36 | } catch { 37 | print(error) 38 | } 39 | } 40 | 41 | // MARK: - Handling 42 | 43 | @objc private func handleClassification(request: VNRequest, error: Error?) { 44 | let result = extractClassificationResult(from: request, count: 1) 45 | delegate?.classificationService(self, didDetectSentiment: result) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "NotificationIcon@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "NotificationIcon@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-Small.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-Small@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-Small@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "57x57", 47 | "idiom" : "iphone", 48 | "filename" : "Icon.png", 49 | "scale" : "1x" 50 | }, 51 | { 52 | "size" : "57x57", 53 | "idiom" : "iphone", 54 | "filename" : "Icon@2x.png", 55 | "scale" : "2x" 56 | }, 57 | { 58 | "size" : "60x60", 59 | "idiom" : "iphone", 60 | "filename" : "Icon-60@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "60x60", 65 | "idiom" : "iphone", 66 | "filename" : "Icon-60@3x.png", 67 | "scale" : "3x" 68 | }, 69 | { 70 | "size" : "20x20", 71 | "idiom" : "ipad", 72 | "filename" : "NotificationIcon~ipad.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "20x20", 77 | "idiom" : "ipad", 78 | "filename" : "NotificationIcon~ipad@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "29x29", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-Small.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "29x29", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-Small@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "40x40", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-40.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "40x40", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-40@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "50x50", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-Small-50.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "50x50", 113 | "idiom" : "ipad", 114 | "filename" : "Icon-Small-50@2x.png", 115 | "scale" : "2x" 116 | }, 117 | { 118 | "size" : "72x72", 119 | "idiom" : "ipad", 120 | "filename" : "Icon-72.png", 121 | "scale" : "1x" 122 | }, 123 | { 124 | "size" : "72x72", 125 | "idiom" : "ipad", 126 | "filename" : "Icon-72@2x.png", 127 | "scale" : "2x" 128 | }, 129 | { 130 | "size" : "76x76", 131 | "idiom" : "ipad", 132 | "filename" : "Icon-76.png", 133 | "scale" : "1x" 134 | }, 135 | { 136 | "size" : "76x76", 137 | "idiom" : "ipad", 138 | "filename" : "Icon-76@2x.png", 139 | "scale" : "2x" 140 | }, 141 | { 142 | "size" : "83.5x83.5", 143 | "idiom" : "ipad", 144 | "filename" : "Icon-83.5@2x.png", 145 | "scale" : "2x" 146 | }, 147 | { 148 | "size" : "1024x1024", 149 | "idiom" : "ios-marketing", 150 | "filename" : "Group 4.png", 151 | "scale" : "1x" 152 | } 153 | ], 154 | "info" : { 155 | "version" : 1, 156 | "author" : "xcode" 157 | } 158 | } -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Group 4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Group 4.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-72.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-72@2x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-83.5@2x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small-50.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/Icon@2x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/NotificationIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/NotificationIcon@2x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/NotificationIcon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/NotificationIcon@3x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/NotificationIcon~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/NotificationIcon~ipad.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/NotificationIcon~ipad@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocoa-ai/SentimentVisionDemo/64f14c557dece3fa99349294a04a2e70a64816fb/SentimentVision/Resources/Assets.xcassets/AppIcon.appiconset/NotificationIcon~ipad@2x.png -------------------------------------------------------------------------------- /SentimentVision/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | NSPhotoLibraryUsageDescription 24 | To demonstrate image recognition. 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UIStatusBarStyle 32 | UIStatusBarStyleLightContent 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /SentimentVision/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 | 30 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /SentimentVision/ViewController.swift: -------------------------------------------------------------------------------- 1 | import VisionLab 2 | 3 | final class ViewController: ImageClassificationController { 4 | override func viewDidLoad() { 5 | super.viewDidLoad() 6 | mainView.button.setTitle("Choose a picture", for: .normal) 7 | classificationService.delegate = self 8 | } 9 | } 10 | 11 | // MARK: - ClassificationServiceDelegate 12 | 13 | extension ViewController: ClassificationServiceDelegate { 14 | func classificationService(_ service: ClassificationService, didDetectSentiment sentiment: String) { 15 | DispatchQueue.main.async { [weak mainView] in 16 | mainView?.label.text = sentiment.capitalized 17 | } 18 | } 19 | } 20 | --------------------------------------------------------------------------------