├── CoreMLDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── wutian.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── wutian.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── CoreMLDemo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── DemoPanel.h ├── DemoPanel.m ├── FaceLandmarkView.h ├── FaceLandmarkView.m ├── Info.plist ├── ViewController.h ├── ViewController.mm └── main.m ├── README.md └── intro.gif /CoreMLDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C6337B021F00B1130049AC8C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C6337B011F00B1130049AC8C /* AppDelegate.m */; }; 11 | C6337B051F00B1130049AC8C /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = C6337B041F00B1130049AC8C /* ViewController.mm */; }; 12 | C6337B081F00B1130049AC8C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C6337B061F00B1130049AC8C /* Main.storyboard */; }; 13 | C6337B0A1F00B1130049AC8C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C6337B091F00B1130049AC8C /* Assets.xcassets */; }; 14 | C6337B0D1F00B1130049AC8C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C6337B0B1F00B1130049AC8C /* LaunchScreen.storyboard */; }; 15 | C6337B101F00B1130049AC8C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C6337B0F1F00B1130049AC8C /* main.m */; }; 16 | C6337B191F00B3D70049AC8C /* Vision.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6337B181F00B3C50049AC8C /* Vision.framework */; }; 17 | C6337B1A1F00B3D90049AC8C /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6337B171F00B3BE0049AC8C /* AVFoundation.framework */; }; 18 | C6337B1D1F00B4750049AC8C /* DemoPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = C6337B1C1F00B4750049AC8C /* DemoPanel.m */; }; 19 | C6337B1F1F00BB320049AC8C /* Resnet50.mlmodel in Sources */ = {isa = PBXBuildFile; fileRef = C6337B1E1F00BB320049AC8C /* Resnet50.mlmodel */; }; 20 | C6337B211F00BBD00049AC8C /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6337B201F00BBCC0049AC8C /* CoreMedia.framework */; }; 21 | C6337B231F00BBD60049AC8C /* CoreML.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6337B221F00BBD40049AC8C /* CoreML.framework */; }; 22 | C6C23D821F00D4F6002DB91A /* FaceLandmarkView.m in Sources */ = {isa = PBXBuildFile; fileRef = C6C23D811F00D4F6002DB91A /* FaceLandmarkView.m */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | C6337AFD1F00B1130049AC8C /* CoreMLDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CoreMLDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | C6337B001F00B1130049AC8C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 28 | C6337B011F00B1130049AC8C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 29 | C6337B031F00B1130049AC8C /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 30 | C6337B041F00B1130049AC8C /* ViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = ""; }; 31 | C6337B071F00B1130049AC8C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 32 | C6337B091F00B1130049AC8C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 33 | C6337B0C1F00B1130049AC8C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 34 | C6337B0E1F00B1130049AC8C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 35 | C6337B0F1F00B1130049AC8C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 36 | C6337B171F00B3BE0049AC8C /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; 37 | C6337B181F00B3C50049AC8C /* Vision.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Vision.framework; path = System/Library/Frameworks/Vision.framework; sourceTree = SDKROOT; }; 38 | C6337B1B1F00B4750049AC8C /* DemoPanel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoPanel.h; sourceTree = ""; }; 39 | C6337B1C1F00B4750049AC8C /* DemoPanel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoPanel.m; sourceTree = ""; }; 40 | C6337B1E1F00BB320049AC8C /* Resnet50.mlmodel */ = {isa = PBXFileReference; lastKnownFileType = file.mlmodel; name = Resnet50.mlmodel; path = ../Resnet50.mlmodel; sourceTree = ""; }; 41 | C6337B201F00BBCC0049AC8C /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; 42 | C6337B221F00BBD40049AC8C /* CoreML.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreML.framework; path = System/Library/Frameworks/CoreML.framework; sourceTree = SDKROOT; }; 43 | C6C23D801F00D4F6002DB91A /* FaceLandmarkView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FaceLandmarkView.h; sourceTree = ""; }; 44 | C6C23D811F00D4F6002DB91A /* FaceLandmarkView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FaceLandmarkView.m; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | C6337AFA1F00B1130049AC8C /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | C6337B191F00B3D70049AC8C /* Vision.framework in Frameworks */, 53 | C6337B1A1F00B3D90049AC8C /* AVFoundation.framework in Frameworks */, 54 | C6337B211F00BBD00049AC8C /* CoreMedia.framework in Frameworks */, 55 | C6337B231F00BBD60049AC8C /* CoreML.framework in Frameworks */, 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | /* End PBXFrameworksBuildPhase section */ 60 | 61 | /* Begin PBXGroup section */ 62 | C6337AF41F00B1130049AC8C = { 63 | isa = PBXGroup; 64 | children = ( 65 | C6337AFF1F00B1130049AC8C /* CoreMLDemo */, 66 | C6337AFE1F00B1130049AC8C /* Products */, 67 | C6337B161F00B3BD0049AC8C /* Frameworks */, 68 | ); 69 | sourceTree = ""; 70 | }; 71 | C6337AFE1F00B1130049AC8C /* Products */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | C6337AFD1F00B1130049AC8C /* CoreMLDemo.app */, 75 | ); 76 | name = Products; 77 | sourceTree = ""; 78 | }; 79 | C6337AFF1F00B1130049AC8C /* CoreMLDemo */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | C6337B1E1F00BB320049AC8C /* Resnet50.mlmodel */, 83 | C6337B001F00B1130049AC8C /* AppDelegate.h */, 84 | C6337B011F00B1130049AC8C /* AppDelegate.m */, 85 | C6337B031F00B1130049AC8C /* ViewController.h */, 86 | C6337B041F00B1130049AC8C /* ViewController.mm */, 87 | C6337B1B1F00B4750049AC8C /* DemoPanel.h */, 88 | C6337B1C1F00B4750049AC8C /* DemoPanel.m */, 89 | C6C23D801F00D4F6002DB91A /* FaceLandmarkView.h */, 90 | C6C23D811F00D4F6002DB91A /* FaceLandmarkView.m */, 91 | C6337B061F00B1130049AC8C /* Main.storyboard */, 92 | C6337B091F00B1130049AC8C /* Assets.xcassets */, 93 | C6337B0B1F00B1130049AC8C /* LaunchScreen.storyboard */, 94 | C6337B0E1F00B1130049AC8C /* Info.plist */, 95 | C6337B0F1F00B1130049AC8C /* main.m */, 96 | ); 97 | path = CoreMLDemo; 98 | sourceTree = ""; 99 | }; 100 | C6337B161F00B3BD0049AC8C /* Frameworks */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | C6337B221F00BBD40049AC8C /* CoreML.framework */, 104 | C6337B201F00BBCC0049AC8C /* CoreMedia.framework */, 105 | C6337B181F00B3C50049AC8C /* Vision.framework */, 106 | C6337B171F00B3BE0049AC8C /* AVFoundation.framework */, 107 | ); 108 | name = Frameworks; 109 | sourceTree = ""; 110 | }; 111 | /* End PBXGroup section */ 112 | 113 | /* Begin PBXNativeTarget section */ 114 | C6337AFC1F00B1130049AC8C /* CoreMLDemo */ = { 115 | isa = PBXNativeTarget; 116 | buildConfigurationList = C6337B131F00B1130049AC8C /* Build configuration list for PBXNativeTarget "CoreMLDemo" */; 117 | buildPhases = ( 118 | C6337AF91F00B1130049AC8C /* Sources */, 119 | C6337AFA1F00B1130049AC8C /* Frameworks */, 120 | C6337AFB1F00B1130049AC8C /* Resources */, 121 | ); 122 | buildRules = ( 123 | ); 124 | dependencies = ( 125 | ); 126 | name = CoreMLDemo; 127 | productName = CoreMLDemo; 128 | productReference = C6337AFD1F00B1130049AC8C /* CoreMLDemo.app */; 129 | productType = "com.apple.product-type.application"; 130 | }; 131 | /* End PBXNativeTarget section */ 132 | 133 | /* Begin PBXProject section */ 134 | C6337AF51F00B1130049AC8C /* Project object */ = { 135 | isa = PBXProject; 136 | attributes = { 137 | LastUpgradeCheck = 0900; 138 | ORGANIZATIONNAME = Weibo; 139 | TargetAttributes = { 140 | C6337AFC1F00B1130049AC8C = { 141 | CreatedOnToolsVersion = 9.0; 142 | }; 143 | }; 144 | }; 145 | buildConfigurationList = C6337AF81F00B1130049AC8C /* Build configuration list for PBXProject "CoreMLDemo" */; 146 | compatibilityVersion = "Xcode 8.0"; 147 | developmentRegion = en; 148 | hasScannedForEncodings = 0; 149 | knownRegions = ( 150 | en, 151 | Base, 152 | ); 153 | mainGroup = C6337AF41F00B1130049AC8C; 154 | productRefGroup = C6337AFE1F00B1130049AC8C /* Products */; 155 | projectDirPath = ""; 156 | projectRoot = ""; 157 | targets = ( 158 | C6337AFC1F00B1130049AC8C /* CoreMLDemo */, 159 | ); 160 | }; 161 | /* End PBXProject section */ 162 | 163 | /* Begin PBXResourcesBuildPhase section */ 164 | C6337AFB1F00B1130049AC8C /* Resources */ = { 165 | isa = PBXResourcesBuildPhase; 166 | buildActionMask = 2147483647; 167 | files = ( 168 | C6337B0D1F00B1130049AC8C /* LaunchScreen.storyboard in Resources */, 169 | C6337B0A1F00B1130049AC8C /* Assets.xcassets in Resources */, 170 | C6337B081F00B1130049AC8C /* Main.storyboard in Resources */, 171 | ); 172 | runOnlyForDeploymentPostprocessing = 0; 173 | }; 174 | /* End PBXResourcesBuildPhase section */ 175 | 176 | /* Begin PBXSourcesBuildPhase section */ 177 | C6337AF91F00B1130049AC8C /* Sources */ = { 178 | isa = PBXSourcesBuildPhase; 179 | buildActionMask = 2147483647; 180 | files = ( 181 | C6337B1F1F00BB320049AC8C /* Resnet50.mlmodel in Sources */, 182 | C6C23D821F00D4F6002DB91A /* FaceLandmarkView.m in Sources */, 183 | C6337B051F00B1130049AC8C /* ViewController.mm in Sources */, 184 | C6337B101F00B1130049AC8C /* main.m in Sources */, 185 | C6337B021F00B1130049AC8C /* AppDelegate.m in Sources */, 186 | C6337B1D1F00B4750049AC8C /* DemoPanel.m in Sources */, 187 | ); 188 | runOnlyForDeploymentPostprocessing = 0; 189 | }; 190 | /* End PBXSourcesBuildPhase section */ 191 | 192 | /* Begin PBXVariantGroup section */ 193 | C6337B061F00B1130049AC8C /* Main.storyboard */ = { 194 | isa = PBXVariantGroup; 195 | children = ( 196 | C6337B071F00B1130049AC8C /* Base */, 197 | ); 198 | name = Main.storyboard; 199 | sourceTree = ""; 200 | }; 201 | C6337B0B1F00B1130049AC8C /* LaunchScreen.storyboard */ = { 202 | isa = PBXVariantGroup; 203 | children = ( 204 | C6337B0C1F00B1130049AC8C /* Base */, 205 | ); 206 | name = LaunchScreen.storyboard; 207 | sourceTree = ""; 208 | }; 209 | /* End PBXVariantGroup section */ 210 | 211 | /* Begin XCBuildConfiguration section */ 212 | C6337B111F00B1130049AC8C /* Debug */ = { 213 | isa = XCBuildConfiguration; 214 | buildSettings = { 215 | ALWAYS_SEARCH_USER_PATHS = NO; 216 | CLANG_ANALYZER_NONNULL = YES; 217 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 218 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 219 | CLANG_CXX_LIBRARY = "libc++"; 220 | CLANG_ENABLE_MODULES = YES; 221 | CLANG_ENABLE_OBJC_ARC = YES; 222 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 223 | CLANG_WARN_BOOL_CONVERSION = YES; 224 | CLANG_WARN_COMMA = YES; 225 | CLANG_WARN_CONSTANT_CONVERSION = YES; 226 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 227 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 228 | CLANG_WARN_EMPTY_BODY = YES; 229 | CLANG_WARN_ENUM_CONVERSION = YES; 230 | CLANG_WARN_INFINITE_RECURSION = YES; 231 | CLANG_WARN_INT_CONVERSION = YES; 232 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 233 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 234 | CLANG_WARN_STRICT_PROTOTYPES = YES; 235 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 236 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 237 | CLANG_WARN_UNREACHABLE_CODE = YES; 238 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 239 | CODE_SIGN_IDENTITY = "iPhone Developer"; 240 | COPY_PHASE_STRIP = NO; 241 | DEBUG_INFORMATION_FORMAT = dwarf; 242 | ENABLE_STRICT_OBJC_MSGSEND = YES; 243 | ENABLE_TESTABILITY = YES; 244 | GCC_C_LANGUAGE_STANDARD = gnu11; 245 | GCC_DYNAMIC_NO_PIC = NO; 246 | GCC_NO_COMMON_BLOCKS = YES; 247 | GCC_OPTIMIZATION_LEVEL = 0; 248 | GCC_PREPROCESSOR_DEFINITIONS = ( 249 | "DEBUG=1", 250 | "$(inherited)", 251 | ); 252 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 253 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 254 | GCC_WARN_UNDECLARED_SELECTOR = YES; 255 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 256 | GCC_WARN_UNUSED_FUNCTION = YES; 257 | GCC_WARN_UNUSED_VARIABLE = YES; 258 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 259 | MTL_ENABLE_DEBUG_INFO = YES; 260 | ONLY_ACTIVE_ARCH = YES; 261 | SDKROOT = iphoneos; 262 | }; 263 | name = Debug; 264 | }; 265 | C6337B121F00B1130049AC8C /* Release */ = { 266 | isa = XCBuildConfiguration; 267 | buildSettings = { 268 | ALWAYS_SEARCH_USER_PATHS = NO; 269 | CLANG_ANALYZER_NONNULL = YES; 270 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 271 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 272 | CLANG_CXX_LIBRARY = "libc++"; 273 | CLANG_ENABLE_MODULES = YES; 274 | CLANG_ENABLE_OBJC_ARC = YES; 275 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 276 | CLANG_WARN_BOOL_CONVERSION = YES; 277 | CLANG_WARN_COMMA = YES; 278 | CLANG_WARN_CONSTANT_CONVERSION = YES; 279 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 280 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 281 | CLANG_WARN_EMPTY_BODY = YES; 282 | CLANG_WARN_ENUM_CONVERSION = YES; 283 | CLANG_WARN_INFINITE_RECURSION = YES; 284 | CLANG_WARN_INT_CONVERSION = YES; 285 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 286 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 287 | CLANG_WARN_STRICT_PROTOTYPES = YES; 288 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 289 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 290 | CLANG_WARN_UNREACHABLE_CODE = YES; 291 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 292 | CODE_SIGN_IDENTITY = "iPhone Developer"; 293 | COPY_PHASE_STRIP = NO; 294 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 295 | ENABLE_NS_ASSERTIONS = NO; 296 | ENABLE_STRICT_OBJC_MSGSEND = YES; 297 | GCC_C_LANGUAGE_STANDARD = gnu11; 298 | GCC_NO_COMMON_BLOCKS = YES; 299 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 300 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 301 | GCC_WARN_UNDECLARED_SELECTOR = YES; 302 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 303 | GCC_WARN_UNUSED_FUNCTION = YES; 304 | GCC_WARN_UNUSED_VARIABLE = YES; 305 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 306 | MTL_ENABLE_DEBUG_INFO = NO; 307 | SDKROOT = iphoneos; 308 | VALIDATE_PRODUCT = YES; 309 | }; 310 | name = Release; 311 | }; 312 | C6337B141F00B1130049AC8C /* Debug */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 316 | DEVELOPMENT_TEAM = DMJXDB9H6Q; 317 | INFOPLIST_FILE = CoreMLDemo/Info.plist; 318 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 319 | PRODUCT_BUNDLE_IDENTIFIER = com.weibo.CoreMLDemo; 320 | PRODUCT_NAME = "$(TARGET_NAME)"; 321 | TARGETED_DEVICE_FAMILY = "1,2"; 322 | }; 323 | name = Debug; 324 | }; 325 | C6337B151F00B1130049AC8C /* Release */ = { 326 | isa = XCBuildConfiguration; 327 | buildSettings = { 328 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 329 | DEVELOPMENT_TEAM = DMJXDB9H6Q; 330 | INFOPLIST_FILE = CoreMLDemo/Info.plist; 331 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 332 | PRODUCT_BUNDLE_IDENTIFIER = com.weibo.CoreMLDemo; 333 | PRODUCT_NAME = "$(TARGET_NAME)"; 334 | TARGETED_DEVICE_FAMILY = "1,2"; 335 | }; 336 | name = Release; 337 | }; 338 | /* End XCBuildConfiguration section */ 339 | 340 | /* Begin XCConfigurationList section */ 341 | C6337AF81F00B1130049AC8C /* Build configuration list for PBXProject "CoreMLDemo" */ = { 342 | isa = XCConfigurationList; 343 | buildConfigurations = ( 344 | C6337B111F00B1130049AC8C /* Debug */, 345 | C6337B121F00B1130049AC8C /* Release */, 346 | ); 347 | defaultConfigurationIsVisible = 0; 348 | defaultConfigurationName = Release; 349 | }; 350 | C6337B131F00B1130049AC8C /* Build configuration list for PBXNativeTarget "CoreMLDemo" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | C6337B141F00B1130049AC8C /* Debug */, 354 | C6337B151F00B1130049AC8C /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | /* End XCConfigurationList section */ 360 | }; 361 | rootObject = C6337AF51F00B1130049AC8C /* Project object */; 362 | } 363 | -------------------------------------------------------------------------------- /CoreMLDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CoreMLDemo.xcodeproj/project.xcworkspace/xcuserdata/wutian.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naituw/CoreMLDemo/fcb0edf112f0f620a2a3ba9b071c57e171a59a0d/CoreMLDemo.xcodeproj/project.xcworkspace/xcuserdata/wutian.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CoreMLDemo.xcodeproj/xcuserdata/wutian.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /CoreMLDemo.xcodeproj/xcuserdata/wutian.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CoreMLDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /CoreMLDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CoreMLDemo 4 | // 5 | // Created by wutian on 2017/6/26. 6 | // Copyright © 2017年 Weibo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /CoreMLDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CoreMLDemo 4 | // 5 | // Created by wutian on 2017/6/26. 6 | // Copyright © 2017年 Weibo. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /CoreMLDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /CoreMLDemo/Base.lproj/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 | -------------------------------------------------------------------------------- /CoreMLDemo/Base.lproj/Main.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 | -------------------------------------------------------------------------------- /CoreMLDemo/DemoPanel.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoPanel.h 3 | // CoreMLDemo 4 | // 5 | // Created by wutian on 2017/6/26. 6 | // Copyright © 2017年 Weibo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DemoPanel : UIView 12 | 13 | @property (nonatomic, strong) NSString * text; 14 | @property (nonatomic, strong, readonly) UISegmentedControl * segmentedControl; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /CoreMLDemo/DemoPanel.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoPanel.m 3 | // CoreMLDemo 4 | // 5 | // Created by wutian on 2017/6/26. 6 | // Copyright © 2017年 Weibo. All rights reserved. 7 | // 8 | 9 | #import "DemoPanel.h" 10 | 11 | @interface DemoPanel () 12 | 13 | @property (nonatomic, strong) UIVisualEffectView * blurView; 14 | @property (nonatomic, strong) UILabel * textLabel; 15 | @property (nonatomic, strong) UISegmentedControl * segmentedControl; 16 | 17 | @end 18 | 19 | @implementation DemoPanel 20 | 21 | - (instancetype)initWithFrame:(CGRect)frame 22 | { 23 | if (self = [super initWithFrame:frame]) { 24 | 25 | self.layer.cornerRadius = 6.0; 26 | self.layer.masksToBounds = YES; 27 | 28 | UIBlurEffect * blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]; 29 | _blurView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; 30 | 31 | UIVisualEffectView * vibView = [[UIVisualEffectView alloc] initWithEffect:[UIVibrancyEffect effectForBlurEffect:blurEffect]]; 32 | vibView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 33 | [_blurView.contentView addSubview:vibView]; 34 | 35 | [self addSubview:_blurView]; 36 | 37 | [self addSubview:self.textLabel]; 38 | [vibView.contentView addSubview:self.segmentedControl]; 39 | } 40 | return self; 41 | } 42 | 43 | - (UILabel *)textLabel 44 | { 45 | if (!_textLabel) { 46 | _textLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 10, 10)]; 47 | _textLabel.font = [UIFont boldSystemFontOfSize:32]; 48 | _textLabel.textColor = [UIColor whiteColor]; 49 | _textLabel.textAlignment = NSTextAlignmentCenter; 50 | _textLabel.numberOfLines = 2; 51 | } 52 | return _textLabel; 53 | } 54 | 55 | - (UISegmentedControl *)segmentedControl 56 | { 57 | if (!_segmentedControl) { 58 | _segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"CoreML", @"Vision"]]; 59 | _segmentedControl.tintColor = [UIColor whiteColor]; 60 | _segmentedControl.selectedSegmentIndex = 0; 61 | } 62 | return _segmentedControl; 63 | } 64 | 65 | - (void)setText:(NSString *)text 66 | { 67 | _textLabel.text = text; 68 | } 69 | 70 | - (NSString *)text 71 | { 72 | return _textLabel.text; 73 | } 74 | 75 | - (void)layoutSubviews 76 | { 77 | [super layoutSubviews]; 78 | 79 | _blurView.frame = self.bounds; 80 | 81 | CGRect labelFrame = self.bounds; 82 | labelFrame.size.height = 100; 83 | labelFrame = CGRectInset(labelFrame, 10, 10); 84 | 85 | _textLabel.frame = labelFrame; 86 | 87 | CGRect segmentFrame = self.bounds; 88 | segmentFrame.size.height = 60; 89 | segmentFrame.origin.y = 100; 90 | segmentFrame = CGRectInset(segmentFrame, 10, 10); 91 | 92 | _segmentedControl.frame = segmentFrame; 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /CoreMLDemo/FaceLandmarkView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FaceLandmarkView.h 3 | // CoreMLDemo 4 | // 5 | // Created by wutian on 2017/6/26. 6 | // Copyright © 2017年 Weibo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface FaceLandmarkView : UIView 13 | 14 | @property (nonatomic, strong) VNFaceObservation * observation; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /CoreMLDemo/FaceLandmarkView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FaceLandmarkView.m 3 | // CoreMLDemo 4 | // 5 | // Created by wutian on 2017/6/26. 6 | // Copyright © 2017年 Weibo. All rights reserved. 7 | // 8 | 9 | #import "FaceLandmarkView.h" 10 | 11 | @implementation FaceLandmarkView 12 | 13 | - (instancetype)initWithFrame:(CGRect)frame 14 | { 15 | if (self = [super initWithFrame:frame]) { 16 | self.opaque = NO; 17 | } 18 | return self; 19 | } 20 | 21 | - (void)setObservation:(VNFaceObservation *)observation 22 | { 23 | if (_observation != observation) { 24 | _observation = observation; 25 | 26 | [self setNeedsDisplay]; 27 | } 28 | } 29 | 30 | - (void)drawFaceRegion:(VNFaceLandmarkRegion2D *)faceRegion boundingBox:(CGRect)boundingBox 31 | { 32 | UIBezierPath * path = [[UIBezierPath alloc] init]; 33 | 34 | const CGPoint * points = faceRegion.normalizedPoints; 35 | NSUInteger pointCount = faceRegion.pointCount; 36 | 37 | BOOL first = YES; 38 | 39 | for (NSUInteger i = 0; i < pointCount; i++) { 40 | CGPoint vector = points[i]; 41 | CGPoint point = CGPointMake(vector.x, vector.y); 42 | 43 | point.x *= boundingBox.size.width; 44 | point.y *= boundingBox.size.height; 45 | 46 | point.x += boundingBox.origin.x; 47 | point.y += boundingBox.origin.y; 48 | 49 | if (first) { 50 | [path moveToPoint:point]; 51 | first = NO; 52 | } else { 53 | [path addLineToPoint:point]; 54 | } 55 | } 56 | 57 | [path closePath]; 58 | 59 | [path setLineWidth:2]; 60 | 61 | [path stroke]; 62 | } 63 | 64 | - (void)drawRect:(CGRect)rect 65 | { 66 | CGContextRef ctx = UIGraphicsGetCurrentContext(); 67 | 68 | CGSize size = self.bounds.size; 69 | 70 | CGContextTranslateCTM(ctx, size.width, size.height); 71 | CGContextScaleCTM(ctx, -1, -1); 72 | 73 | CGRect bounding = _observation.boundingBox; 74 | bounding.origin.x *= size.width; 75 | bounding.origin.y *= size.height; 76 | 77 | bounding.size.width *= size.width; 78 | bounding.size.height *= size.height; 79 | 80 | UIBezierPath * path = [UIBezierPath bezierPathWithRect:bounding]; 81 | [path setLineWidth:3]; 82 | 83 | [[UIColor greenColor] setStroke]; 84 | [path stroke]; 85 | 86 | VNFaceLandmarks2D * landmarks = _observation.landmarks; 87 | 88 | [[UIColor whiteColor] setStroke]; 89 | 90 | [self drawFaceRegion:landmarks.leftEyebrow boundingBox:bounding]; 91 | [self drawFaceRegion:landmarks.rightEyebrow boundingBox:bounding]; 92 | 93 | [[UIColor greenColor] setStroke]; 94 | 95 | [self drawFaceRegion:landmarks.leftEye boundingBox:bounding]; 96 | [self drawFaceRegion:landmarks.rightEye boundingBox:bounding]; 97 | 98 | [[UIColor yellowColor] setStroke]; 99 | 100 | [self drawFaceRegion:landmarks.faceContour boundingBox:bounding]; 101 | 102 | [self drawFaceRegion:landmarks.nose boundingBox:bounding]; 103 | [self drawFaceRegion:landmarks.noseCrest boundingBox:bounding]; 104 | [self drawFaceRegion:landmarks.medianLine boundingBox:bounding]; 105 | 106 | [self drawFaceRegion:landmarks.leftPupil boundingBox:bounding]; 107 | [self drawFaceRegion:landmarks.rightPupil boundingBox:bounding]; 108 | 109 | [[UIColor redColor] setStroke]; 110 | 111 | [self drawFaceRegion:landmarks.outerLips boundingBox:bounding]; 112 | [self drawFaceRegion:landmarks.innerLips boundingBox:bounding]; 113 | } 114 | 115 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 116 | { 117 | [super touchesBegan:touches withEvent:event]; 118 | self.alpha = 0.0; 119 | } 120 | 121 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 122 | { 123 | [super touchesEnded:touches withEvent:event]; 124 | self.alpha = 1.0; 125 | } 126 | 127 | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 128 | { 129 | [super touchesCancelled:touches withEvent:event]; 130 | self.alpha = 1.0; 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /CoreMLDemo/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 | NSCameraUsageDescription 24 | Use with CoreML 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /CoreMLDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // CoreMLDemo 4 | // 5 | // Created by wutian on 2017/6/26. 6 | // Copyright © 2017年 Weibo. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /CoreMLDemo/ViewController.mm: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // CoreMLDemo 4 | // 5 | // Created by wutian on 2017/6/26. 6 | // Copyright © 2017年 Weibo. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "DemoPanel.h" 11 | #import 12 | #import 13 | #import "Resnet50.h" 14 | #import "FaceLandmarkView.h" 15 | 16 | #define let auto const 17 | 18 | typedef NS_ENUM(NSInteger, VisionMode) { 19 | VisionModeCoreML = 0, 20 | VisionModeFaceLandmark, 21 | }; 22 | 23 | @interface ViewController () 24 | 25 | @property (nonatomic, strong) AVCaptureSession * session; 26 | @property (nonatomic, strong) AVCaptureVideoPreviewLayer * previewLayer; 27 | @property (nonatomic, strong) dispatch_queue_t captureQueue; 28 | 29 | @property (nonatomic, strong) DemoPanel * demoPanel; 30 | @property (nonatomic, strong) FaceLandmarkView * faceLandmarkView; 31 | 32 | @property (nonatomic, strong) VNRequest * visionCoreMLRequest; 33 | @property (nonatomic, strong) VNRequest * visionFaceLandmarkRequest; 34 | 35 | @property (nonatomic, assign) VisionMode visionMode; 36 | @property (nonatomic, strong) AVCaptureInput * currentInput; 37 | @property (nonatomic, strong) AVCaptureOutput * currentOutput; 38 | 39 | @property (nonatomic, strong) VNSequenceRequestHandler * sequenceRequestHandler; 40 | 41 | @end 42 | 43 | @implementation ViewController 44 | 45 | - (void)viewDidLoad 46 | { 47 | [super viewDidLoad]; 48 | 49 | [self setupVisionRequests]; 50 | 51 | _captureQueue = dispatch_queue_create("com.wutian.CaptureQueue", DISPATCH_QUEUE_SERIAL); 52 | 53 | _session = [[AVCaptureSession alloc] init]; 54 | _previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_session]; 55 | 56 | [self.view.layer addSublayer:_previewLayer]; 57 | 58 | let videoOutput = [[AVCaptureVideoDataOutput alloc] init]; 59 | [videoOutput setSampleBufferDelegate:self queue:_captureQueue]; 60 | [videoOutput setAlwaysDiscardsLateVideoFrames:YES]; 61 | [videoOutput setVideoSettings:@{(NSString *)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}]; 62 | 63 | _session.sessionPreset = AVCaptureSessionPresetHigh; 64 | 65 | _currentOutput = videoOutput; 66 | [_session addOutput:videoOutput]; 67 | 68 | _visionMode = VisionModeFaceLandmark; 69 | self.visionMode = VisionModeCoreML; 70 | 71 | [_session startRunning]; 72 | 73 | _faceLandmarkView = [[FaceLandmarkView alloc] initWithFrame:self.view.bounds]; 74 | [self.view addSubview:_faceLandmarkView]; 75 | 76 | _demoPanel = [[DemoPanel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 77 | [_demoPanel.segmentedControl addTarget:self action:@selector(segmentedControlChanged:) forControlEvents:UIControlEventValueChanged]; 78 | [self.view addSubview:_demoPanel]; 79 | } 80 | 81 | - (void)viewWillLayoutSubviews 82 | { 83 | _previewLayer.frame = self.view.bounds; 84 | 85 | CGFloat panelPadding = 10; 86 | CGFloat panelHeight = 160; 87 | CGFloat panelAreaHeight = panelHeight + 2 * panelPadding; 88 | 89 | CGRect panelArea = CGRectMake(0, self.view.bounds.size.height - panelAreaHeight, self.view.bounds.size.width, panelAreaHeight); 90 | 91 | _faceLandmarkView.frame = self.view.bounds; 92 | _demoPanel.frame = CGRectInset(panelArea, panelPadding, panelPadding); 93 | } 94 | 95 | - (void)setupVisionRequests 96 | { 97 | let model = [Resnet50 new]; 98 | 99 | let visionModel = [VNCoreMLModel modelForMLModel:model.model error:NULL]; 100 | 101 | let classificationRequest = [[VNCoreMLRequest alloc] initWithModel:visionModel completionHandler:^(VNRequest * _Nonnull request, NSError * _Nullable error) { 102 | 103 | if (_visionMode != VisionModeCoreML) { 104 | return; 105 | } 106 | 107 | if (error) { 108 | return NSLog(@"Failed: %@", error); 109 | } 110 | let observations = request.results; 111 | if (!observations.count) { 112 | return NSLog(@"No Results"); 113 | } 114 | 115 | VNClassificationObservation * observation = nil; 116 | for (VNClassificationObservation * ob in observations) { 117 | if (![ob isKindOfClass:[VNClassificationObservation class]]) { 118 | continue; 119 | } 120 | if (!observation) { 121 | observation = ob; 122 | continue; 123 | } 124 | if (observation.confidence < ob.confidence) { 125 | observation = ob; 126 | } 127 | } 128 | 129 | dispatch_async(dispatch_get_main_queue(), ^{ 130 | NSString * text = [NSString stringWithFormat:@"%@ (%.0f%%)", [[observation.identifier componentsSeparatedByString:@", "] firstObject], observation.confidence * 100]; 131 | _demoPanel.text = text; 132 | }); 133 | }]; 134 | 135 | _visionCoreMLRequest = classificationRequest; 136 | 137 | let faceRequest = [[VNDetectFaceLandmarksRequest alloc] initWithCompletionHandler:^(VNRequest * _Nonnull request, NSError * _Nullable error) { 138 | 139 | if (_visionMode != VisionModeFaceLandmark) { 140 | return; 141 | } 142 | 143 | void (^finish)(VNFaceObservation *, NSString *) = ^(VNFaceObservation * ob, NSString * text) { 144 | dispatch_async(dispatch_get_main_queue(), ^{ 145 | _faceLandmarkView.observation = ob; 146 | _demoPanel.text = text; 147 | }); 148 | }; 149 | 150 | if (error) { 151 | return finish(nil, error.description); 152 | } 153 | let observations = request.results; 154 | if (!observations.count) { 155 | return finish(nil, @"未识别人脸"); 156 | } 157 | 158 | VNFaceObservation * observation = nil; 159 | for (VNFaceObservation * ob in observations) { 160 | if (![ob isKindOfClass:[VNFaceObservation class]]) { 161 | continue; 162 | } 163 | if (!observation) { 164 | observation = ob; 165 | continue; 166 | } 167 | if (observation.confidence < ob.confidence) { 168 | observation = ob; 169 | } 170 | } 171 | 172 | finish(observation, [NSString stringWithFormat:@"(%.0f%%)", observation.confidence * 100]); 173 | }]; 174 | 175 | _visionFaceLandmarkRequest = faceRequest; 176 | } 177 | 178 | - (AVCaptureDevice *)deviceWithPosition:(AVCaptureDevicePosition)position 179 | { 180 | return [AVCaptureDevice defaultDeviceWithDeviceType:AVCaptureDeviceTypeBuiltInWideAngleCamera mediaType:AVMediaTypeVideo position:position]; 181 | } 182 | 183 | - (void)setVisionMode:(VisionMode)visionMode 184 | { 185 | if (_visionMode != visionMode) { 186 | _visionMode = visionMode; 187 | 188 | [_session beginConfiguration]; 189 | 190 | if (_currentInput) { 191 | [_session removeInput:_currentInput]; 192 | _currentInput = nil; 193 | } 194 | 195 | let camera = [self deviceWithPosition:(visionMode == VisionModeFaceLandmark) ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack]; 196 | let cameraInput = [AVCaptureDeviceInput deviceInputWithDevice:camera error:NULL]; 197 | _currentInput = cameraInput; 198 | [_session addInput:cameraInput]; 199 | 200 | let conn = [_currentOutput connectionWithMediaType:AVMediaTypeVideo]; 201 | conn.videoOrientation = AVCaptureVideoOrientationPortrait; 202 | 203 | [_session commitConfiguration]; 204 | } 205 | } 206 | 207 | - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 208 | { 209 | let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 210 | if (!pixelBuffer) { 211 | return; 212 | } 213 | 214 | AVCaptureInput * input = connection.inputPorts.firstObject.input; 215 | if (input != _currentInput) { 216 | return; 217 | } 218 | 219 | NSMutableDictionary * requestOptions = [NSMutableDictionary dictionary]; 220 | let cameraIntrinsicData = CMGetAttachment(sampleBuffer, kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix, nil); 221 | if (cameraIntrinsicData) { 222 | requestOptions[VNImageOptionCameraIntrinsics] = (__bridge NSData *)cameraIntrinsicData; 223 | } 224 | 225 | if (!_sequenceRequestHandler) { 226 | _sequenceRequestHandler = [[VNSequenceRequestHandler alloc] init]; 227 | } 228 | 229 | [_sequenceRequestHandler performRequests:(_visionMode == VisionModeFaceLandmark) ? @[_visionFaceLandmarkRequest] : @[_visionCoreMLRequest] onCVPixelBuffer:pixelBuffer error:NULL]; 230 | } 231 | 232 | - (void)segmentedControlChanged:(id)sender 233 | { 234 | self.visionMode = (VisionMode)_demoPanel.segmentedControl.selectedSegmentIndex; 235 | self.demoPanel.text = @"初始化..."; 236 | self.faceLandmarkView.observation = nil; 237 | _sequenceRequestHandler = nil; 238 | } 239 | 240 | @end 241 | -------------------------------------------------------------------------------- /CoreMLDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CoreMLDemo 4 | // 5 | // Created by wutian on 2017/6/26. 6 | // Copyright © 2017年 Weibo. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Demo for CoreML and Vision framework 2 | 3 | ![Intro Image](intro.gif) 4 | 5 | ## Usage 6 | 7 | - Download ResNet50 model file from https://developer.apple.com/machine-learning/ 8 | - Clone this project 9 | - Place the `Resnet50.mlmodel` file at root of CoreMLDemo folder 10 | - Build and Run 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /intro.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Naituw/CoreMLDemo/fcb0edf112f0f620a2a3ba9b071c57e171a59a0d/intro.gif --------------------------------------------------------------------------------