@moveris/shared 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +57 -41
- package/dist/index.d.ts +57 -41
- package/dist/index.js +86 -12
- package/dist/index.mjs +82 -12
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -215,6 +215,40 @@ interface LivenessCallbacks {
|
|
|
215
215
|
onStateChange?: OnStateChangeCallback;
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
interface FaceLandmarkPoint {
|
|
219
|
+
x: number;
|
|
220
|
+
y: number;
|
|
221
|
+
z: number;
|
|
222
|
+
}
|
|
223
|
+
interface LandmarkValidationResult {
|
|
224
|
+
valid: boolean;
|
|
225
|
+
message?: string;
|
|
226
|
+
}
|
|
227
|
+
declare const LANDMARK_INDEX: {
|
|
228
|
+
readonly NOSE_TIP: 1;
|
|
229
|
+
readonly UPPER_LIP: 13;
|
|
230
|
+
readonly LOWER_LIP: 14;
|
|
231
|
+
};
|
|
232
|
+
declare const EYE_LANDMARK_INDICES: {
|
|
233
|
+
readonly RIGHT_EYE: readonly [33, 7, 163, 144, 145, 153, 154, 155, 133, 173, 157, 158, 159, 160, 161, 246];
|
|
234
|
+
readonly LEFT_EYE: readonly [362, 382, 381, 380, 374, 373, 390, 249, 263, 466, 388, 387, 386, 385, 384, 398];
|
|
235
|
+
};
|
|
236
|
+
interface EyeRegionBounds {
|
|
237
|
+
x: number;
|
|
238
|
+
y: number;
|
|
239
|
+
width: number;
|
|
240
|
+
height: number;
|
|
241
|
+
}
|
|
242
|
+
interface EyeRegionsBounds {
|
|
243
|
+
leftEye: EyeRegionBounds;
|
|
244
|
+
rightEye: EyeRegionBounds;
|
|
245
|
+
}
|
|
246
|
+
declare function getEyeRegionBounds(landmarks: FaceLandmarkPoint[]): EyeRegionsBounds | null;
|
|
247
|
+
declare const LANDMARK_MIN_BOUND = 0.1;
|
|
248
|
+
declare const LANDMARK_MAX_BOUND = 0.9;
|
|
249
|
+
declare const MIN_LANDMARK_COUNT = 15;
|
|
250
|
+
declare function validateFaceLandmarks(landmarks: FaceLandmarkPoint[] | undefined): LandmarkValidationResult;
|
|
251
|
+
|
|
218
252
|
interface FaceBoundingBox {
|
|
219
253
|
originX: number;
|
|
220
254
|
originY: number;
|
|
@@ -272,15 +306,17 @@ declare const MIN_FACE_SIDE_MARGIN = 0.05;
|
|
|
272
306
|
declare const MIN_CAPTURE_ALIGNMENT = 0.6;
|
|
273
307
|
declare const HIGH_ALIGNMENT = 0.85;
|
|
274
308
|
declare const GOOD_ALIGNMENT = 0.5;
|
|
275
|
-
declare const IDEAL_CROP_MULTIPLIER =
|
|
276
|
-
declare const MIN_CROP_MULTIPLIER =
|
|
277
|
-
declare const MAX_CROP_MULTIPLIER =
|
|
309
|
+
declare const IDEAL_CROP_MULTIPLIER = 3;
|
|
310
|
+
declare const MIN_CROP_MULTIPLIER = 2.5;
|
|
311
|
+
declare const MAX_CROP_MULTIPLIER = 4;
|
|
278
312
|
declare const FACE_CENTER_VERTICAL_OFFSET = 0.05;
|
|
313
|
+
declare const MIN_IDEAL_FACE_RATIO = 0.05;
|
|
314
|
+
declare const MAX_IDEAL_FACE_RATIO = 0.2;
|
|
279
315
|
declare const MIN_FACE_RATIO = 0.036;
|
|
280
316
|
declare const MAX_FACE_RATIO = 0.7;
|
|
281
317
|
declare const FACE_CROP_OUTPUT_SIZE = 224;
|
|
282
|
-
declare const MAX_FACE_PERCENTAGE_IN_CROP = 0.
|
|
283
|
-
declare const TARGET_FACE_PERCENTAGE_IN_CROP = 0.
|
|
318
|
+
declare const MAX_FACE_PERCENTAGE_IN_CROP = 0.45;
|
|
319
|
+
declare const TARGET_FACE_PERCENTAGE_IN_CROP = 0.33;
|
|
284
320
|
declare function analyzeBlur(grayscalePixels: number[], width: number, height: number, threshold?: number): BlurAnalysis;
|
|
285
321
|
declare function rgbaToGrayscale(rgbaPixels: Uint8ClampedArray | number[]): number[];
|
|
286
322
|
declare function calculateBrightness(rgbaPixels: Uint8ClampedArray | number[]): number;
|
|
@@ -306,6 +342,12 @@ declare function checkFrameQuality(options: {
|
|
|
306
342
|
lightingAnalysis?: LightingAnalysis;
|
|
307
343
|
minAlignment?: number;
|
|
308
344
|
}): FrameQualityResult;
|
|
345
|
+
interface FaceRollResult {
|
|
346
|
+
roll: number;
|
|
347
|
+
tooTilted: boolean;
|
|
348
|
+
}
|
|
349
|
+
declare const MAX_FACE_ROLL_DEGREES = 15;
|
|
350
|
+
declare function detectFaceRoll(landmarks: FaceLandmarkPoint[]): FaceRollResult;
|
|
309
351
|
declare class BaseFrameCollector {
|
|
310
352
|
protected frames: CapturedFrame[];
|
|
311
353
|
protected maxFrames: number;
|
|
@@ -321,40 +363,6 @@ declare class BaseFrameCollector {
|
|
|
321
363
|
getNextIndex(): number;
|
|
322
364
|
}
|
|
323
365
|
|
|
324
|
-
interface FaceLandmarkPoint {
|
|
325
|
-
x: number;
|
|
326
|
-
y: number;
|
|
327
|
-
z: number;
|
|
328
|
-
}
|
|
329
|
-
interface LandmarkValidationResult {
|
|
330
|
-
valid: boolean;
|
|
331
|
-
message?: string;
|
|
332
|
-
}
|
|
333
|
-
declare const LANDMARK_INDEX: {
|
|
334
|
-
readonly NOSE_TIP: 1;
|
|
335
|
-
readonly UPPER_LIP: 13;
|
|
336
|
-
readonly LOWER_LIP: 14;
|
|
337
|
-
};
|
|
338
|
-
declare const EYE_LANDMARK_INDICES: {
|
|
339
|
-
readonly RIGHT_EYE: readonly [33, 7, 163, 144, 145, 153, 154, 155, 133, 173, 157, 158, 159, 160, 161, 246];
|
|
340
|
-
readonly LEFT_EYE: readonly [362, 382, 381, 380, 374, 373, 390, 249, 263, 466, 388, 387, 386, 385, 384, 398];
|
|
341
|
-
};
|
|
342
|
-
interface EyeRegionBounds {
|
|
343
|
-
x: number;
|
|
344
|
-
y: number;
|
|
345
|
-
width: number;
|
|
346
|
-
height: number;
|
|
347
|
-
}
|
|
348
|
-
interface EyeRegionsBounds {
|
|
349
|
-
leftEye: EyeRegionBounds;
|
|
350
|
-
rightEye: EyeRegionBounds;
|
|
351
|
-
}
|
|
352
|
-
declare function getEyeRegionBounds(landmarks: FaceLandmarkPoint[]): EyeRegionsBounds | null;
|
|
353
|
-
declare const LANDMARK_MIN_BOUND = 0.1;
|
|
354
|
-
declare const LANDMARK_MAX_BOUND = 0.9;
|
|
355
|
-
declare const MIN_LANDMARK_COUNT = 15;
|
|
356
|
-
declare function validateFaceLandmarks(landmarks: FaceLandmarkPoint[] | undefined): LandmarkValidationResult;
|
|
357
|
-
|
|
358
366
|
interface DetectionResult {
|
|
359
367
|
type: string;
|
|
360
368
|
passed: boolean;
|
|
@@ -620,7 +628,7 @@ declare const ERROR_MESSAGES_ES: Record<string, string>;
|
|
|
620
628
|
declare function getApiErrorMessage(code: string | undefined, message?: string, customMessages?: Record<string, string>): string;
|
|
621
629
|
declare function isRetryableError(code: string | undefined): boolean;
|
|
622
630
|
|
|
623
|
-
declare const ALIGNMENT_THRESHOLD_CAPTURE = 0.
|
|
631
|
+
declare const ALIGNMENT_THRESHOLD_CAPTURE = 0.85;
|
|
624
632
|
declare const ALIGNMENT_THRESHOLD_POOR = 0.6;
|
|
625
633
|
declare const ALIGNMENT_THRESHOLD_GOOD = 0.6;
|
|
626
634
|
declare const ALIGNMENT_THRESHOLD_PERFECT = 0.85;
|
|
@@ -677,6 +685,8 @@ declare const FEEDBACK_MESSAGES: {
|
|
|
677
685
|
readonly move_back: "Move back - face too close";
|
|
678
686
|
readonly too_close: "Move back - face too close";
|
|
679
687
|
readonly too_far: "Move closer - face too far";
|
|
688
|
+
readonly move_closer_ideal: "Move a little closer";
|
|
689
|
+
readonly move_back_ideal: "Move back slightly";
|
|
680
690
|
readonly face_not_visible: "Center your face - edges cut off";
|
|
681
691
|
readonly partial_face: "Center your face - edges cut off";
|
|
682
692
|
readonly hold_still: "Hold still - image blurry";
|
|
@@ -684,6 +694,8 @@ declare const FEEDBACK_MESSAGES: {
|
|
|
684
694
|
readonly poor_lighting: "Improve lighting";
|
|
685
695
|
readonly too_dark: "Low lighting - move to a brighter area";
|
|
686
696
|
readonly backlit: "Backlit - try facing the light source";
|
|
697
|
+
readonly phone_angle_low: "Raise your phone to eye level";
|
|
698
|
+
readonly phone_tilted: "Hold your phone level";
|
|
687
699
|
readonly hand_detected: "Remove hand from face";
|
|
688
700
|
readonly eyes_not_visible: "Eyes not clearly visible";
|
|
689
701
|
readonly eyes_shadowed: "Eyes are in shadow - improve lighting";
|
|
@@ -714,6 +726,10 @@ interface CaptureQualityState {
|
|
|
714
726
|
isPartialFace: boolean;
|
|
715
727
|
framesCaptured: number;
|
|
716
728
|
targetFrames: number;
|
|
729
|
+
tooFarFromIdeal?: boolean;
|
|
730
|
+
tooCloseToIdeal?: boolean;
|
|
731
|
+
phoneAngled?: boolean;
|
|
732
|
+
phoneTilted?: boolean;
|
|
717
733
|
}
|
|
718
734
|
declare function getCaptureQualityFeedback(state: CaptureQualityState): string;
|
|
719
735
|
declare function canCaptureFrame(state: Omit<CaptureQualityState, 'framesCaptured' | 'targetFrames' | 'isCapturing'>): boolean;
|
|
@@ -764,4 +780,4 @@ declare function analyzeEyeRegionContrast(pixels: Uint8Array | Uint8ClampedArray
|
|
|
764
780
|
declare function detectSpecularHighlights(pixels: Uint8Array | Uint8ClampedArray, threshold?: number): number;
|
|
765
781
|
declare function checkEyeRegionQuality(pixels: Uint8Array | Uint8ClampedArray, thresholds?: EyeQualityThresholds): EyeRegionQuality;
|
|
766
782
|
|
|
767
|
-
export { ALIGNMENT_THRESHOLD_CAPTURE, ALIGNMENT_THRESHOLD_GOOD, ALIGNMENT_THRESHOLD_PERFECT, ALIGNMENT_THRESHOLD_POOR, API_ENDPOINTS, API_ERROR_CODES, API_PATHS, AUTH_CONFIG, type ApiErrorCode, BACKLIT_RATIO_THRESHOLD, BLUR_THRESHOLD_MOBILE, BaseFrameCollector, type BlurAnalysis, type CaptureQualityState, type CapturedFrame, type CropData, DEFAULT_BLUR_THRESHOLD, DEFAULT_ENDPOINT, DEFAULT_FACE_DETECTION_TIERS, DEFAULT_GAZE_THRESHOLDS, DEFAULT_HAND_OCCLUSION_CONFIG, DEFAULT_LIVENESS_CONFIG, DEFAULT_LOCALE, DEFAULT_OVAL_REGION, DEFAULT_STABILIZER_CONFIG, DEFAULT_STATUS_MESSAGES, type DetectionResult, type DetectionSummary, type DetectorConfig, ERROR_MESSAGES, ERROR_MESSAGES_ES, ES_LOCALE, EYE_LANDMARK_INDICES, EYE_QUALITY_THRESHOLDS, type ErrorResponse, type EyeQualityThresholds, type EyeRegionBounds, type EyeRegionQuality, type EyeRegionsBounds, FACE_CENTER_VERTICAL_OFFSET, FACE_CROP_OUTPUT_SIZE, FEEDBACK_MESSAGES, FRAME_BUFFER_CONFIG, FRAME_CONFIG, type FaceAlignmentResult, type FaceBoundingBox, type FaceDetectionTiers, type FaceInOvalResult, type FaceLandmarkPoint, type FaceVisibilityResult, type FastCheckCropsRequest, type FastCheckModel, type FastCheckRequest, type FastCheckResponse, type FastCheckStreamRequest, type FastCheckStreamResponse, type FeedbackLocale, type FeedbackMessageKey, type Frame, FrameBuffer, type FrameData, type FrameQualityResult, FrameQueue, type FrameSource, GOOD_ALIGNMENT, type GazeThresholds, HIGH_ALIGNMENT, HYBRID_MODEL_CONFIGS, type HandOcclusionConfig, type HeadPose, type HealthResponse, type Hybrid150CheckRequest, type Hybrid50CheckRequest, type HybridCheckRequest, type HybridCheckResponse, type HybridFrameData, type HybridModelConfig, IDEAL_CROP_MULTIPLIER, type JobStatus, type JobStatusResponse, LANDMARK_INDEX, LANDMARK_MAX_BOUND, LANDMARK_MIN_BOUND, LOW_LIGHT_THRESHOLD, type LandmarkValidationResult, type LightingAnalysis, LivenessApiError, type LivenessCallbacks, LivenessClient, type LivenessClientConfig, type LivenessConfig, type LivenessResult, type LivenessState, MAX_CROP_MULTIPLIER, MAX_FACE_PERCENTAGE_IN_CROP, MAX_FACE_RATIO, MIN_CAPTURE_ALIGNMENT, MIN_CROP_MULTIPLIER, MIN_FACE_BOTTOM_MARGIN, MIN_FACE_RATIO, MIN_FACE_SIDE_MARGIN, MIN_FACE_TOP_MARGIN, MIN_LANDMARK_COUNT, MODEL_CONFIGS, type ModelConfig, type ModelEntry, type ModelType, type ModelsResponse, OVAL_GUIDE_COLORS, OVAL_GUIDE_STYLES, OVAL_REGION_DESKTOP, OVAL_REGION_MOBILE, type OnErrorCallback, type OnFrameCapturedCallback, type OnProgressCallback, type OnResultCallback, type OnStateChangeCallback, type OvalGuideState, type OvalRegion, type QueueStatsResponse, RETRY_CONFIG, type RetryOptions, type StabilizationProgress, type StabilizationResult, type StabilizerConfig, type StatusMessageKey, type StreamingStatus, TARGET_FACE_PERCENTAGE_IN_CROP, type Verdict, type VerifyRequest, type VerifyResponse, type VideoFrameMetadata, analyzeBlur, analyzeEyeRegionBrightness, analyzeEyeRegionContrast, analyzeLighting, calculateAdaptiveCropMultiplier, calculateBrightness, calculateFaceAlignment, calculateFaceCropRegion, canCaptureFrame, checkEyeRegionQuality, checkFrameQuality, decodeBase64, detectSpecularHighlights, encodeBase64, generateSessionId, getActiveModels, getApiErrorMessage, getCaptureQualityFeedback, getEyeRegionBounds, getFeedbackMessage, getMinFramesForModel, getOvalGuideState, getStatusMessage, hasEnoughFrames, isDeprecatedModel, isFaceCropFullyInFrame, isFaceFullyVisible, isFaceInOval, isRetryableError, retryWithBackoff, rgbaToGrayscale, sleep, toFrameData, toHybridFrameData, toLivenessResult, toLivenessResultFromStream, validateApiKey, validateFaceLandmarks, validateFrameCount, validateFrameData, validateFrameIndex, validateTimestamp, validateUUID, validateUrl };
|
|
783
|
+
export { ALIGNMENT_THRESHOLD_CAPTURE, ALIGNMENT_THRESHOLD_GOOD, ALIGNMENT_THRESHOLD_PERFECT, ALIGNMENT_THRESHOLD_POOR, API_ENDPOINTS, API_ERROR_CODES, API_PATHS, AUTH_CONFIG, type ApiErrorCode, BACKLIT_RATIO_THRESHOLD, BLUR_THRESHOLD_MOBILE, BaseFrameCollector, type BlurAnalysis, type CaptureQualityState, type CapturedFrame, type CropData, DEFAULT_BLUR_THRESHOLD, DEFAULT_ENDPOINT, DEFAULT_FACE_DETECTION_TIERS, DEFAULT_GAZE_THRESHOLDS, DEFAULT_HAND_OCCLUSION_CONFIG, DEFAULT_LIVENESS_CONFIG, DEFAULT_LOCALE, DEFAULT_OVAL_REGION, DEFAULT_STABILIZER_CONFIG, DEFAULT_STATUS_MESSAGES, type DetectionResult, type DetectionSummary, type DetectorConfig, ERROR_MESSAGES, ERROR_MESSAGES_ES, ES_LOCALE, EYE_LANDMARK_INDICES, EYE_QUALITY_THRESHOLDS, type ErrorResponse, type EyeQualityThresholds, type EyeRegionBounds, type EyeRegionQuality, type EyeRegionsBounds, FACE_CENTER_VERTICAL_OFFSET, FACE_CROP_OUTPUT_SIZE, FEEDBACK_MESSAGES, FRAME_BUFFER_CONFIG, FRAME_CONFIG, type FaceAlignmentResult, type FaceBoundingBox, type FaceDetectionTiers, type FaceInOvalResult, type FaceLandmarkPoint, type FaceRollResult, type FaceVisibilityResult, type FastCheckCropsRequest, type FastCheckModel, type FastCheckRequest, type FastCheckResponse, type FastCheckStreamRequest, type FastCheckStreamResponse, type FeedbackLocale, type FeedbackMessageKey, type Frame, FrameBuffer, type FrameData, type FrameQualityResult, FrameQueue, type FrameSource, GOOD_ALIGNMENT, type GazeThresholds, HIGH_ALIGNMENT, HYBRID_MODEL_CONFIGS, type HandOcclusionConfig, type HeadPose, type HealthResponse, type Hybrid150CheckRequest, type Hybrid50CheckRequest, type HybridCheckRequest, type HybridCheckResponse, type HybridFrameData, type HybridModelConfig, IDEAL_CROP_MULTIPLIER, type JobStatus, type JobStatusResponse, LANDMARK_INDEX, LANDMARK_MAX_BOUND, LANDMARK_MIN_BOUND, LOW_LIGHT_THRESHOLD, type LandmarkValidationResult, type LightingAnalysis, LivenessApiError, type LivenessCallbacks, LivenessClient, type LivenessClientConfig, type LivenessConfig, type LivenessResult, type LivenessState, MAX_CROP_MULTIPLIER, MAX_FACE_PERCENTAGE_IN_CROP, MAX_FACE_RATIO, MAX_FACE_ROLL_DEGREES, MAX_IDEAL_FACE_RATIO, MIN_CAPTURE_ALIGNMENT, MIN_CROP_MULTIPLIER, MIN_FACE_BOTTOM_MARGIN, MIN_FACE_RATIO, MIN_FACE_SIDE_MARGIN, MIN_FACE_TOP_MARGIN, MIN_IDEAL_FACE_RATIO, MIN_LANDMARK_COUNT, MODEL_CONFIGS, type ModelConfig, type ModelEntry, type ModelType, type ModelsResponse, OVAL_GUIDE_COLORS, OVAL_GUIDE_STYLES, OVAL_REGION_DESKTOP, OVAL_REGION_MOBILE, type OnErrorCallback, type OnFrameCapturedCallback, type OnProgressCallback, type OnResultCallback, type OnStateChangeCallback, type OvalGuideState, type OvalRegion, type QueueStatsResponse, RETRY_CONFIG, type RetryOptions, type StabilizationProgress, type StabilizationResult, type StabilizerConfig, type StatusMessageKey, type StreamingStatus, TARGET_FACE_PERCENTAGE_IN_CROP, type Verdict, type VerifyRequest, type VerifyResponse, type VideoFrameMetadata, analyzeBlur, analyzeEyeRegionBrightness, analyzeEyeRegionContrast, analyzeLighting, calculateAdaptiveCropMultiplier, calculateBrightness, calculateFaceAlignment, calculateFaceCropRegion, canCaptureFrame, checkEyeRegionQuality, checkFrameQuality, decodeBase64, detectFaceRoll, detectSpecularHighlights, encodeBase64, generateSessionId, getActiveModels, getApiErrorMessage, getCaptureQualityFeedback, getEyeRegionBounds, getFeedbackMessage, getMinFramesForModel, getOvalGuideState, getStatusMessage, hasEnoughFrames, isDeprecatedModel, isFaceCropFullyInFrame, isFaceFullyVisible, isFaceInOval, isRetryableError, retryWithBackoff, rgbaToGrayscale, sleep, toFrameData, toHybridFrameData, toLivenessResult, toLivenessResultFromStream, validateApiKey, validateFaceLandmarks, validateFrameCount, validateFrameData, validateFrameIndex, validateTimestamp, validateUUID, validateUrl };
|
package/dist/index.d.ts
CHANGED
|
@@ -215,6 +215,40 @@ interface LivenessCallbacks {
|
|
|
215
215
|
onStateChange?: OnStateChangeCallback;
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
interface FaceLandmarkPoint {
|
|
219
|
+
x: number;
|
|
220
|
+
y: number;
|
|
221
|
+
z: number;
|
|
222
|
+
}
|
|
223
|
+
interface LandmarkValidationResult {
|
|
224
|
+
valid: boolean;
|
|
225
|
+
message?: string;
|
|
226
|
+
}
|
|
227
|
+
declare const LANDMARK_INDEX: {
|
|
228
|
+
readonly NOSE_TIP: 1;
|
|
229
|
+
readonly UPPER_LIP: 13;
|
|
230
|
+
readonly LOWER_LIP: 14;
|
|
231
|
+
};
|
|
232
|
+
declare const EYE_LANDMARK_INDICES: {
|
|
233
|
+
readonly RIGHT_EYE: readonly [33, 7, 163, 144, 145, 153, 154, 155, 133, 173, 157, 158, 159, 160, 161, 246];
|
|
234
|
+
readonly LEFT_EYE: readonly [362, 382, 381, 380, 374, 373, 390, 249, 263, 466, 388, 387, 386, 385, 384, 398];
|
|
235
|
+
};
|
|
236
|
+
interface EyeRegionBounds {
|
|
237
|
+
x: number;
|
|
238
|
+
y: number;
|
|
239
|
+
width: number;
|
|
240
|
+
height: number;
|
|
241
|
+
}
|
|
242
|
+
interface EyeRegionsBounds {
|
|
243
|
+
leftEye: EyeRegionBounds;
|
|
244
|
+
rightEye: EyeRegionBounds;
|
|
245
|
+
}
|
|
246
|
+
declare function getEyeRegionBounds(landmarks: FaceLandmarkPoint[]): EyeRegionsBounds | null;
|
|
247
|
+
declare const LANDMARK_MIN_BOUND = 0.1;
|
|
248
|
+
declare const LANDMARK_MAX_BOUND = 0.9;
|
|
249
|
+
declare const MIN_LANDMARK_COUNT = 15;
|
|
250
|
+
declare function validateFaceLandmarks(landmarks: FaceLandmarkPoint[] | undefined): LandmarkValidationResult;
|
|
251
|
+
|
|
218
252
|
interface FaceBoundingBox {
|
|
219
253
|
originX: number;
|
|
220
254
|
originY: number;
|
|
@@ -272,15 +306,17 @@ declare const MIN_FACE_SIDE_MARGIN = 0.05;
|
|
|
272
306
|
declare const MIN_CAPTURE_ALIGNMENT = 0.6;
|
|
273
307
|
declare const HIGH_ALIGNMENT = 0.85;
|
|
274
308
|
declare const GOOD_ALIGNMENT = 0.5;
|
|
275
|
-
declare const IDEAL_CROP_MULTIPLIER =
|
|
276
|
-
declare const MIN_CROP_MULTIPLIER =
|
|
277
|
-
declare const MAX_CROP_MULTIPLIER =
|
|
309
|
+
declare const IDEAL_CROP_MULTIPLIER = 3;
|
|
310
|
+
declare const MIN_CROP_MULTIPLIER = 2.5;
|
|
311
|
+
declare const MAX_CROP_MULTIPLIER = 4;
|
|
278
312
|
declare const FACE_CENTER_VERTICAL_OFFSET = 0.05;
|
|
313
|
+
declare const MIN_IDEAL_FACE_RATIO = 0.05;
|
|
314
|
+
declare const MAX_IDEAL_FACE_RATIO = 0.2;
|
|
279
315
|
declare const MIN_FACE_RATIO = 0.036;
|
|
280
316
|
declare const MAX_FACE_RATIO = 0.7;
|
|
281
317
|
declare const FACE_CROP_OUTPUT_SIZE = 224;
|
|
282
|
-
declare const MAX_FACE_PERCENTAGE_IN_CROP = 0.
|
|
283
|
-
declare const TARGET_FACE_PERCENTAGE_IN_CROP = 0.
|
|
318
|
+
declare const MAX_FACE_PERCENTAGE_IN_CROP = 0.45;
|
|
319
|
+
declare const TARGET_FACE_PERCENTAGE_IN_CROP = 0.33;
|
|
284
320
|
declare function analyzeBlur(grayscalePixels: number[], width: number, height: number, threshold?: number): BlurAnalysis;
|
|
285
321
|
declare function rgbaToGrayscale(rgbaPixels: Uint8ClampedArray | number[]): number[];
|
|
286
322
|
declare function calculateBrightness(rgbaPixels: Uint8ClampedArray | number[]): number;
|
|
@@ -306,6 +342,12 @@ declare function checkFrameQuality(options: {
|
|
|
306
342
|
lightingAnalysis?: LightingAnalysis;
|
|
307
343
|
minAlignment?: number;
|
|
308
344
|
}): FrameQualityResult;
|
|
345
|
+
interface FaceRollResult {
|
|
346
|
+
roll: number;
|
|
347
|
+
tooTilted: boolean;
|
|
348
|
+
}
|
|
349
|
+
declare const MAX_FACE_ROLL_DEGREES = 15;
|
|
350
|
+
declare function detectFaceRoll(landmarks: FaceLandmarkPoint[]): FaceRollResult;
|
|
309
351
|
declare class BaseFrameCollector {
|
|
310
352
|
protected frames: CapturedFrame[];
|
|
311
353
|
protected maxFrames: number;
|
|
@@ -321,40 +363,6 @@ declare class BaseFrameCollector {
|
|
|
321
363
|
getNextIndex(): number;
|
|
322
364
|
}
|
|
323
365
|
|
|
324
|
-
interface FaceLandmarkPoint {
|
|
325
|
-
x: number;
|
|
326
|
-
y: number;
|
|
327
|
-
z: number;
|
|
328
|
-
}
|
|
329
|
-
interface LandmarkValidationResult {
|
|
330
|
-
valid: boolean;
|
|
331
|
-
message?: string;
|
|
332
|
-
}
|
|
333
|
-
declare const LANDMARK_INDEX: {
|
|
334
|
-
readonly NOSE_TIP: 1;
|
|
335
|
-
readonly UPPER_LIP: 13;
|
|
336
|
-
readonly LOWER_LIP: 14;
|
|
337
|
-
};
|
|
338
|
-
declare const EYE_LANDMARK_INDICES: {
|
|
339
|
-
readonly RIGHT_EYE: readonly [33, 7, 163, 144, 145, 153, 154, 155, 133, 173, 157, 158, 159, 160, 161, 246];
|
|
340
|
-
readonly LEFT_EYE: readonly [362, 382, 381, 380, 374, 373, 390, 249, 263, 466, 388, 387, 386, 385, 384, 398];
|
|
341
|
-
};
|
|
342
|
-
interface EyeRegionBounds {
|
|
343
|
-
x: number;
|
|
344
|
-
y: number;
|
|
345
|
-
width: number;
|
|
346
|
-
height: number;
|
|
347
|
-
}
|
|
348
|
-
interface EyeRegionsBounds {
|
|
349
|
-
leftEye: EyeRegionBounds;
|
|
350
|
-
rightEye: EyeRegionBounds;
|
|
351
|
-
}
|
|
352
|
-
declare function getEyeRegionBounds(landmarks: FaceLandmarkPoint[]): EyeRegionsBounds | null;
|
|
353
|
-
declare const LANDMARK_MIN_BOUND = 0.1;
|
|
354
|
-
declare const LANDMARK_MAX_BOUND = 0.9;
|
|
355
|
-
declare const MIN_LANDMARK_COUNT = 15;
|
|
356
|
-
declare function validateFaceLandmarks(landmarks: FaceLandmarkPoint[] | undefined): LandmarkValidationResult;
|
|
357
|
-
|
|
358
366
|
interface DetectionResult {
|
|
359
367
|
type: string;
|
|
360
368
|
passed: boolean;
|
|
@@ -620,7 +628,7 @@ declare const ERROR_MESSAGES_ES: Record<string, string>;
|
|
|
620
628
|
declare function getApiErrorMessage(code: string | undefined, message?: string, customMessages?: Record<string, string>): string;
|
|
621
629
|
declare function isRetryableError(code: string | undefined): boolean;
|
|
622
630
|
|
|
623
|
-
declare const ALIGNMENT_THRESHOLD_CAPTURE = 0.
|
|
631
|
+
declare const ALIGNMENT_THRESHOLD_CAPTURE = 0.85;
|
|
624
632
|
declare const ALIGNMENT_THRESHOLD_POOR = 0.6;
|
|
625
633
|
declare const ALIGNMENT_THRESHOLD_GOOD = 0.6;
|
|
626
634
|
declare const ALIGNMENT_THRESHOLD_PERFECT = 0.85;
|
|
@@ -677,6 +685,8 @@ declare const FEEDBACK_MESSAGES: {
|
|
|
677
685
|
readonly move_back: "Move back - face too close";
|
|
678
686
|
readonly too_close: "Move back - face too close";
|
|
679
687
|
readonly too_far: "Move closer - face too far";
|
|
688
|
+
readonly move_closer_ideal: "Move a little closer";
|
|
689
|
+
readonly move_back_ideal: "Move back slightly";
|
|
680
690
|
readonly face_not_visible: "Center your face - edges cut off";
|
|
681
691
|
readonly partial_face: "Center your face - edges cut off";
|
|
682
692
|
readonly hold_still: "Hold still - image blurry";
|
|
@@ -684,6 +694,8 @@ declare const FEEDBACK_MESSAGES: {
|
|
|
684
694
|
readonly poor_lighting: "Improve lighting";
|
|
685
695
|
readonly too_dark: "Low lighting - move to a brighter area";
|
|
686
696
|
readonly backlit: "Backlit - try facing the light source";
|
|
697
|
+
readonly phone_angle_low: "Raise your phone to eye level";
|
|
698
|
+
readonly phone_tilted: "Hold your phone level";
|
|
687
699
|
readonly hand_detected: "Remove hand from face";
|
|
688
700
|
readonly eyes_not_visible: "Eyes not clearly visible";
|
|
689
701
|
readonly eyes_shadowed: "Eyes are in shadow - improve lighting";
|
|
@@ -714,6 +726,10 @@ interface CaptureQualityState {
|
|
|
714
726
|
isPartialFace: boolean;
|
|
715
727
|
framesCaptured: number;
|
|
716
728
|
targetFrames: number;
|
|
729
|
+
tooFarFromIdeal?: boolean;
|
|
730
|
+
tooCloseToIdeal?: boolean;
|
|
731
|
+
phoneAngled?: boolean;
|
|
732
|
+
phoneTilted?: boolean;
|
|
717
733
|
}
|
|
718
734
|
declare function getCaptureQualityFeedback(state: CaptureQualityState): string;
|
|
719
735
|
declare function canCaptureFrame(state: Omit<CaptureQualityState, 'framesCaptured' | 'targetFrames' | 'isCapturing'>): boolean;
|
|
@@ -764,4 +780,4 @@ declare function analyzeEyeRegionContrast(pixels: Uint8Array | Uint8ClampedArray
|
|
|
764
780
|
declare function detectSpecularHighlights(pixels: Uint8Array | Uint8ClampedArray, threshold?: number): number;
|
|
765
781
|
declare function checkEyeRegionQuality(pixels: Uint8Array | Uint8ClampedArray, thresholds?: EyeQualityThresholds): EyeRegionQuality;
|
|
766
782
|
|
|
767
|
-
export { ALIGNMENT_THRESHOLD_CAPTURE, ALIGNMENT_THRESHOLD_GOOD, ALIGNMENT_THRESHOLD_PERFECT, ALIGNMENT_THRESHOLD_POOR, API_ENDPOINTS, API_ERROR_CODES, API_PATHS, AUTH_CONFIG, type ApiErrorCode, BACKLIT_RATIO_THRESHOLD, BLUR_THRESHOLD_MOBILE, BaseFrameCollector, type BlurAnalysis, type CaptureQualityState, type CapturedFrame, type CropData, DEFAULT_BLUR_THRESHOLD, DEFAULT_ENDPOINT, DEFAULT_FACE_DETECTION_TIERS, DEFAULT_GAZE_THRESHOLDS, DEFAULT_HAND_OCCLUSION_CONFIG, DEFAULT_LIVENESS_CONFIG, DEFAULT_LOCALE, DEFAULT_OVAL_REGION, DEFAULT_STABILIZER_CONFIG, DEFAULT_STATUS_MESSAGES, type DetectionResult, type DetectionSummary, type DetectorConfig, ERROR_MESSAGES, ERROR_MESSAGES_ES, ES_LOCALE, EYE_LANDMARK_INDICES, EYE_QUALITY_THRESHOLDS, type ErrorResponse, type EyeQualityThresholds, type EyeRegionBounds, type EyeRegionQuality, type EyeRegionsBounds, FACE_CENTER_VERTICAL_OFFSET, FACE_CROP_OUTPUT_SIZE, FEEDBACK_MESSAGES, FRAME_BUFFER_CONFIG, FRAME_CONFIG, type FaceAlignmentResult, type FaceBoundingBox, type FaceDetectionTiers, type FaceInOvalResult, type FaceLandmarkPoint, type FaceVisibilityResult, type FastCheckCropsRequest, type FastCheckModel, type FastCheckRequest, type FastCheckResponse, type FastCheckStreamRequest, type FastCheckStreamResponse, type FeedbackLocale, type FeedbackMessageKey, type Frame, FrameBuffer, type FrameData, type FrameQualityResult, FrameQueue, type FrameSource, GOOD_ALIGNMENT, type GazeThresholds, HIGH_ALIGNMENT, HYBRID_MODEL_CONFIGS, type HandOcclusionConfig, type HeadPose, type HealthResponse, type Hybrid150CheckRequest, type Hybrid50CheckRequest, type HybridCheckRequest, type HybridCheckResponse, type HybridFrameData, type HybridModelConfig, IDEAL_CROP_MULTIPLIER, type JobStatus, type JobStatusResponse, LANDMARK_INDEX, LANDMARK_MAX_BOUND, LANDMARK_MIN_BOUND, LOW_LIGHT_THRESHOLD, type LandmarkValidationResult, type LightingAnalysis, LivenessApiError, type LivenessCallbacks, LivenessClient, type LivenessClientConfig, type LivenessConfig, type LivenessResult, type LivenessState, MAX_CROP_MULTIPLIER, MAX_FACE_PERCENTAGE_IN_CROP, MAX_FACE_RATIO, MIN_CAPTURE_ALIGNMENT, MIN_CROP_MULTIPLIER, MIN_FACE_BOTTOM_MARGIN, MIN_FACE_RATIO, MIN_FACE_SIDE_MARGIN, MIN_FACE_TOP_MARGIN, MIN_LANDMARK_COUNT, MODEL_CONFIGS, type ModelConfig, type ModelEntry, type ModelType, type ModelsResponse, OVAL_GUIDE_COLORS, OVAL_GUIDE_STYLES, OVAL_REGION_DESKTOP, OVAL_REGION_MOBILE, type OnErrorCallback, type OnFrameCapturedCallback, type OnProgressCallback, type OnResultCallback, type OnStateChangeCallback, type OvalGuideState, type OvalRegion, type QueueStatsResponse, RETRY_CONFIG, type RetryOptions, type StabilizationProgress, type StabilizationResult, type StabilizerConfig, type StatusMessageKey, type StreamingStatus, TARGET_FACE_PERCENTAGE_IN_CROP, type Verdict, type VerifyRequest, type VerifyResponse, type VideoFrameMetadata, analyzeBlur, analyzeEyeRegionBrightness, analyzeEyeRegionContrast, analyzeLighting, calculateAdaptiveCropMultiplier, calculateBrightness, calculateFaceAlignment, calculateFaceCropRegion, canCaptureFrame, checkEyeRegionQuality, checkFrameQuality, decodeBase64, detectSpecularHighlights, encodeBase64, generateSessionId, getActiveModels, getApiErrorMessage, getCaptureQualityFeedback, getEyeRegionBounds, getFeedbackMessage, getMinFramesForModel, getOvalGuideState, getStatusMessage, hasEnoughFrames, isDeprecatedModel, isFaceCropFullyInFrame, isFaceFullyVisible, isFaceInOval, isRetryableError, retryWithBackoff, rgbaToGrayscale, sleep, toFrameData, toHybridFrameData, toLivenessResult, toLivenessResultFromStream, validateApiKey, validateFaceLandmarks, validateFrameCount, validateFrameData, validateFrameIndex, validateTimestamp, validateUUID, validateUrl };
|
|
783
|
+
export { ALIGNMENT_THRESHOLD_CAPTURE, ALIGNMENT_THRESHOLD_GOOD, ALIGNMENT_THRESHOLD_PERFECT, ALIGNMENT_THRESHOLD_POOR, API_ENDPOINTS, API_ERROR_CODES, API_PATHS, AUTH_CONFIG, type ApiErrorCode, BACKLIT_RATIO_THRESHOLD, BLUR_THRESHOLD_MOBILE, BaseFrameCollector, type BlurAnalysis, type CaptureQualityState, type CapturedFrame, type CropData, DEFAULT_BLUR_THRESHOLD, DEFAULT_ENDPOINT, DEFAULT_FACE_DETECTION_TIERS, DEFAULT_GAZE_THRESHOLDS, DEFAULT_HAND_OCCLUSION_CONFIG, DEFAULT_LIVENESS_CONFIG, DEFAULT_LOCALE, DEFAULT_OVAL_REGION, DEFAULT_STABILIZER_CONFIG, DEFAULT_STATUS_MESSAGES, type DetectionResult, type DetectionSummary, type DetectorConfig, ERROR_MESSAGES, ERROR_MESSAGES_ES, ES_LOCALE, EYE_LANDMARK_INDICES, EYE_QUALITY_THRESHOLDS, type ErrorResponse, type EyeQualityThresholds, type EyeRegionBounds, type EyeRegionQuality, type EyeRegionsBounds, FACE_CENTER_VERTICAL_OFFSET, FACE_CROP_OUTPUT_SIZE, FEEDBACK_MESSAGES, FRAME_BUFFER_CONFIG, FRAME_CONFIG, type FaceAlignmentResult, type FaceBoundingBox, type FaceDetectionTiers, type FaceInOvalResult, type FaceLandmarkPoint, type FaceRollResult, type FaceVisibilityResult, type FastCheckCropsRequest, type FastCheckModel, type FastCheckRequest, type FastCheckResponse, type FastCheckStreamRequest, type FastCheckStreamResponse, type FeedbackLocale, type FeedbackMessageKey, type Frame, FrameBuffer, type FrameData, type FrameQualityResult, FrameQueue, type FrameSource, GOOD_ALIGNMENT, type GazeThresholds, HIGH_ALIGNMENT, HYBRID_MODEL_CONFIGS, type HandOcclusionConfig, type HeadPose, type HealthResponse, type Hybrid150CheckRequest, type Hybrid50CheckRequest, type HybridCheckRequest, type HybridCheckResponse, type HybridFrameData, type HybridModelConfig, IDEAL_CROP_MULTIPLIER, type JobStatus, type JobStatusResponse, LANDMARK_INDEX, LANDMARK_MAX_BOUND, LANDMARK_MIN_BOUND, LOW_LIGHT_THRESHOLD, type LandmarkValidationResult, type LightingAnalysis, LivenessApiError, type LivenessCallbacks, LivenessClient, type LivenessClientConfig, type LivenessConfig, type LivenessResult, type LivenessState, MAX_CROP_MULTIPLIER, MAX_FACE_PERCENTAGE_IN_CROP, MAX_FACE_RATIO, MAX_FACE_ROLL_DEGREES, MAX_IDEAL_FACE_RATIO, MIN_CAPTURE_ALIGNMENT, MIN_CROP_MULTIPLIER, MIN_FACE_BOTTOM_MARGIN, MIN_FACE_RATIO, MIN_FACE_SIDE_MARGIN, MIN_FACE_TOP_MARGIN, MIN_IDEAL_FACE_RATIO, MIN_LANDMARK_COUNT, MODEL_CONFIGS, type ModelConfig, type ModelEntry, type ModelType, type ModelsResponse, OVAL_GUIDE_COLORS, OVAL_GUIDE_STYLES, OVAL_REGION_DESKTOP, OVAL_REGION_MOBILE, type OnErrorCallback, type OnFrameCapturedCallback, type OnProgressCallback, type OnResultCallback, type OnStateChangeCallback, type OvalGuideState, type OvalRegion, type QueueStatsResponse, RETRY_CONFIG, type RetryOptions, type StabilizationProgress, type StabilizationResult, type StabilizerConfig, type StatusMessageKey, type StreamingStatus, TARGET_FACE_PERCENTAGE_IN_CROP, type Verdict, type VerifyRequest, type VerifyResponse, type VideoFrameMetadata, analyzeBlur, analyzeEyeRegionBrightness, analyzeEyeRegionContrast, analyzeLighting, calculateAdaptiveCropMultiplier, calculateBrightness, calculateFaceAlignment, calculateFaceCropRegion, canCaptureFrame, checkEyeRegionQuality, checkFrameQuality, decodeBase64, detectFaceRoll, detectSpecularHighlights, encodeBase64, generateSessionId, getActiveModels, getApiErrorMessage, getCaptureQualityFeedback, getEyeRegionBounds, getFeedbackMessage, getMinFramesForModel, getOvalGuideState, getStatusMessage, hasEnoughFrames, isDeprecatedModel, isFaceCropFullyInFrame, isFaceFullyVisible, isFaceInOval, isRetryableError, retryWithBackoff, rgbaToGrayscale, sleep, toFrameData, toHybridFrameData, toLivenessResult, toLivenessResultFromStream, validateApiKey, validateFaceLandmarks, validateFrameCount, validateFrameData, validateFrameIndex, validateTimestamp, validateUUID, validateUrl };
|
package/dist/index.js
CHANGED
|
@@ -66,12 +66,15 @@ __export(index_exports, {
|
|
|
66
66
|
MAX_CROP_MULTIPLIER: () => MAX_CROP_MULTIPLIER,
|
|
67
67
|
MAX_FACE_PERCENTAGE_IN_CROP: () => MAX_FACE_PERCENTAGE_IN_CROP,
|
|
68
68
|
MAX_FACE_RATIO: () => MAX_FACE_RATIO,
|
|
69
|
+
MAX_FACE_ROLL_DEGREES: () => MAX_FACE_ROLL_DEGREES,
|
|
70
|
+
MAX_IDEAL_FACE_RATIO: () => MAX_IDEAL_FACE_RATIO,
|
|
69
71
|
MIN_CAPTURE_ALIGNMENT: () => MIN_CAPTURE_ALIGNMENT,
|
|
70
72
|
MIN_CROP_MULTIPLIER: () => MIN_CROP_MULTIPLIER,
|
|
71
73
|
MIN_FACE_BOTTOM_MARGIN: () => MIN_FACE_BOTTOM_MARGIN,
|
|
72
74
|
MIN_FACE_RATIO: () => MIN_FACE_RATIO,
|
|
73
75
|
MIN_FACE_SIDE_MARGIN: () => MIN_FACE_SIDE_MARGIN,
|
|
74
76
|
MIN_FACE_TOP_MARGIN: () => MIN_FACE_TOP_MARGIN,
|
|
77
|
+
MIN_IDEAL_FACE_RATIO: () => MIN_IDEAL_FACE_RATIO,
|
|
75
78
|
MIN_LANDMARK_COUNT: () => MIN_LANDMARK_COUNT,
|
|
76
79
|
MODEL_CONFIGS: () => MODEL_CONFIGS,
|
|
77
80
|
OVAL_GUIDE_COLORS: () => OVAL_GUIDE_COLORS,
|
|
@@ -92,6 +95,7 @@ __export(index_exports, {
|
|
|
92
95
|
checkEyeRegionQuality: () => checkEyeRegionQuality,
|
|
93
96
|
checkFrameQuality: () => checkFrameQuality,
|
|
94
97
|
decodeBase64: () => decodeBase64,
|
|
98
|
+
detectFaceRoll: () => detectFaceRoll,
|
|
95
99
|
detectSpecularHighlights: () => detectSpecularHighlights,
|
|
96
100
|
encodeBase64: () => encodeBase64,
|
|
97
101
|
generateSessionId: () => generateSessionId,
|
|
@@ -1177,7 +1181,7 @@ function isRetryableError(code) {
|
|
|
1177
1181
|
}
|
|
1178
1182
|
|
|
1179
1183
|
// src/constants/feedback.ts
|
|
1180
|
-
var ALIGNMENT_THRESHOLD_CAPTURE = 0.
|
|
1184
|
+
var ALIGNMENT_THRESHOLD_CAPTURE = 0.85;
|
|
1181
1185
|
var ALIGNMENT_THRESHOLD_POOR = 0.6;
|
|
1182
1186
|
var ALIGNMENT_THRESHOLD_GOOD = 0.6;
|
|
1183
1187
|
var ALIGNMENT_THRESHOLD_PERFECT = 0.85;
|
|
@@ -1230,6 +1234,8 @@ var FEEDBACK_MESSAGES = {
|
|
|
1230
1234
|
move_back: "Move back - face too close",
|
|
1231
1235
|
too_close: "Move back - face too close",
|
|
1232
1236
|
too_far: "Move closer - face too far",
|
|
1237
|
+
move_closer_ideal: "Move a little closer",
|
|
1238
|
+
move_back_ideal: "Move back slightly",
|
|
1233
1239
|
// Visibility issues
|
|
1234
1240
|
face_not_visible: "Center your face - edges cut off",
|
|
1235
1241
|
partial_face: "Center your face - edges cut off",
|
|
@@ -1240,6 +1246,9 @@ var FEEDBACK_MESSAGES = {
|
|
|
1240
1246
|
poor_lighting: "Improve lighting",
|
|
1241
1247
|
too_dark: "Low lighting - move to a brighter area",
|
|
1242
1248
|
backlit: "Backlit - try facing the light source",
|
|
1249
|
+
// Phone orientation
|
|
1250
|
+
phone_angle_low: "Raise your phone to eye level",
|
|
1251
|
+
phone_tilted: "Hold your phone level",
|
|
1243
1252
|
// Hand occlusion
|
|
1244
1253
|
hand_detected: "Remove hand from face",
|
|
1245
1254
|
// Eye region quality
|
|
@@ -1287,6 +1296,8 @@ var ES_LOCALE = {
|
|
|
1287
1296
|
move_back: "Al\xE9jate - rostro muy cerca",
|
|
1288
1297
|
too_close: "Al\xE9jate - rostro muy cerca",
|
|
1289
1298
|
too_far: "Ac\xE9rcate - rostro muy lejos",
|
|
1299
|
+
move_closer_ideal: "Ac\xE9rcate un poco",
|
|
1300
|
+
move_back_ideal: "Al\xE9jate un poco",
|
|
1290
1301
|
// Visibility issues
|
|
1291
1302
|
face_not_visible: "Centra tu rostro - bordes cortados",
|
|
1292
1303
|
partial_face: "Centra tu rostro - bordes cortados",
|
|
@@ -1297,6 +1308,9 @@ var ES_LOCALE = {
|
|
|
1297
1308
|
poor_lighting: "Mejora la iluminaci\xF3n",
|
|
1298
1309
|
too_dark: "Poca luz - mu\xE9vete a un \xE1rea m\xE1s iluminada",
|
|
1299
1310
|
backlit: "Contraluz - intenta mirar hacia la fuente de luz",
|
|
1311
|
+
// Phone orientation
|
|
1312
|
+
phone_angle_low: "Levanta el tel\xE9fono a la altura de los ojos",
|
|
1313
|
+
phone_tilted: "Mant\xE9n el tel\xE9fono nivelado",
|
|
1300
1314
|
// Hand occlusion
|
|
1301
1315
|
hand_detected: "Retira la mano del rostro",
|
|
1302
1316
|
// Eye region quality
|
|
@@ -1329,11 +1343,21 @@ function getCaptureQualityFeedback(state) {
|
|
|
1329
1343
|
isBlurry,
|
|
1330
1344
|
isPartialFace,
|
|
1331
1345
|
framesCaptured,
|
|
1332
|
-
targetFrames
|
|
1346
|
+
targetFrames,
|
|
1347
|
+
tooFarFromIdeal,
|
|
1348
|
+
tooCloseToIdeal,
|
|
1349
|
+
phoneAngled,
|
|
1350
|
+
phoneTilted
|
|
1333
1351
|
} = state;
|
|
1334
1352
|
if (!hasFace) {
|
|
1335
1353
|
return FEEDBACK_MESSAGES.no_face;
|
|
1336
1354
|
}
|
|
1355
|
+
if (phoneTilted) {
|
|
1356
|
+
return FEEDBACK_MESSAGES.phone_tilted;
|
|
1357
|
+
}
|
|
1358
|
+
if (phoneAngled) {
|
|
1359
|
+
return FEEDBACK_MESSAGES.phone_angle_low;
|
|
1360
|
+
}
|
|
1337
1361
|
if (tooClose) {
|
|
1338
1362
|
return FEEDBACK_MESSAGES.too_close;
|
|
1339
1363
|
}
|
|
@@ -1346,6 +1370,12 @@ function getCaptureQualityFeedback(state) {
|
|
|
1346
1370
|
if (isBlurry) {
|
|
1347
1371
|
return FEEDBACK_MESSAGES.blurry;
|
|
1348
1372
|
}
|
|
1373
|
+
if (tooFarFromIdeal) {
|
|
1374
|
+
return FEEDBACK_MESSAGES.move_closer_ideal;
|
|
1375
|
+
}
|
|
1376
|
+
if (tooCloseToIdeal) {
|
|
1377
|
+
return FEEDBACK_MESSAGES.move_back_ideal;
|
|
1378
|
+
}
|
|
1349
1379
|
if (alignment < ALIGNMENT_THRESHOLD_POOR) {
|
|
1350
1380
|
return FEEDBACK_MESSAGES.move_closer_to_center;
|
|
1351
1381
|
}
|
|
@@ -1361,8 +1391,19 @@ function getCaptureQualityFeedback(state) {
|
|
|
1361
1391
|
return FEEDBACK_MESSAGES.perfect;
|
|
1362
1392
|
}
|
|
1363
1393
|
function canCaptureFrame(state) {
|
|
1364
|
-
const {
|
|
1365
|
-
|
|
1394
|
+
const {
|
|
1395
|
+
hasFace,
|
|
1396
|
+
alignment,
|
|
1397
|
+
tooClose,
|
|
1398
|
+
tooFar,
|
|
1399
|
+
isBlurry,
|
|
1400
|
+
isPartialFace,
|
|
1401
|
+
tooFarFromIdeal,
|
|
1402
|
+
tooCloseToIdeal,
|
|
1403
|
+
phoneAngled,
|
|
1404
|
+
phoneTilted
|
|
1405
|
+
} = state;
|
|
1406
|
+
return hasFace && alignment >= ALIGNMENT_THRESHOLD_CAPTURE && !tooClose && !tooFar && !isBlurry && !isPartialFace && !tooFarFromIdeal && !tooCloseToIdeal && !phoneAngled && !phoneTilted;
|
|
1366
1407
|
}
|
|
1367
1408
|
|
|
1368
1409
|
// src/utils/validators.ts
|
|
@@ -1439,15 +1480,17 @@ var MIN_FACE_SIDE_MARGIN = 0.05;
|
|
|
1439
1480
|
var MIN_CAPTURE_ALIGNMENT = 0.6;
|
|
1440
1481
|
var HIGH_ALIGNMENT = 0.85;
|
|
1441
1482
|
var GOOD_ALIGNMENT = 0.5;
|
|
1442
|
-
var IDEAL_CROP_MULTIPLIER =
|
|
1443
|
-
var MIN_CROP_MULTIPLIER =
|
|
1444
|
-
var MAX_CROP_MULTIPLIER =
|
|
1483
|
+
var IDEAL_CROP_MULTIPLIER = 3;
|
|
1484
|
+
var MIN_CROP_MULTIPLIER = 2.5;
|
|
1485
|
+
var MAX_CROP_MULTIPLIER = 4;
|
|
1445
1486
|
var FACE_CENTER_VERTICAL_OFFSET = 0.05;
|
|
1487
|
+
var MIN_IDEAL_FACE_RATIO = 0.05;
|
|
1488
|
+
var MAX_IDEAL_FACE_RATIO = 0.2;
|
|
1446
1489
|
var MIN_FACE_RATIO = 0.036;
|
|
1447
1490
|
var MAX_FACE_RATIO = 0.7;
|
|
1448
1491
|
var FACE_CROP_OUTPUT_SIZE = 224;
|
|
1449
|
-
var MAX_FACE_PERCENTAGE_IN_CROP = 0.
|
|
1450
|
-
var TARGET_FACE_PERCENTAGE_IN_CROP = 0.
|
|
1492
|
+
var MAX_FACE_PERCENTAGE_IN_CROP = 0.45;
|
|
1493
|
+
var TARGET_FACE_PERCENTAGE_IN_CROP = 0.33;
|
|
1451
1494
|
function analyzeBlur(grayscalePixels, width, height, threshold = DEFAULT_BLUR_THRESHOLD) {
|
|
1452
1495
|
const laplacian = [];
|
|
1453
1496
|
for (let y = 1; y < height - 1; y++) {
|
|
@@ -1543,9 +1586,9 @@ var OVAL_REGION_DESKTOP = {
|
|
|
1543
1586
|
var OVAL_REGION_MOBILE = {
|
|
1544
1587
|
centerX: 0.5,
|
|
1545
1588
|
centerY: 0.5,
|
|
1546
|
-
width: 0.
|
|
1547
|
-
height: 0.
|
|
1548
|
-
// 0.
|
|
1589
|
+
width: 0.48,
|
|
1590
|
+
height: 0.64
|
|
1591
|
+
// 0.48 * (4/3)
|
|
1549
1592
|
};
|
|
1550
1593
|
var DEFAULT_OVAL_REGION = OVAL_REGION_DESKTOP;
|
|
1551
1594
|
function isFaceInOval(faceBox, frameWidth, frameHeight, oval = DEFAULT_OVAL_REGION, tolerance = 0.3) {
|
|
@@ -1701,6 +1744,33 @@ function checkFrameQuality(options) {
|
|
|
1701
1744
|
}
|
|
1702
1745
|
return result;
|
|
1703
1746
|
}
|
|
1747
|
+
var MAX_FACE_ROLL_DEGREES = 15;
|
|
1748
|
+
function detectFaceRoll(landmarks) {
|
|
1749
|
+
if (landmarks.length < 364) {
|
|
1750
|
+
return { roll: 0, tooTilted: false };
|
|
1751
|
+
}
|
|
1752
|
+
const l33 = landmarks[33];
|
|
1753
|
+
const l133 = landmarks[133];
|
|
1754
|
+
const l362 = landmarks[362];
|
|
1755
|
+
const l263 = landmarks[263];
|
|
1756
|
+
if (!l33 || !l133 || !l362 || !l263) {
|
|
1757
|
+
return { roll: 0, tooTilted: false };
|
|
1758
|
+
}
|
|
1759
|
+
const leftEyeX = (l33.x + l133.x) / 2;
|
|
1760
|
+
const leftEyeY = (l33.y + l133.y) / 2;
|
|
1761
|
+
const rightEyeX = (l362.x + l263.x) / 2;
|
|
1762
|
+
const rightEyeY = (l362.y + l263.y) / 2;
|
|
1763
|
+
const eyeXDist = Math.abs(leftEyeX - rightEyeX);
|
|
1764
|
+
const eyeYDiff = Math.abs(leftEyeY - rightEyeY);
|
|
1765
|
+
if (eyeXDist < 0.01) {
|
|
1766
|
+
return { roll: 0, tooTilted: false };
|
|
1767
|
+
}
|
|
1768
|
+
const roll = Math.atan2(eyeYDiff, eyeXDist) * (180 / Math.PI);
|
|
1769
|
+
return {
|
|
1770
|
+
roll,
|
|
1771
|
+
tooTilted: roll > MAX_FACE_ROLL_DEGREES
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
1704
1774
|
var BaseFrameCollector = class {
|
|
1705
1775
|
constructor(maxFrames = 10) {
|
|
1706
1776
|
this.frames = [];
|
|
@@ -1961,12 +2031,15 @@ function checkEyeRegionQuality(pixels, thresholds = EYE_QUALITY_THRESHOLDS) {
|
|
|
1961
2031
|
MAX_CROP_MULTIPLIER,
|
|
1962
2032
|
MAX_FACE_PERCENTAGE_IN_CROP,
|
|
1963
2033
|
MAX_FACE_RATIO,
|
|
2034
|
+
MAX_FACE_ROLL_DEGREES,
|
|
2035
|
+
MAX_IDEAL_FACE_RATIO,
|
|
1964
2036
|
MIN_CAPTURE_ALIGNMENT,
|
|
1965
2037
|
MIN_CROP_MULTIPLIER,
|
|
1966
2038
|
MIN_FACE_BOTTOM_MARGIN,
|
|
1967
2039
|
MIN_FACE_RATIO,
|
|
1968
2040
|
MIN_FACE_SIDE_MARGIN,
|
|
1969
2041
|
MIN_FACE_TOP_MARGIN,
|
|
2042
|
+
MIN_IDEAL_FACE_RATIO,
|
|
1970
2043
|
MIN_LANDMARK_COUNT,
|
|
1971
2044
|
MODEL_CONFIGS,
|
|
1972
2045
|
OVAL_GUIDE_COLORS,
|
|
@@ -1987,6 +2060,7 @@ function checkEyeRegionQuality(pixels, thresholds = EYE_QUALITY_THRESHOLDS) {
|
|
|
1987
2060
|
checkEyeRegionQuality,
|
|
1988
2061
|
checkFrameQuality,
|
|
1989
2062
|
decodeBase64,
|
|
2063
|
+
detectFaceRoll,
|
|
1990
2064
|
detectSpecularHighlights,
|
|
1991
2065
|
encodeBase64,
|
|
1992
2066
|
generateSessionId,
|
package/dist/index.mjs
CHANGED
|
@@ -1048,7 +1048,7 @@ function isRetryableError(code) {
|
|
|
1048
1048
|
}
|
|
1049
1049
|
|
|
1050
1050
|
// src/constants/feedback.ts
|
|
1051
|
-
var ALIGNMENT_THRESHOLD_CAPTURE = 0.
|
|
1051
|
+
var ALIGNMENT_THRESHOLD_CAPTURE = 0.85;
|
|
1052
1052
|
var ALIGNMENT_THRESHOLD_POOR = 0.6;
|
|
1053
1053
|
var ALIGNMENT_THRESHOLD_GOOD = 0.6;
|
|
1054
1054
|
var ALIGNMENT_THRESHOLD_PERFECT = 0.85;
|
|
@@ -1101,6 +1101,8 @@ var FEEDBACK_MESSAGES = {
|
|
|
1101
1101
|
move_back: "Move back - face too close",
|
|
1102
1102
|
too_close: "Move back - face too close",
|
|
1103
1103
|
too_far: "Move closer - face too far",
|
|
1104
|
+
move_closer_ideal: "Move a little closer",
|
|
1105
|
+
move_back_ideal: "Move back slightly",
|
|
1104
1106
|
// Visibility issues
|
|
1105
1107
|
face_not_visible: "Center your face - edges cut off",
|
|
1106
1108
|
partial_face: "Center your face - edges cut off",
|
|
@@ -1111,6 +1113,9 @@ var FEEDBACK_MESSAGES = {
|
|
|
1111
1113
|
poor_lighting: "Improve lighting",
|
|
1112
1114
|
too_dark: "Low lighting - move to a brighter area",
|
|
1113
1115
|
backlit: "Backlit - try facing the light source",
|
|
1116
|
+
// Phone orientation
|
|
1117
|
+
phone_angle_low: "Raise your phone to eye level",
|
|
1118
|
+
phone_tilted: "Hold your phone level",
|
|
1114
1119
|
// Hand occlusion
|
|
1115
1120
|
hand_detected: "Remove hand from face",
|
|
1116
1121
|
// Eye region quality
|
|
@@ -1158,6 +1163,8 @@ var ES_LOCALE = {
|
|
|
1158
1163
|
move_back: "Al\xE9jate - rostro muy cerca",
|
|
1159
1164
|
too_close: "Al\xE9jate - rostro muy cerca",
|
|
1160
1165
|
too_far: "Ac\xE9rcate - rostro muy lejos",
|
|
1166
|
+
move_closer_ideal: "Ac\xE9rcate un poco",
|
|
1167
|
+
move_back_ideal: "Al\xE9jate un poco",
|
|
1161
1168
|
// Visibility issues
|
|
1162
1169
|
face_not_visible: "Centra tu rostro - bordes cortados",
|
|
1163
1170
|
partial_face: "Centra tu rostro - bordes cortados",
|
|
@@ -1168,6 +1175,9 @@ var ES_LOCALE = {
|
|
|
1168
1175
|
poor_lighting: "Mejora la iluminaci\xF3n",
|
|
1169
1176
|
too_dark: "Poca luz - mu\xE9vete a un \xE1rea m\xE1s iluminada",
|
|
1170
1177
|
backlit: "Contraluz - intenta mirar hacia la fuente de luz",
|
|
1178
|
+
// Phone orientation
|
|
1179
|
+
phone_angle_low: "Levanta el tel\xE9fono a la altura de los ojos",
|
|
1180
|
+
phone_tilted: "Mant\xE9n el tel\xE9fono nivelado",
|
|
1171
1181
|
// Hand occlusion
|
|
1172
1182
|
hand_detected: "Retira la mano del rostro",
|
|
1173
1183
|
// Eye region quality
|
|
@@ -1200,11 +1210,21 @@ function getCaptureQualityFeedback(state) {
|
|
|
1200
1210
|
isBlurry,
|
|
1201
1211
|
isPartialFace,
|
|
1202
1212
|
framesCaptured,
|
|
1203
|
-
targetFrames
|
|
1213
|
+
targetFrames,
|
|
1214
|
+
tooFarFromIdeal,
|
|
1215
|
+
tooCloseToIdeal,
|
|
1216
|
+
phoneAngled,
|
|
1217
|
+
phoneTilted
|
|
1204
1218
|
} = state;
|
|
1205
1219
|
if (!hasFace) {
|
|
1206
1220
|
return FEEDBACK_MESSAGES.no_face;
|
|
1207
1221
|
}
|
|
1222
|
+
if (phoneTilted) {
|
|
1223
|
+
return FEEDBACK_MESSAGES.phone_tilted;
|
|
1224
|
+
}
|
|
1225
|
+
if (phoneAngled) {
|
|
1226
|
+
return FEEDBACK_MESSAGES.phone_angle_low;
|
|
1227
|
+
}
|
|
1208
1228
|
if (tooClose) {
|
|
1209
1229
|
return FEEDBACK_MESSAGES.too_close;
|
|
1210
1230
|
}
|
|
@@ -1217,6 +1237,12 @@ function getCaptureQualityFeedback(state) {
|
|
|
1217
1237
|
if (isBlurry) {
|
|
1218
1238
|
return FEEDBACK_MESSAGES.blurry;
|
|
1219
1239
|
}
|
|
1240
|
+
if (tooFarFromIdeal) {
|
|
1241
|
+
return FEEDBACK_MESSAGES.move_closer_ideal;
|
|
1242
|
+
}
|
|
1243
|
+
if (tooCloseToIdeal) {
|
|
1244
|
+
return FEEDBACK_MESSAGES.move_back_ideal;
|
|
1245
|
+
}
|
|
1220
1246
|
if (alignment < ALIGNMENT_THRESHOLD_POOR) {
|
|
1221
1247
|
return FEEDBACK_MESSAGES.move_closer_to_center;
|
|
1222
1248
|
}
|
|
@@ -1232,8 +1258,19 @@ function getCaptureQualityFeedback(state) {
|
|
|
1232
1258
|
return FEEDBACK_MESSAGES.perfect;
|
|
1233
1259
|
}
|
|
1234
1260
|
function canCaptureFrame(state) {
|
|
1235
|
-
const {
|
|
1236
|
-
|
|
1261
|
+
const {
|
|
1262
|
+
hasFace,
|
|
1263
|
+
alignment,
|
|
1264
|
+
tooClose,
|
|
1265
|
+
tooFar,
|
|
1266
|
+
isBlurry,
|
|
1267
|
+
isPartialFace,
|
|
1268
|
+
tooFarFromIdeal,
|
|
1269
|
+
tooCloseToIdeal,
|
|
1270
|
+
phoneAngled,
|
|
1271
|
+
phoneTilted
|
|
1272
|
+
} = state;
|
|
1273
|
+
return hasFace && alignment >= ALIGNMENT_THRESHOLD_CAPTURE && !tooClose && !tooFar && !isBlurry && !isPartialFace && !tooFarFromIdeal && !tooCloseToIdeal && !phoneAngled && !phoneTilted;
|
|
1237
1274
|
}
|
|
1238
1275
|
|
|
1239
1276
|
// src/utils/validators.ts
|
|
@@ -1310,15 +1347,17 @@ var MIN_FACE_SIDE_MARGIN = 0.05;
|
|
|
1310
1347
|
var MIN_CAPTURE_ALIGNMENT = 0.6;
|
|
1311
1348
|
var HIGH_ALIGNMENT = 0.85;
|
|
1312
1349
|
var GOOD_ALIGNMENT = 0.5;
|
|
1313
|
-
var IDEAL_CROP_MULTIPLIER =
|
|
1314
|
-
var MIN_CROP_MULTIPLIER =
|
|
1315
|
-
var MAX_CROP_MULTIPLIER =
|
|
1350
|
+
var IDEAL_CROP_MULTIPLIER = 3;
|
|
1351
|
+
var MIN_CROP_MULTIPLIER = 2.5;
|
|
1352
|
+
var MAX_CROP_MULTIPLIER = 4;
|
|
1316
1353
|
var FACE_CENTER_VERTICAL_OFFSET = 0.05;
|
|
1354
|
+
var MIN_IDEAL_FACE_RATIO = 0.05;
|
|
1355
|
+
var MAX_IDEAL_FACE_RATIO = 0.2;
|
|
1317
1356
|
var MIN_FACE_RATIO = 0.036;
|
|
1318
1357
|
var MAX_FACE_RATIO = 0.7;
|
|
1319
1358
|
var FACE_CROP_OUTPUT_SIZE = 224;
|
|
1320
|
-
var MAX_FACE_PERCENTAGE_IN_CROP = 0.
|
|
1321
|
-
var TARGET_FACE_PERCENTAGE_IN_CROP = 0.
|
|
1359
|
+
var MAX_FACE_PERCENTAGE_IN_CROP = 0.45;
|
|
1360
|
+
var TARGET_FACE_PERCENTAGE_IN_CROP = 0.33;
|
|
1322
1361
|
function analyzeBlur(grayscalePixels, width, height, threshold = DEFAULT_BLUR_THRESHOLD) {
|
|
1323
1362
|
const laplacian = [];
|
|
1324
1363
|
for (let y = 1; y < height - 1; y++) {
|
|
@@ -1414,9 +1453,9 @@ var OVAL_REGION_DESKTOP = {
|
|
|
1414
1453
|
var OVAL_REGION_MOBILE = {
|
|
1415
1454
|
centerX: 0.5,
|
|
1416
1455
|
centerY: 0.5,
|
|
1417
|
-
width: 0.
|
|
1418
|
-
height: 0.
|
|
1419
|
-
// 0.
|
|
1456
|
+
width: 0.48,
|
|
1457
|
+
height: 0.64
|
|
1458
|
+
// 0.48 * (4/3)
|
|
1420
1459
|
};
|
|
1421
1460
|
var DEFAULT_OVAL_REGION = OVAL_REGION_DESKTOP;
|
|
1422
1461
|
function isFaceInOval(faceBox, frameWidth, frameHeight, oval = DEFAULT_OVAL_REGION, tolerance = 0.3) {
|
|
@@ -1572,6 +1611,33 @@ function checkFrameQuality(options) {
|
|
|
1572
1611
|
}
|
|
1573
1612
|
return result;
|
|
1574
1613
|
}
|
|
1614
|
+
var MAX_FACE_ROLL_DEGREES = 15;
|
|
1615
|
+
function detectFaceRoll(landmarks) {
|
|
1616
|
+
if (landmarks.length < 364) {
|
|
1617
|
+
return { roll: 0, tooTilted: false };
|
|
1618
|
+
}
|
|
1619
|
+
const l33 = landmarks[33];
|
|
1620
|
+
const l133 = landmarks[133];
|
|
1621
|
+
const l362 = landmarks[362];
|
|
1622
|
+
const l263 = landmarks[263];
|
|
1623
|
+
if (!l33 || !l133 || !l362 || !l263) {
|
|
1624
|
+
return { roll: 0, tooTilted: false };
|
|
1625
|
+
}
|
|
1626
|
+
const leftEyeX = (l33.x + l133.x) / 2;
|
|
1627
|
+
const leftEyeY = (l33.y + l133.y) / 2;
|
|
1628
|
+
const rightEyeX = (l362.x + l263.x) / 2;
|
|
1629
|
+
const rightEyeY = (l362.y + l263.y) / 2;
|
|
1630
|
+
const eyeXDist = Math.abs(leftEyeX - rightEyeX);
|
|
1631
|
+
const eyeYDiff = Math.abs(leftEyeY - rightEyeY);
|
|
1632
|
+
if (eyeXDist < 0.01) {
|
|
1633
|
+
return { roll: 0, tooTilted: false };
|
|
1634
|
+
}
|
|
1635
|
+
const roll = Math.atan2(eyeYDiff, eyeXDist) * (180 / Math.PI);
|
|
1636
|
+
return {
|
|
1637
|
+
roll,
|
|
1638
|
+
tooTilted: roll > MAX_FACE_ROLL_DEGREES
|
|
1639
|
+
};
|
|
1640
|
+
}
|
|
1575
1641
|
var BaseFrameCollector = class {
|
|
1576
1642
|
constructor(maxFrames = 10) {
|
|
1577
1643
|
this.frames = [];
|
|
@@ -1831,12 +1897,15 @@ export {
|
|
|
1831
1897
|
MAX_CROP_MULTIPLIER,
|
|
1832
1898
|
MAX_FACE_PERCENTAGE_IN_CROP,
|
|
1833
1899
|
MAX_FACE_RATIO,
|
|
1900
|
+
MAX_FACE_ROLL_DEGREES,
|
|
1901
|
+
MAX_IDEAL_FACE_RATIO,
|
|
1834
1902
|
MIN_CAPTURE_ALIGNMENT,
|
|
1835
1903
|
MIN_CROP_MULTIPLIER,
|
|
1836
1904
|
MIN_FACE_BOTTOM_MARGIN,
|
|
1837
1905
|
MIN_FACE_RATIO,
|
|
1838
1906
|
MIN_FACE_SIDE_MARGIN,
|
|
1839
1907
|
MIN_FACE_TOP_MARGIN,
|
|
1908
|
+
MIN_IDEAL_FACE_RATIO,
|
|
1840
1909
|
MIN_LANDMARK_COUNT,
|
|
1841
1910
|
MODEL_CONFIGS,
|
|
1842
1911
|
OVAL_GUIDE_COLORS,
|
|
@@ -1857,6 +1926,7 @@ export {
|
|
|
1857
1926
|
checkEyeRegionQuality,
|
|
1858
1927
|
checkFrameQuality,
|
|
1859
1928
|
decodeBase64,
|
|
1929
|
+
detectFaceRoll,
|
|
1860
1930
|
detectSpecularHighlights,
|
|
1861
1931
|
encodeBase64,
|
|
1862
1932
|
generateSessionId,
|