├── .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 |

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 |
--------------------------------------------------------------------------------