Skip to content

Commit

Permalink
feat: add no light challenge implementation (#127)
Browse files Browse the repository at this point in the history
* feat: add no light challenge implementation

* update package.swift for CI build

* Fix unit tests

* Address review comments
  • Loading branch information
thisisabhash committed Jul 1, 2024
1 parent c24b7f0 commit bc16192
Show file tree
Hide file tree
Showing 21 changed files with 305 additions and 81 deletions.
2 changes: 0 additions & 2 deletions HostApp/HostApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,6 @@
Base,
);
mainGroup = 9070FF97285112B4009867D5;
packageReferences = (
);
productRefGroup = 9070FFA1285112B4009867D5 /* Products */;
projectDirPath = "";
projectRoot = "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/aws-amplify/amplify-swift",
"state" : {
"revision" : "7846328106dba471b3fb35170155e92aad50d427",
"version" : "2.33.3"
"branch" : "feat/no-light-support",
"revision" : "7c1fa2f7a766208f5af69ca8dce5fd02e6de4db6"
}
},
{
Expand Down Expand Up @@ -50,8 +50,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/stephencelis/SQLite.swift.git",
"state" : {
"revision" : "e78ae0220e17525a15ac68c697a155eb7a672a8e",
"version" : "0.15.0"
"revision" : "5f5ad81ac0d0a0f3e56e39e646e8423c617df523",
"version" : "0.13.2"
}
},
{
Expand Down
3 changes: 2 additions & 1 deletion HostApp/HostApp/Views/ExampleLivenessView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ struct ExampleLivenessView: View {
case .liveness:
FaceLivenessDetectorView(
sessionID: viewModel.sessionID,
region: "us-east-1",
// TODO: Change before merging to main
region: "us-west-2",
isPresented: Binding(
get: { viewModel.presentationState == .liveness },
set: { _ in }
Expand Down
8 changes: 4 additions & 4 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/aws-amplify/amplify-swift",
"state" : {
"revision" : "dbc4a0412f4b5cd96f3e756e78bbd1e8e0a35a2f",
"version" : "2.35.4"
"branch" : "feat/no-light-support",
"revision" : "7c1fa2f7a766208f5af69ca8dce5fd02e6de4db6"
}
},
{
Expand Down Expand Up @@ -50,8 +50,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/stephencelis/SQLite.swift.git",
"state" : {
"revision" : "a95fc6df17d108bd99210db5e8a9bac90fe984b8",
"version" : "0.15.3"
"revision" : "5f5ad81ac0d0a0f3e56e39e646e8423c617df523",
"version" : "0.13.2"
}
},
{
Expand Down
3 changes: 2 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ let package = Package(
targets: ["FaceLiveness"]),
],
dependencies: [
.package(url: "https://github.com/aws-amplify/amplify-swift", exact: "2.35.4")
// TODO: Change this before merge to main
.package(url: "https://github.com/aws-amplify/amplify-swift", branch: "feat/no-light-support")
],
targets: [
.target(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import Foundation
@_spi(PredictionsFaceLiveness) import AWSPredictionsPlugin

struct DetectedFace {
var boundingBox: CGRect
Expand All @@ -19,7 +20,8 @@ struct DetectedFace {

let confidence: Float

func boundingBoxFromLandmarks(ovalRect: CGRect) -> CGRect {
func boundingBoxFromLandmarks(ovalRect: CGRect,
ovalMatchChallenge: FaceLivenessSession.OvalMatchChallenge) -> CGRect {
let alpha = 2.0
let gamma = 1.8
let ow = (alpha * pupilDistance + gamma * faceHeight) / 2
Expand All @@ -34,7 +36,7 @@ struct DetectedFace {
}

let faceWidth = ow
let faceHeight = 1.618 * faceWidth
let faceHeight = ovalMatchChallenge.oval.heightWidthRatio * faceWidth
let faceBoxBottom = boundingBox.maxY
let faceBoxTop = faceBoxBottom - faceHeight
let faceBoxLeft = min(cx - ow / 2, rightEar.x)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Accelerate
import CoreGraphics
import CoreImage
import VideoToolbox
@_spi(PredictionsFaceLiveness) import AWSPredictionsPlugin

enum FaceDetectorShortRange {}

Expand All @@ -33,11 +34,16 @@ extension FaceDetectorShortRange {
)
}

weak var faceDetectionSessionConfiguration: FaceDetectionSessionConfigurationWrapper?
weak var detectionResultHandler: FaceDetectionResultHandler?

func setResultHandler(detectionResultHandler: FaceDetectionResultHandler) {
self.detectionResultHandler = detectionResultHandler
}

func setFaceDetectionSessionConfigurationWrapper(configuration: FaceDetectionSessionConfigurationWrapper) {
self.faceDetectionSessionConfiguration = configuration
}

func detectFaces(from buffer: CVPixelBuffer) {
let faces = prediction(for: buffer)
Expand Down Expand Up @@ -105,10 +111,17 @@ extension FaceDetectorShortRange {
count: confidenceScoresCapacity
)
)

let blazeFaceDetectionThreshold: Float
if let sessionConfiguration = faceDetectionSessionConfiguration?.sessionConfiguration {
blazeFaceDetectionThreshold = Float(sessionConfiguration.ovalMatchChallenge.faceDetectionThreshold)
} else {
blazeFaceDetectionThreshold = confidenceScoreThreshold
}

var passingConfidenceScoresIndices = confidenceScores
.enumerated()
.filter { $0.element >= confidenceScoreThreshold }
.filter { $0.element >= blazeFaceDetectionThreshold}
.sorted(by: {
$0.element > $1.element
})
Expand Down
5 changes: 5 additions & 0 deletions Sources/FaceLiveness/FaceDetection/FaceDetector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import AVFoundation
@_spi(PredictionsFaceLiveness) import AWSPredictionsPlugin

protocol FaceDetector {
func detectFaces(from buffer: CVPixelBuffer)
Expand All @@ -16,6 +17,10 @@ protocol FaceDetectionResultHandler: AnyObject {
func process(newResult: FaceDetectionResult)
}

protocol FaceDetectionSessionConfigurationWrapper: AnyObject {
var sessionConfiguration: FaceLivenessSession.SessionConfiguration? { get }
}

enum FaceDetectionResult {
case noFace
case singleFace(DetectedFace)
Expand Down
46 changes: 31 additions & 15 deletions Sources/FaceLiveness/Views/GetReadyPage/GetReadyPageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,49 @@
//

import SwiftUI
@_spi(PredictionsFaceLiveness) import AWSPredictionsPlugin

struct GetReadyPageView: View {
let beginCheckButtonDisabled: Bool
let onBegin: () -> Void

let challenge: Challenge

init(
onBegin: @escaping () -> Void,
beginCheckButtonDisabled: Bool = false
beginCheckButtonDisabled: Bool = false,
challenge: Challenge
) {
self.onBegin = onBegin
self.beginCheckButtonDisabled = beginCheckButtonDisabled
self.challenge = challenge
}

var body: some View {
VStack {
ZStack {
CameraPreviewView()
VStack {
WarningBox(
titleText: LocalizedStrings.get_ready_photosensitivity_title,
bodyText: LocalizedStrings.get_ready_photosensitivity_description,
popoverContent: { photosensitivityWarningPopoverContent }
)
.accessibilityElement(children: .combine)
Text(LocalizedStrings.preview_center_your_face_text)
.font(.title)
.multilineTextAlignment(.center)
Spacer()
}.padding()
switch self.challenge.type {
case .faceMovementChallenge:
VStack {
Text(LocalizedStrings.preview_center_your_face_text)
.font(.title)
.multilineTextAlignment(.center)
Spacer()
}.padding()
case . faceMovementAndLightChallenge:
VStack {
WarningBox(
titleText: LocalizedStrings.get_ready_photosensitivity_title,
bodyText: LocalizedStrings.get_ready_photosensitivity_description,
popoverContent: { photosensitivityWarningPopoverContent }
)
.accessibilityElement(children: .combine)
Text(LocalizedStrings.preview_center_your_face_text)
.font(.title)
.multilineTextAlignment(.center)
Spacer()
}.padding()
}
}
beginCheckButton
}
Expand Down Expand Up @@ -72,6 +86,8 @@ struct GetReadyPageView: View {

struct GetReadyPageView_Previews: PreviewProvider {
static var previews: some View {
GetReadyPageView(onBegin: {})
GetReadyPageView(onBegin: {},
challenge: .init(version: "2.0.0",
type: .faceMovementAndLightChallenge))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import SwiftUI
import Combine
@_spi(PredictionsFaceLiveness) import AWSPredictionsPlugin

struct InstructionContainerView: View {
@ObservedObject var viewModel: FaceLivenessDetectionViewModel
Expand Down Expand Up @@ -97,13 +98,29 @@ struct InstructionContainerView: View {
argument: LocalizedStrings.challenge_verifying
)
}
case .faceMatched:
case .completedNoLightCheck:
InstructionView(
text: LocalizedStrings.challenge_instruction_hold_still,
backgroundColor: .livenessPrimaryBackground,
textColor: .livenessPrimaryLabel,
font: .title
text: LocalizedStrings.challenge_verifying,
backgroundColor: .livenessBackground
)
.onAppear {
UIAccessibility.post(
notification: .announcement,
argument: LocalizedStrings.challenge_verifying
)
}
case .faceMatched:
if let challenge = viewModel.challenge,
case .faceMovementAndLightChallenge = challenge.type {
InstructionView(
text: LocalizedStrings.challenge_instruction_hold_still,
backgroundColor: .livenessPrimaryBackground,
textColor: .livenessPrimaryLabel,
font: .title
)
} else {
EmptyView()
}
default:
EmptyView()
}
Expand Down
Loading

0 comments on commit bc16192

Please sign in to comment.