From 6b444781d21dd72210796dae8cea86d255410e10 Mon Sep 17 00:00:00 2001 From: HaroldoTeruya Date: Wed, 17 Mar 2021 17:51:19 -0300 Subject: [PATCH 1/3] refactor: move info plist to root directory --- YoonitFacefy/Info.plist => Info.plist | 0 YoonitFacefy.xcodeproj/project.pbxproj | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename YoonitFacefy/Info.plist => Info.plist (100%) diff --git a/YoonitFacefy/Info.plist b/Info.plist similarity index 100% rename from YoonitFacefy/Info.plist rename to Info.plist diff --git a/YoonitFacefy.xcodeproj/project.pbxproj b/YoonitFacefy.xcodeproj/project.pbxproj index 18b8988..fdfd944 100644 --- a/YoonitFacefy.xcodeproj/project.pbxproj +++ b/YoonitFacefy.xcodeproj/project.pbxproj @@ -93,6 +93,7 @@ 6176EF25252CFEE000F4D4DD /* README.md */, 6176EF22252CFC9500F4D4DD /* LICENSE */, 6176EF1F252CFA4300F4D4DD /* YoonitFacefy.podspec */, + 6176EEFA252CF9D200F4D4DD /* Info.plist */, 6176EEF8252CF9D200F4D4DD /* YoonitFacefy */, 6176EEF7252CF9D200F4D4DD /* Products */, 85073D94B694632C1A966E28 /* Pods */, @@ -112,7 +113,6 @@ isa = PBXGroup; children = ( 5C0C6435254208E400EDF95B /* src */, - 6176EEFA252CF9D200F4D4DD /* Info.plist */, 5CB4F8EE25CC7DDC001D3606 /* YoonitFacefy.h */, ); path = YoonitFacefy; From d44c2c67c983faba823f8dc056189de1e478528d Mon Sep 17 00:00:00 2001 From: HaroldoTeruya Date: Wed, 17 Mar 2021 17:52:49 -0300 Subject: [PATCH 2/3] refactor: remove face detected availability aparameters --- .../FacefyViewController.swift | 40 ++++++---------- README.md | 46 ++++++++----------- YoonitFacefy/src/FaceDetected.swift | 44 ++++++------------ YoonitFacefy/src/Facefy.swift | 2 - YoonitFacefy/src/FacefyController.swift | 31 ++++++------- 5 files changed, 62 insertions(+), 101 deletions(-) diff --git a/Example/YoonitFacefyDemo/YoonitFacefyDemo/FacefyViewController.swift b/Example/YoonitFacefyDemo/YoonitFacefyDemo/FacefyViewController.swift index 0986ae8..1e4ebce 100644 --- a/Example/YoonitFacefyDemo/YoonitFacefyDemo/FacefyViewController.swift +++ b/Example/YoonitFacefyDemo/YoonitFacefyDemo/FacefyViewController.swift @@ -54,43 +54,27 @@ class FacefyViewController: self.facefy?.detect(image!) { faceDetected in - if let faceDetected: FaceDetected = faceDetected { - - print( - "onFaceDetected" + - "\n x: \(faceDetected.boundingBox.minX), y: \(faceDetected.boundingBox.minY), width: \(faceDetected.boundingBox.width), height: \(faceDetected.boundingBox.height)" + - "\n leftEyeOpenProbability: \(faceDetected.hasLeftEyeOpenProbability) \(faceDetected.leftEyeOpenProbability)" + - "\n rightEyeOpenProbability: \(faceDetected.hasRightEyeOpenProbability) \(faceDetected.rightEyeOpenProbability)" + - "\n smilingProbability: \(faceDetected.hasSmilingProbability) \(faceDetected.smilingProbability)" + - "\n headEulerAngleX: \(faceDetected.hasHeadEulerAngleX) \(faceDetected.headEulerAngleX)" + - "\n headEulerAngleY: \(faceDetected.hasHeadEulerAngleY) \(faceDetected.headEulerAngleY)" + - "\n headEulerAngleZ: \(faceDetected.hasHeadEulerAngleZ) \(faceDetected.headEulerAngleZ)" - ) - + if let faceDetected: FaceDetected = faceDetected { self.handleDisplayProbability( label: self.leftEyeLabel, - hasValue: faceDetected.hasLeftEyeOpenProbability, value: faceDetected.leftEyeOpenProbability, validText: "Open", invalidText: "Close" ) self.handleDisplayProbability( label: self.rightEyeLabel, - hasValue: faceDetected.hasRightEyeOpenProbability, value: faceDetected.rightEyeOpenProbability, validText: "Open", invalidText: "Close" ) self.handleDisplayProbability( label: self.smilingLabel, - hasValue: faceDetected.hasSmilingProbability, value: faceDetected.smilingProbability, validText: "Smiling", invalidText: "Not Smiling" ) - if faceDetected.hasHeadEulerAngleX { - let headEulerAngleX = faceDetected.headEulerAngleX + if let headEulerAngleX = faceDetected.headEulerAngleX { var headPosition = "" if headEulerAngleX < -36 { headPosition = "Super Down" @@ -106,8 +90,7 @@ class FacefyViewController: self.verticalMovementLabel.text = headPosition } - if faceDetected.hasHeadEulerAngleY { - let headEulerAngleY = faceDetected.headEulerAngleY + if let headEulerAngleY = faceDetected.headEulerAngleY { var headPosition = "" if headEulerAngleY < -36 { headPosition = "Super Right" @@ -123,8 +106,7 @@ class FacefyViewController: self.horizontalMovementLabel.text = headPosition } - if faceDetected.hasHeadEulerAngleZ { - let headEulerAngleZ = faceDetected.headEulerAngleZ + if let headEulerAngleZ = faceDetected.headEulerAngleZ { var headPosition = "" if headEulerAngleZ < -36 { headPosition = "Super Left" @@ -140,7 +122,14 @@ class FacefyViewController: self.tiltMovementLabel.text = headPosition } - if let cgImage = image?.cgImage { + if let cgImage = image?.cgImage { + + self.graphicView.handleDraw( + image: cgImage, + faceBoundingBox: faceDetected.boundingBox, + faceContours: faceDetected.contours + ) + // Crop the face image. self.faceImageView.image = UIImage( cgImage: cgImage.cropping(to: faceDetected.boundingBox)! @@ -160,12 +149,11 @@ class FacefyViewController: func handleDisplayProbability( label: UILabel, - hasValue: Bool, - value: Float, + value: Float?, validText: String, invalidText: String ) { - if hasValue { + if let value: Float = value { label.text = value > 0.8 ? validText : invalidText } } diff --git a/README.md b/README.md index 9deffa9..2e455fc 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ A iOS plugin to provide: * Face expressions * Face movement - + ## Table of Contents @@ -53,29 +53,29 @@ let facefy: Facefy = Facefy() self.facefy.detect(image!) { faceDetected in if let faceDetected: FaceDetected = faceDetected { - if faceDetected.hasLeftEyeOpenProbability { - print(String(format: "%.2f", faceDetected.leftEyeOpenProbability)) + if let leftEyeOpenProbability = faceDetected.leftEyeOpenProbability { + print(String(format: "%.2f", leftEyeOpenProbability)) } - if faceDetected.rightEyeOpenProbability { - print(String(format: "%.2f", faceDetected.rightEyeOpenProbability)) + if let rightEyeOpenProbability = faceDetected.rightEyeOpenProbability { + print(String(format: "%.2f", rightEyeOpenProbability)) } - if faceDetected.smilingProbability { + if let smilingProbability = faceDetected.smilingProbability { print(String(format: "%.2f", faceDetected.smilingProbability)) } - if faceDetected.hasHeadEulerAngleX { - print(String(format: "%.2f", faceDetected.headEulerAngleX)) + if let hasHeadEulerAngleX = faceDetected.hasHeadEulerAngleX { + print(String(format: "%.2f", hasHeadEulerAngleX)) } - if faceDetected.hasHeadEulerAngleY { - print(String(format: "%.2f", faceDetected.headEulerAngleY)) + if let hasHeadEulerAngleY = faceDetected.hasHeadEulerAngleY { + print(String(format: "%.2f", hasHeadEulerAngleY)) } - if faceDetected.hasHeadEulerAngleZ { - print(String(format: "%.2f", faceDetected.headEulerAngleZ)) + if let hasHeadEulerAngleZ = faceDetected.hasHeadEulerAngleZ { + print(String(format: "%.2f", hasHeadEulerAngleZ)) } if let cgImage = image?.cgImage { - // Crop the face image from. - UIImage( + // Crop the face image from the camera frame. + let faceImage = UIImage( cgImage: cgImage.cropping(to: faceDetected.boundingBox)! ).withHorizontallyFlippedOrientation() } @@ -98,18 +98,12 @@ self.facefy.detect(image!) { faceDetected in | Attribute | Type | Description | | - | - | - | | boundingBox | `CGRect` | The face bounding box related to the image input. | -| leftEyeOpenProbability | `Float` | The left eye open probability. | -| hasLeftEyeOpenProbability | `Bool` | Indicates whether a left eye open probability is available. | -| rightEyeOpenProbability | `Float` | The right eye open probability. | -| hasRightEyeOpenProbability | `Bool` | Indicates whether a right eye open probability is available. | -| smilingProbability | `Float` | The smiling probability. | -| hasSmilingProbability | `Bool` | Indicates whether a smiling probability is available. | -| headEulerAngleX | `Float` | The angle in degrees that indicate the vertical head direction. See [Head Movements](#headmovements). | -| hasHeadEulerAngleX | `Bool` | Indicates whether the detector found the head x euler angle. | -| headEulerAngleY | `Float` | The angle in degrees that indicate the horizontal head direction. See [Head Movements](#headmovements). | -| hasHeadEulerAngleY | `Bool` | Indicates whether the detector found the head y euler angle. | -| headEulerAngleZ | `Float` | The angle in degrees that indicate the tilt head direction. See [Head Movements](#headmovements). | -| hasHeadEulerAngleZ | `Bool` | Indicates whether the detector found the head z euler angle. | +| leftEyeOpenProbability | `Float?` | The left eye open probability. | +| rightEyeOpenProbability | `Float?` | The right eye open probability. | +| smilingProbability | `Float?` | The smiling probability. | +| headEulerAngleX | `Float?` | The angle in degrees that indicate the vertical head direction. See [Head Movements](#headmovements). | +| headEulerAngleY | `Float?` | The angle in degrees that indicate the horizontal head direction. See [Head Movements](#headmovements). | +| headEulerAngleZ | `Float?` | The angle in degrees that indicate the tilt head direction. See [Head Movements](#headmovements). | | contours | `[CGPoint]` | List of points that represents the shape of the detected face. | #### Head Movements diff --git a/YoonitFacefy/src/FaceDetected.swift b/YoonitFacefy/src/FaceDetected.swift index f051ed1..7aa3402 100644 --- a/YoonitFacefy/src/FaceDetected.swift +++ b/YoonitFacefy/src/FaceDetected.swift @@ -14,49 +14,31 @@ import UIKit public class FaceDetected { public var boundingBox: CGRect - public var leftEyeOpenProbability: Float - public var hasLeftEyeOpenProbability: Bool - public var rightEyeOpenProbability: Float - public var hasRightEyeOpenProbability: Bool - public var smilingProbability: Float - public var hasSmilingProbability: Bool - public var headEulerAngleX: Float - public var hasHeadEulerAngleX: Bool - public var headEulerAngleY: Float - public var hasHeadEulerAngleY: Bool - public var headEulerAngleZ: Float - public var hasHeadEulerAngleZ: Bool + public var leftEyeOpenProbability: Float? + public var rightEyeOpenProbability: Float? + public var smilingProbability: Float? + public var headEulerAngleX: Float? + public var headEulerAngleY: Float? + public var headEulerAngleZ: Float? public var contours: [CGPoint] = [] init( boundingBox: CGRect, - leftEyeOpenProbability: Float, - hasLeftEyeOpenProbability: Bool, - rightEyeOpenProbability: Float, - hasRightEyeOpenProbability: Bool, - smilingProbability: Float, - hasSmilingProbability: Bool, - headEulerAngleX: Float, - hasHeadEulerAngleX: Bool, - headEulerAngleY: Float, - hasHeadEulerAngleY: Bool, - headEulerAngleZ: Float, - hasHeadEulerAngleZ: Bool, + leftEyeOpenProbability: Float?, + rightEyeOpenProbability: Float?, + smilingProbability: Float?, + headEulerAngleX: Float?, + headEulerAngleY: Float?, + headEulerAngleZ: Float?, contours: [CGPoint] ) { self.boundingBox = boundingBox self.leftEyeOpenProbability = leftEyeOpenProbability - self.hasLeftEyeOpenProbability = hasLeftEyeOpenProbability self.rightEyeOpenProbability = rightEyeOpenProbability - self.hasRightEyeOpenProbability = hasRightEyeOpenProbability self.smilingProbability = smilingProbability - self.hasSmilingProbability = hasSmilingProbability self.headEulerAngleX = headEulerAngleX - self.hasHeadEulerAngleX = hasHeadEulerAngleX self.headEulerAngleY = headEulerAngleY - self.hasHeadEulerAngleY = hasHeadEulerAngleY - self.headEulerAngleZ = headEulerAngleZ - self.hasHeadEulerAngleZ = hasHeadEulerAngleZ + self.headEulerAngleZ = headEulerAngleZ self.contours = contours } } diff --git a/YoonitFacefy/src/Facefy.swift b/YoonitFacefy/src/Facefy.swift index 53c3c04..8bbe4d9 100644 --- a/YoonitFacefy/src/Facefy.swift +++ b/YoonitFacefy/src/Facefy.swift @@ -9,9 +9,7 @@ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // -import Foundation import UIKit -import Vision public class Facefy { diff --git a/YoonitFacefy/src/FacefyController.swift b/YoonitFacefy/src/FacefyController.swift index 3968620..1ac74bf 100644 --- a/YoonitFacefy/src/FacefyController.swift +++ b/YoonitFacefy/src/FacefyController.swift @@ -9,9 +9,7 @@ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // -import Foundation import UIKit -import Vision import MLKit public class FacefyController { @@ -19,9 +17,9 @@ public class FacefyController { private let faceDetector: FaceDetector init() { - let options: FaceDetectorOptions = FaceDetectorOptions() + let options = FaceDetectorOptions() options.performanceMode = .fast - options.landmarkMode = .all + options.landmarkMode = .none options.contourMode = .all options.classificationMode = .all @@ -63,22 +61,23 @@ public class FacefyController { } } } + + let rightEyeOpenProbability: Float? = face.hasRightEyeOpenProbability ? Float(face.rightEyeOpenProbability) : nil + let leftEyeOpenProbability: Float? = face.hasLeftEyeOpenProbability ? Float(face.leftEyeOpenProbability) : nil + let smilingProbability: Float? = face.hasSmilingProbability ? Float(face.smilingProbability) : nil + let headEulerAngleX: Float? = face.hasHeadEulerAngleX ? Float(face.headEulerAngleX) : nil + let headEulerAngleY: Float? = face.hasHeadEulerAngleY ? Float(face.headEulerAngleY) : nil + let headEulerAngleZ: Float? = face.hasHeadEulerAngleZ ? Float(face.headEulerAngleZ) : nil onSuccess( FaceDetected( boundingBox: face.frame, - leftEyeOpenProbability: Float(face.rightEyeOpenProbability), - hasLeftEyeOpenProbability: face.hasRightEyeOpenProbability, - rightEyeOpenProbability: Float(face.leftEyeOpenProbability), - hasRightEyeOpenProbability: face.hasLeftEyeOpenProbability, - smilingProbability: Float(face.smilingProbability), - hasSmilingProbability: face.hasSmilingProbability, - headEulerAngleX: Float(face.headEulerAngleX), - hasHeadEulerAngleX: face.hasHeadEulerAngleX, - headEulerAngleY: Float(face.headEulerAngleY), - hasHeadEulerAngleY: face.hasHeadEulerAngleY, - headEulerAngleZ: Float(face.headEulerAngleZ), - hasHeadEulerAngleZ: face.hasHeadEulerAngleZ, + leftEyeOpenProbability: rightEyeOpenProbability, + rightEyeOpenProbability: leftEyeOpenProbability, + smilingProbability: smilingProbability, + headEulerAngleX: headEulerAngleX, + headEulerAngleY: headEulerAngleY, + headEulerAngleZ: headEulerAngleZ, contours: faceContours ) ) From b776f1f6999fdcb1755ad19da56c8f0ecc8305cc Mon Sep 17 00:00:00 2001 From: HaroldoTeruya Date: Wed, 17 Mar 2021 18:10:45 -0300 Subject: [PATCH 3/3] build: bump version from 1.0.3 to 1.0.4 --- .../YoonitFacefyDemo.xcodeproj/project.pbxproj | 8 ++++---- YoonitFacefy.podspec | 2 +- YoonitFacefy.xcodeproj/project.pbxproj | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Example/YoonitFacefyDemo/YoonitFacefyDemo.xcodeproj/project.pbxproj b/Example/YoonitFacefyDemo/YoonitFacefyDemo.xcodeproj/project.pbxproj index 9861ee9..72b9080 100644 --- a/Example/YoonitFacefyDemo/YoonitFacefyDemo.xcodeproj/project.pbxproj +++ b/Example/YoonitFacefyDemo/YoonitFacefyDemo.xcodeproj/project.pbxproj @@ -404,8 +404,8 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.2; - PRODUCT_BUNDLE_IDENTIFIER = ai.cyberlabs.YoonitFacefyDemo; + MARKETING_VERSION = 1.0.4; + PRODUCT_BUNDLE_IDENTIFIER = com.yoonit.facefydemo; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -434,8 +434,8 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.2; - PRODUCT_BUNDLE_IDENTIFIER = ai.cyberlabs.YoonitFacefyDemo; + MARKETING_VERSION = 1.0.4; + PRODUCT_BUNDLE_IDENTIFIER = com.yoonit.facefydemo; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/YoonitFacefy.podspec b/YoonitFacefy.podspec index 8853bb5..b568a25 100644 --- a/YoonitFacefy.podspec +++ b/YoonitFacefy.podspec @@ -9,7 +9,7 @@ Pod::Spec.new do |spec| # spec.name = "YoonitFacefy" - spec.version = "1.0.3" + spec.version = "1.0.4" spec.summary = "The face detection's module for iOS with a lot of awesome features" # This description is used to generate tags and improve search results. diff --git a/YoonitFacefy.xcodeproj/project.pbxproj b/YoonitFacefy.xcodeproj/project.pbxproj index fdfd944..80d3335 100644 --- a/YoonitFacefy.xcodeproj/project.pbxproj +++ b/YoonitFacefy.xcodeproj/project.pbxproj @@ -414,7 +414,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = YoonitFacefy/Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -422,8 +422,8 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.0.3; - PRODUCT_BUNDLE_IDENTIFIER = ai.cyberlabs.YoonitFacefy; + MARKETING_VERSION = 1.0.4; + PRODUCT_BUNDLE_IDENTIFIER = com.yoonit.facefy; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; SUPPORTS_MACCATALYST = NO; @@ -444,7 +444,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = YoonitFacefy/Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -452,8 +452,8 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MARKETING_VERSION = 1.0.3; - PRODUCT_BUNDLE_IDENTIFIER = ai.cyberlabs.YoonitFacefy; + MARKETING_VERSION = 1.0.4; + PRODUCT_BUNDLE_IDENTIFIER = com.yoonit.facefy; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; SUPPORTS_MACCATALYST = NO;